2023年11月29日发(作者:)
【opencv】pytorch->onnx->opencv模型推理
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中的veAvgPool2d(),需要改成普通的l2d()。修改之后不会对⽹络精度造成很⼤的影响。
据了解,veAvgPool2d()的kernel⼤⼩是⾃适应变化的,stride也是⾃适应的,转成普通的l2d就要⾃⼰计算
kernel⼤⼩和stride,计算公式如下:
stride = floor ( (input_size / (output_size) )
kernel_size = input_size − (output_size−1) * stride
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 = veAvgPool2d(size)
return avgpool(x)
通过调试发现,我的池化层kernel_h、kernel_w是变
xxxxxxxxxx/python3.6/site-packages/torch/onnx/symbolic_
量,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_')
上述代码读取onnx⽂件,出现以下报错
: OpenCV(4.4.0) /tmp/pip-req-build-qacpj5ci/opencv/modules/dnn/src/onnx/onnx_:1410: error: (-2:Unspecified error) in function '
void cv::dnn::dnn4_v20200609::ONNXImporter::populateNet(cv::dnn::dnn4_v20200609::Net)'
> (expected: '() == CV_32S'), where
> '()' 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]


发布评论