You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV运行YOLOv4-tiny代码触发断言失败错误求助

问题分析与解决方案

核心原因

触发dims() <= 2断言失败的直接原因:

  1. YOLO模型的输入blob是4维张量(NCHW格式,形状为[1, 3, 416, 416]),而cv::Mat::size()仅支持输出维度≤2的矩阵尺寸,直接打印会触发断言。
  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会被污染。

修复步骤

  1. 添加空帧检查:每次读取帧后立即判断img.empty(),为空则退出循环。
  2. 正确输出blob形状:通过Mat的size数组逐个输出维度(如blobFromImg.size[0]对应batch数)。
  3. 合并归一化操作:将scale=1/255.0和mean=Scalar(0,0,0)整合到blobFromImage中,避免重复处理。
  4. 移除static修饰:将blobFromImg改为局部变量,确保每次循环都重新初始化。
  5. 验证模型加载:检查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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 06:57:05