C++中将OpenCV Mat转为DNN张量及blobFromImage维度报错如何解决
问题修复方案
核心问题根因
你收到的报错是因为生成的输入张量维度完全不符合模型要求,从报错日志可以看到当前生成的blob维度为[1, 100, 3, 150],模型第一层卷积要求输入通道为3,但系统误把宽度100识别成了通道数。
常见问题解答:blobFromImage是唯一方式吗?
不是。blobFromImage只是OpenCV封装的图像预处理便捷接口,整合了resize、归一化、通道交换、维度调整等步骤。你完全可以手动完成所有预处理操作,只要最终输入给网络的四维张量维度、数值范围、通道顺序符合模型要求即可。
修复步骤
你需要按顺序修改代码中的两个核心错误:
- 修正归一化系数的整数运算问题
你当前写的1/255是C++整数除法,运算结果直接为0,会导致整张图片的像素值被置为0,需要修改为浮点数除法1.0/255.0。 - 调整张量维度顺序匹配模型要求
OpenCV的blobFromImage默认生成的是NCHW格式的四维张量(顺序为[batch数, 通道数, 高度, 宽度]),正常情况下你传入cv::Size(100,150)后生成的张量应该是[1,3,150,100],如果你的模型是用TensorFlow等框架训练、导出的ONNX默认是NHWC格式(顺序为[batch数, 高度, 宽度, 通道数]),你需要额外调用接口调整维度顺序。
修正后完整可运行代码
#include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <vector> int main() { std::vector< cv::Mat > outs; std::cout << "LOAD DNN in CPP Project!" << std::endl; cv::Mat image = cv::imread("example.png",1); if(image.empty()){ std::cerr << "图像读取失败,请检查路径" << std::endl; return -1; } cv::dnn::Net net; net = cv::dnn::readNetFromONNX("model.onnx"); if(net.empty()){ std::cerr << "模型读取失败,请检查路径" << std::endl; return -1; } cv::Mat blob; // 修正归一化系数,根据模型要求调整swapRB参数 cv::dnn::blobFromImage(image, blob, 1.0/255.0, cv::Size(100,150), cv::Scalar(0,0,0), false,false); // 调试用:打印blob维度确认是否符合要求 // std::cout << "Blob shape: [" << blob.size[0] << ", " << blob.size[1] << ", " << blob.size[2] << ", " << blob.size[3] << "]" << std::endl; // 如果模型要求NHWC格式,取消下一行注释 // blob = blob.permute({0, 2, 3, 1}); net.setInput(blob); net.forward( outs, "output"); return 0; }
内容的提问来源于stack exchange,提问作者MH.AI.eAgLe
相关产品推荐
相关产品推荐

