【opencv】pytorch->onnx->opencv模型推理

10 篇文章 1 订阅
2 篇文章 0 订阅

opencv的DNN推理模块是不直接支持pytorch训练出来的pth文件。一般来说,可以将pth文件转成onnx格式,再用opencv调用onnx文件,即可实现推理。
pth文件转onnx文件时,因为onnx对于pth中某些定义的层是不支持的,难免会碰到一些问题。近期,对一些分割网络进行了部署,碰到的一些问题记录在下。

  • RuntimeError: ONNX export failed: Couldn’t export operator aten::adaptive_avg_pool2d
    onnx不支持pytorch中的nn.AdaptiveAvgPool2d(),需要改成普通的nn.AvgPool2d()。修改之后不会对网络精度造成很大的影响。据了解,nn.AdaptiveAvgPool2d()的kernel大小是自适应变化的,stride也是自适应的,转成普通的nn.AvgPool2d就要自己计算kernel大小和stride,计算公式如下:

    stride = floor ( (input_size / (output_size) )
    kernel_size = input_size − (output_size−1) * stride 
    

    参考:https://www.cnblogs.com/xiaosongshine/p/10750908.html

  • RuntimeError: Failed to export an ONNX attribute, since it’s not constant, please try to make things (e.g., kernel size) static if possible
    说明pytorch模型中有些层的参数是变量,onnx识别不了,需要改成常量。

        def pool(self, x, size):
            th, tw = size, size
            xh, xw = x.size()[2:]
            stride_h = xh // th
            stride_w = xw // tw
            kernel_h = xh - (th - 1) * stride_h
            kernel_w = xw - (tw - 1) * stride_w
            avgpool = nn.AvgPool2d((kernel_h, kernel_w), stride=(stride_h, stride_w))
            # avgpool = nn.AdaptiveAvgPool2d(size)
            return avgpool(x)
    

    通过调试xxxxxxxxxx/python3.6/site-packages/torch/onnx/symbolic_helper.py发现,我的池化层kernel_h、kernel_w是变量,onnx不认可。因此,将其改成固定的阿拉伯数字。

  • RuntimeError: ONNX export failed: Couldn’t export operator aten::upsample_bilinear2d
    onnx不支持aten::upsample_bilinear2d。
    解决办法:

    1. pytorch版本升级至1.3+,转onnx的时候设置opset_version=11
          torch_out = torch.onnx._export(net, inputs, output_onnx, export_params=True, verbose=True,
                                         input_names=input_names, output_names=output_names, opset_version=11)
      
      2.如果第一种不行,就修改上采样层的模式为nearest,不过这样会对模型的效果打一些折扣。
      x = F.interpolate(x, size,   mode='bilinear', align_corners=True)			
      # 修改为model=‘nearest’		
      x = F.interpolate(x, size,   mode='nearest')	
      
  • opencv读取onnx失败

    net = cv2.dnn.readNetFromONNX('./fastscnn_citys.onnx')
    

    上述代码读取onnx文件,出现以下报错

    cv2.error: OpenCV(4.4.0) /tmp/pip-req-build-qacpj5ci/opencv/modules/dnn/src/onnx/onnx_importer.cpp:1410: error: (-2:Unspecified error) in function 'void cv::dnn::dnn4_v20200609::ONNXImporter::populateNet(cv::dnn::dnn4_v20200609::Net)'
    >  (expected: 'shapes.depth() == CV_32S'), where
    >     'shapes.depth()' is 5 (CV_32FC1)
    > must be equal to
    >     'CV_32S' is 4 (CV_32SC1)
    

    暂不知道是什么原因造成的,据说是Upsampling层造成的;将opencv版本升级至4.5+,bug消失。

  • Can’t create layer “122” of type “ReduceL2” in function 'getLayerInstance’
    例如我的网络中其中有一层是对张量进行归一化:

            dn = torch.norm(desc, p=2, dim=1)   # 在dim=1维计算二范数 [1, 256, 30, 60]-->[1, 30, 60]
            desc = desc.div(torch.unsqueeze(dn, 1))  
    

    转成onnx之后用opencv进行推理,出现对ReduceL2未识别的错误;对层进行修改,如下即可:

            dn = torch.norm(desc, p=2, dim=1, keepdim=True)   #在dim=1维计算二范数 [1, 256, 30, 60]-->[1, 1, 30, 60]
            desc = desc.div(dn)     # Divide by norm to normalize. [1, 256, 30, 60]
    
  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值