关于cv2.dnn.readNetFromONNX(path)就报ERROR during processing node with 3 inputs and 1 outputs的解决过程【独家发布】

问题是什么:

如图,对vgg16使用opencv的dnn模块进行推理时出现错误。

错误的详细日志为:

[ERROR:0@0.804] global D:\a\opencv-python\opencv-python\opencv\modules\dnn\src\onnx\onnx_importer.cpp (1021) cv::dnn::dnn4_v20220524::ONNXImporter::handleNode DNN/ONNX: ERROR during processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/vgg16/conv_bn_two_relu_pool1/conv_bn_one_relu/conv2d/Conv2D) from domain='ai.onnx'
Traceback (most recent call last):
  File "D:/DLAI/qwenAILearn/StudyDNN/trainOnnx/test2.py", line 6, in <module>
    net = cv2.dnn.readNetFromONNX(path)  # 加载训练好的识别模型
cv2.error: OpenCV(4.6.0) D:\a\opencv-python\opencv-python\opencv\modules\dnn\src\onnx\onnx_importer.cpp:1040: error: (-2:Unspecified error) in function 'cv::dnn::dnn4_v20220524::ONNXImporter::handleNode'
> Node [Conv@ai.onnx]:(onnx_node!StatefulPartitionedCall/vgg16/conv_bn_two_relu_pool1/conv_bn_one_relu/conv2d/Conv2D) parse error: OpenCV(4.6.0) D:\a\opencv-python\opencv-python\opencv\modules\dnn\src\layers\convolution_layer.cpp:405: error: (-2:Unspecified error) Number of input channels should be multiple of 3 but got 0 in function 'cv::dnn::ConvolutionLayerImpl::getMemoryShapes'
>

错误的关键字是Number of input channels should be multiple of 3 but got 0 in function,通过搜索会发现大量文章,比如这一遍https://github.com/opencv/opencv/issues/20866 并没有给出解决方案

 还有这一篇,给出了解决方案 DNN/ONNX: outputs registration regression, feature request for new version of Clip operator · Issue #21698 · opencv/opencv · GitHub reshape一下维度,但是这个解决方案,是解决在net.setInput时出的问题,而本问题是在cv2.dnn.readNetFromONNX(path)就出现加载不了的问题,其实质是不一样的。

其实网上搜索了很多,都没有给出解决方案。

那么为什么要会出现这个问题呢,这其实跟自已实现CNN的方法有一点关系,如下图这样来实现转换成onnx时就没有问题.

训练后转换成onnx
path = "D:\\DLAI\\qwenAILearn\\StudyDNN\\TrainExample\\weights\\"
command = """python -m tf2onnx.convert  --saved-model  "{}vgg16"  --opset 12   --output {}vgg16.onnx """.format(path,path)
os.system(command)

使用opencv预测

然后我换了一种实现方式,对conv进行了一些封装,如下代码:

按上面的方法转换成vgg16_model.onnx,然后使用相同的推理代码去预测就会出现

onnx_importer.cpp (1021) cv::dnn::dnn4_v20220524::ONNXImporter::handleNode DNN/ONNX: ERROR during processing node with 3 inputs and 1 outputs 的错误。

因为我有相同的模型,不同推理出现不同结果的问题,所以我们可以使用Netron进行查看两个模型的不同点,如图:

从上图可以看到能够进行推理的是左边的,有一个维度是unk_80,224,224,3,而右边不行的是unk_259,unk_260,unk_261,unk_262。结合上面的提示,猜应该是输入维度的问题。

经查询资料可知,opencv dnn并不支持动态尺寸输入,参考:https://github.com/opencv/opencv/issues/19347

 

所以,我们的解决办法,就是想办法将onnx转换成指定的input_size,这个时候通过查询获知以下链接 Make dynamic input shape fixed - onnxruntime 给出了转换的命令,指定输入的维度

python -m onnxruntime.tools.make_dynamic_shape_fixed --input_name "input_1" --input_shape 1,224,224,3 "D:\DLAI\qwenAILearn\StudyDNN\TrainExample\weights\vgg16_model_3.onnx" "D:\DLAI\qwenAILearn\StudyDNN\TrainExample\weights\vgg16_model_3_back.onnx"

 转换后的onnx内容如下。

 

 转换后使用以下脚本来运行

会发现输出的结果是[[0. 0. 0. 1. 0.]]是不正确的,但是这个时候已经不报cv::dnn::dnn4_v20220524::ONNXImporter::handleNode DNN/ONNX: ERROR during processing node with 3 inputs and 1 outputs 错误了。修改上面的问题,只需要加上归一化即可。

如上,预测正确。

综上,当opencv在读onnx时cv2.dnn.readNetFromONNX(path)就报convolution_layer.cpp RROR during processing node with 3 inputs and 1 outputs 错误的时候,只需要使用onnxruntime.tools.make_dynamic_shape_fixed --input_name "input_1" --input_shape 1,224,224,3 改为指定尺寸输入即可解决。

### 回答1: cv2.dnn.readnetfromonnx是OpenCV中的一个函数,用于从ONNX模型文件中读取神经网络模型。ONNX是一种开放式的神经网络交换格式,可以将不同框架中训练好的模型转换为ONNX格式,以便在其他框架中使用。cv2.dnn.readnetfromonnx函数可以读取ONNX格式的模型文件,并将其转换为OpenCV中的dnn模块可以使用的格式。 ### 回答2: cv2.dnn.readnetfromonnx是OpenCV中用来读取ONNX模型的函数。ONNX是一种通用的模型格式,可以用于不同深度学习框架之间的模型转换,这使得在不同框架之间迁移深度学习模型变得更加容易和高效。 使用cv2.dnn.readnetfromonnx函数可以方便地将ONNX模型加载到OpenCV中,便于后续的深度学习模型推理操作。 该函数有两个参数,第一个是ONNX模型的路径,第二个是可选参数,用于指定模型的后端。如果未指定,则使用默认的后端。 使用cv2.dnn.readnetfromonnx读取的模型,随后可以使用OpenCV中的dnn模块的其他函数进行推理操作,例如cv2.dnn.blobFromImage用于将输入数据转换为网络需要的格式,cv2.dnn.forward用于进行前向推理等。 需要注意的是,cv2.dnn.readnetfromonnx函数只能读取ONNX格式的模型,如果模型是其他格式,需要先将其转换为ONNX格式再进行读取。此外,该函数的返回值是一个dnn.Net对象,可以使用其属性和方法进行访问和操作。 ### 回答3: cv2.dnn.readnetfromonnx是OpenCV的一个函数,它的作用是读取ONNX模型并返回OpenCV深度学习模块支持的模型格式。ONNX是一种神经网络模型的中间表示格式,它可以在多个框架和工具之间共享和转换神经网络模型。因此,cv2.dnn.readnetfromonnx是将ONNX模型加载到OpenCV中的一种方法。 该函数的语法如下: `cv2.dnn.readnetfromonnx(model [, blobSize = (0, 0) [, mean = 0 [, scale = 1 [, swapRB = True [, crop = False]]]]]) -> retval` 其中,model是ONNX模型的文件名或二进制数据,blobSize是网络输入数据的大小,mean和scale是处理输入数据时要使用的减均值和缩放系数,swapRB表示是否交换通道顺序,crop表示是否进行裁剪。 调用该函数后,会返回一个OpenCV深度学习模块支持的模型实例。这个实例可以用来进行前向推理,从而对图像、视频或其他输入数据进行分类、检测、分割等深度学习任务。 总之,cv2.dnn.readnetfromonnx是一种将ONNX模型加载到OpenCV深度学习模块中的方法。它可以方便地将不同框架或工具中的神经网络模型转换为OpenCV支持的格式,从而利用OpenCV进行深度学习推理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

那美那美

失业了,写文章求吃碗炒面

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值