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

OpenCV摄像头识别QR码播放视频时warpPerspective断言错误如何解决

问题解决指南

你遇到的 OpenCV(4.5.3) Error: Assertion failed (_src.total() > 0) in cv::warpPerspective 报错,本质是调用warpPerspective时传入的输入图像为空,没有有效像素。你的代码存在多处逻辑漏洞会触发该问题,修复方案如下:

存在的问题清单

  • 缺少视频打开成功校验:如果QR码对应的视频文件不存在、路径错误,video.open()调用失败后仍然继续执行后续逻辑,读取到的视频帧为空
  • 缺少视频帧读取校验:视频播放到末尾后,video >> videoFrame会读取失败得到空帧,直接传入warpPerspective就会触发断言
  • 缺少单应性矩阵校验:findHomography计算失败时会返回空Mat,传入warpPerspective也会触发报错
  • 逻辑顺序错误:你在未对warpedFrame、warpedMask执行透视变换之前,就先调用了copyTo方法,此时两个Mat都是空对象,也会触发空输入错误

修正后的完整代码

#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

int main() 
{
    Mat cameraFrame, videoFrame;
    vector<Point2f> bbox;
    double width, height;
    VideoCapture camera(0), video;
    QRCodeDetector qrDecoder;
    string data;
    
    // 校验摄像头是否正常打开
    if (!camera.isOpened()) {
        cout << "摄像头打开失败" << endl;
        return -1;
    }

    while (camera.read(cameraFrame))
    {
        data = qrDecoder.detectAndDecode(cameraFrame, bbox);

        if (data.length() > 0 && bbox.size() == 4) // 额外校验QR码返回的边界点数量是否正常
        {
            if (!video.isOpened()) {
                string videoPath = "../data/" + data + ".mp4";
                video.open(videoPath);
                // 校验视频是否打开成功
                if (!video.isOpened()) {
                    cout << "视频文件打开失败:" << videoPath << endl;
                    data.clear(); // 清空data避免重复尝试打开失败的视频
                    continue;
                }
                width = video.get(CAP_PROP_FRAME_WIDTH);
                height = video.get(CAP_PROP_FRAME_HEIGHT);
            }
            
            // 读取视频帧并校验
            if (!(video >> videoFrame)) {
                // 视频播放结束后释放资源,下次扫描到QR码重新播放
                video.release();
                data.clear();
                continue;
            }

            vector<Point2f> v_bbox{ Point2f(0, 0), Point2f(width,0), Point2f(width,height), Point2f(0, height) };
            Mat H = findHomography(v_bbox, bbox);
            // 校验单应性矩阵是否有效
            if (H.empty()) {
                continue;
            }

            Mat warpedFrame, warpedMask;
            // 先做透视变换,再执行copyTo操作,修正顺序
            warpPerspective(videoFrame, warpedFrame, H, cameraFrame.size());
            Mat mask(videoFrame.size(), CV_8UC1, Scalar(255));
            warpPerspective(mask, warpedMask, H, cameraFrame.size());
            
            warpedFrame.copyTo(cameraFrame, warpedMask);

            imshow("warpedFrame", warpedFrame);
            imshow("WarpedMask", warpedMask);
        }
        imshow("cam", cameraFrame);
        // 按ESC键退出
        if (waitKey(1) == 27) {
            break;
        }
    }
    // 释放资源
    camera.release();
    if (video.isOpened()) {
        video.release();
    }
    destroyAllWindows();
    return 0;
}

额外注意事项

  • 确认../data/路径下存在和QR码内容同名的mp4文件,路径可以根据你的实际存放位置调整
  • 如果需要重复播放视频,可以在视频读取到末尾后调用video.set(CAP_PROP_POS_FRAMES, 0)重置到第一帧,不用释放资源

内容的提问来源于stack exchange,提问作者윤재준

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 03:06:03