OpenCV运行YOLOv4-tiny代码触发断言失败错误求助
问题分析与解决方案
核心原因
触发dims() <= 2断言失败的直接原因:
- YOLO模型的输入blob是4维张量(NCHW格式,形状为
[1, 3, 416, 416]),而cv::Mat::size()仅支持输出维度≤2的矩阵尺寸,直接打印会触发断言。 blobFromImg的rows和cols为-1,说明blobFromImage处理了无效输入帧(空Mat),导致生成的blob完全无效。
具体问题点
- 未检查空帧:循环中
cap >> img后未判断帧是否为空,当视频读取完毕或路径错误时,img是空白Mat,blobFromImage无法生成有效blob。 - 重复归一化:
blobFromImage已设置缩放因子1,后续setInput又设置scale=1.0/255.0,导致像素值被重复缩放,破坏模型输入格式。 - static变量风险:
static Mat blobFromImg会保留前一次的内存状态,若某次处理失败,后续帧的blob会被污染。
修复步骤
- 添加空帧检查:每次读取帧后立即判断
img.empty(),为空则退出循环。 - 正确输出blob形状:通过Mat的
size数组逐个输出维度(如blobFromImg.size[0]对应batch数)。 - 合并归一化操作:将
scale=1/255.0和mean=Scalar(0,0,0)整合到blobFromImage中,避免重复处理。 - 移除static修饰:将
blobFromImg改为局部变量,确保每次循环都重新初始化。 - 验证模型加载:检查
network.empty()确认模型/配置文件加载成功。
修改后的代码
#include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/highgui.hpp> #include <opencv2/video.hpp> #include <opencv2/dnn.hpp> #include <opencv2/videoio.hpp> #include <opencv2/imgproc.hpp> #include <iomanip> using namespace cv; using namespace std; using namespace dnn; int main() { VideoCapture cap("D:/video1.mp4"); if (!cap.isOpened()) { cout << "Video Capture Fail" << endl; return -1; } std::string model = "./Models/yolov4_tiny_train2_best.weights"; std::string config = "./Models/yolov4_tiny_train2.cfg"; Net network = readNet(model, config, "Darknet"); if (network.empty()) { cout << "Failed to load model/config" << endl; return -1; } network.setPreferableBackend(DNN_BACKEND_DEFAULT); network.setPreferableTarget(DNN_TARGET_OPENCL); namedWindow("Display window", WINDOW_AUTOSIZE); for (;;) { Mat img; cap >> img; if (img.empty()) { cout << "End of video or frame read failed" << endl; break; } Mat blobFromImg; // 将归一化整合到blobFromImage中 blobFromImage(img, blobFromImg, 1.0/255.0, Size(416, 416), Scalar(0,0,0), true, false); // 正确输出4维blob的形状 cout << "Blob shape: [" << blobFromImg.size[0] << ", " << blobFromImg.size[1] << ", " << blobFromImg.size[2] << ", " << blobFromImg.size[3] << "]" << endl; network.setInput(blobFromImg); Mat outMat; network.forward(outMat); int rowsNoOfDetection = outMat.rows; int colsCoordinatesPlusClassScore = outMat.cols; for (int j = 0; j < rowsNoOfDetection; ++j) { Mat scores = outMat.row(j).colRange(5, colsCoordinatesPlusClassScore); Point PositionOfMax; double confidence; minMaxLoc(scores, 0, &confidence, 0, &PositionOfMax); if (confidence > 0.5) { int centerX = (int)(outMat.at<float>(j, 0) * img.cols); int centerY = (int)(outMat.at<float>(j, 1) * img.rows); int width = (int)(outMat.at<float>(j, 2) * img.cols); int height = (int)(outMat.at<float>(j, 3) * img.rows); int left = centerX - width / 2; int top = centerY - height / 2; stringstream ss; ss << PositionOfMax.x; string clas = ss.str(); int color = PositionOfMax.x * 10; putText(img, clas, Point(left, top), FONT_HERSHEY_SIMPLEX, 1, Scalar(color, 255, 255), 2); stringstream ss2; ss2 << fixed << setprecision(2) << confidence; string conf = ss2.str(); putText(img, conf, Point(left, top+30), FONT_HERSHEY_SIMPLEX, 1, Scalar(color, 255, 255), 2); rectangle(img, Rect(left, top, width, height), Scalar(color, 0, 0), 2); } } imshow("Display window", img); if (waitKey(25) == 27) { // ESC键退出 break; } } cap.release(); destroyAllWindows(); return 0; }
额外注意事项
- 确保
yolov4_tiny_train2.cfg中的width和height与blobFromImage的尺寸(416x416)一致,否则模型输入不匹配会导致后续检测错误。 - YOLOv4-tiny有多个输出层(如
yolo_13和yolo_26),原代码仅处理单个输出层,建议改为遍历所有输出层以获取完整检测结果。
内容的提问来源于stack exchange,提问作者S.T.A.L.K.E.R
相关产品推荐
相关产品推荐

