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

OpenCV 4.2.0断言错误求助:calcOpticalFlowPyrLK调用失败

问题分析与解决

错误原因

你遇到的断言错误Assertion failed ((npoints = prevPtsMat.checkVector(2, CV_32F, true)) >= 0),本质是调用calcOpticalFlowPyrLK时,传入的prevPoints为空向量,或者向量内的点格式不符合要求。

常见触发场景:

  • 首次调用goodFeaturesToTrack时,没有从第一帧检测到任何特征点,导致prevPoints为空
  • 后续循环中,光流追踪的所有点都失效(status全为0),直接交换currPoints和prevPoints后,prevPoints变为空

修复后的代码

#include <opencv2/opencv.hpp>
#include <vector>
#include <algorithm>

int main() {
    cv::VideoCapture cap("video.mp4");

    if (!cap.isOpened()) {
        std::cerr << "无法打开视频文件或流。" << std::endl;
        return -1;
    }

    cv::Mat prevFrame, currFrame;
    cv::TermCriteria termcrit(cv::TermCriteria::COUNT | cv::TermCriteria::EPS, 20, 0.03);
    cv::Size winSize(31, 31);

    std::vector<cv::Point2f> prevPoints, currPoints;

    while (true) {
        cap >> currFrame;

        if (currFrame.empty()) {
            break;
        }

        cv::Mat currGray;
        cv::cvtColor(currFrame, currGray, cv::COLOR_BGR2GRAY);

        if (prevFrame.empty()) {
            currGray.copyTo(prevFrame);
            // 检测特征点,同时检查是否成功获取点
            cv::goodFeaturesToTrack(prevFrame, prevPoints, 100, 0.01, 10);
            // 如果没检测到点,跳过当前循环,继续读下一帧
            if (prevPoints.empty()) {
                continue;
            }
        }

        std::vector<uchar> status;
        std::vector<float> err;

        // 确保prevPoints非空才调用光流计算
        if (!prevPoints.empty()) {
            cv::calcOpticalFlowPyrLK(prevFrame, currGray, prevPoints, currPoints, status, err, winSize, 3, termcrit, 0, 0.001);

            // 过滤无效点,只保留追踪成功的点
            std::vector<cv::Point2f> validPrevPoints, validCurrPoints;
            for (size_t i = 0; i < status.size(); i++) {
                if (status[i]) {
                    validPrevPoints.push_back(prevPoints[i]);
                    validCurrPoints.push_back(currPoints[i]);
                    // 在彩色帧上绘制(注意不要在灰度图上画彩色)
                    cv::circle(currFrame, validCurrPoints.back(), 3, cv::Scalar(0, 0, 255), -1);
                    cv::line(currFrame, validPrevPoints.back(), validCurrPoints.back(), cv::Scalar(0, 255, 0));
                }
            }

            // 更新prevPoints为有效点集
            prevPoints.swap(validPrevPoints);
            currPoints.swap(validCurrPoints);

            // 如果有效点过少,重新检测特征点
            if (prevPoints.size() < 10) {
                cv::goodFeaturesToTrack(currGray, prevPoints, 100, 0.01, 10);
            }
        } else {
            // prevPoints为空时重新检测
            cv::goodFeaturesToTrack(currGray, prevPoints, 100, 0.01, 10);
        }

        cv::imshow("Optical flow", currFrame);

        if (cv::waitKey(30) == 'q') {
            break;
        }

        currGray.copyTo(prevFrame);
    }

    cv::destroyAllWindows();

    return 0;
}

关键修复点

  • 避免灰度图绘制彩色异常:原代码将currFrame转为灰度后直接绘制,彩色会显示异常,改为保留原彩色帧用于绘制,单独用灰度帧计算光流
  • 特征点有效性检查:每次调用calcOpticalFlowPyrLK前确保prevPoints非空;追踪后过滤无效点,只保留status[i]为true的点
  • 自动重新检测特征点:当有效追踪点数量过少时,重新调用goodFeaturesToTrack获取新的特征点,避免prevPoints为空
  • 首次检测失败处理:如果第一帧没检测到特征点,跳过当前循环,继续读取下一帧重试

内容的提问来源于stack exchange,提问作者feinhein

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 18:22:47