调试一种在 C++ 中使用 OpenCV 从视频中寻找运动平均帧以进行运动检测的方法

Posted

技术标签:

【中文标题】调试一种在 C++ 中使用 OpenCV 从视频中寻找运动平均帧以进行运动检测的方法【英文标题】:debugging a method for finding running average of frames from video for motion detection using OpenCV in C++ 【发布时间】:2017-12-27 15:17:26 【问题描述】:

为了练习 C++,我正在编写一个运动检测程序,该程序使用 OpenCV 库将照片上传到 dropbox,这是我去年夏天在 pyton 遵循本教程所做的一个项目:https://www.pyimagesearch.com/2015/05/25/basic-motion-detection-and-tracking-with-python-and-opencv/p>

这段代码运行一次,然后在第二次循环时抛出错误。

这是代码:

Mat set_delta(Mat &average, Mat gray_frame)

    Mat delta_frame;
    if (average.empty()==1)
    
        cout<<"gray frame depth: "<<gray_frame.depth();

        gray_frame.convertTo(average, CV_32FC(gray_frame.channels()));
        //Mat Acc(gray_frame.rows,    gray_frame.cols,CV_32FC(gray_frame.channels()));
    
    //cout<<"gray_frame average: "<< get_average(gray_frame)<<
    //      "\naverage_frame average: "<<get_average(average);
    Mat Acc(average.rows, average.cols,CV_32FC(average.channels()));

    cout<<"average depth: "<<average.depth()<<"\nAcc depth: "<<Acc.depth();

    accumulateWeighted(gray_frame, average, .5);
    convertScaleAbs(average, average);
    absdiff(gray_frame,average,delta_frame);
    return delta_frame;

我收到此错误:

OpenCV Error: Assertion failed (func != 0) in accumulateWeighted, file /build/opencv/src/opencv-3.3.1/modules/imgproc/src/accum.cpp, line 635
terminate called after throwing an instance of 'cv::Exception'
what():  /build/opencv/src/opencv-3.3.1/modules/imgproc/src/accum.cpp:635: error: (-215) func != 0 in function accumulateWeighted

错误是由累加加权函数产生的,我在阅读这些页面后尝试通过创建本地数组 Acc 来修复该错误:

http://answers.opencv.org/question/63781/accumulateweighted-problems/

Assertion failed with accumulateWeighted in OpenCV

我需要找出为什么它会在第二个循环中终止。我认为这是一个语义错误。代码按照编写的方式运行,但我的指令实际上并不是我想要/需要的。

一些可能有用的信息:

Acc 最初是基于 gray_frame 但我意识到这种方法的设计依赖于全局值平均值,导致增量帧在所有后续帧中都有原始帧的轮廓。所以我正在尝试重新设计它以坚持使用全球平均值。

所有 3 个通道(gray_frame、average 和 Acc)都是一个。 灰框的深度保持在 0。 平均的深度一开始是5(在if语句之后),然后是0,而Acc的深度保持在5。似乎是主循环执行一次然后退出。

第二个循环的累加加权之前的单个平均值与第一个的平均值相同。 97.89左右

整个 C++ 程序(正在进行中)可以在这里找到:https://github.com/skewballfox/SauronsEye/blob/master/SauronsEye.cpp

我去年夏天的作品,我在某种程度上用作指导(这主要是为了我练习,从来没有真正打算被查看,所以有点乱): https://github.com/skewballfox/opencv-practice/blob/master/pi_surveillance.py

【问题讨论】:

您有什么实际问题?您是在问为什么会收到断言错误? 是的,我知道问题出在 accumWeighted() 上,因为我在最初调试时发现了这两个页面:[***.com/questions/7059817/… 和错误下方问题中列出的那个 我试图找出 Acc(基于 gray_frame 的值创建和平均值(初始化为 empy 矩阵但作为灰度的浮点值副本)之间的区别。我需要这种方法来处理平均值因为我需要有一个运行平均帧才能确定帧中是否有任何东西在移动。 【参考方案1】:

问题是在 convertScaleAbs() 中缩放平均值时,这会将平均值的类型更改为 0 或 CV_8U。这是通过创建一个空的 Mat() 并将结果存储在其中来解决的,而不是缩放平均值本身:

Mat set_delta(Mat &average, Mat gray_frame)

    Mat delta_frame, scaled_average;
    //delta_frame is the storage for the difference between the accumulated average
    //and the current gray frame. scaled average is for storing the output of convertScaleAbs()
    //otherwise the depth of global average is 0 and causes an error on the second loop
    if (average.empty()==1)
    
        gray_frame.convertTo(average, CV_32FC(gray_frame.channels()));
    

    accumulateWeighted(gray_frame, average, .5);
    convertScaleAbs(average, scaled_average);
    absdiff(gray_frame,scaled_average,delta_frame);

    return delta_frame;

【讨论】:

以上是关于调试一种在 C++ 中使用 OpenCV 从视频中寻找运动平均帧以进行运动检测的方法的主要内容,如果未能解决你的问题,请参考以下文章

如何根据相机校准(C++)生成的真实数据使用opencv模拟失真?

openCV、C++ 并发、windows

Opencv c++:如何按时间分割视频?

在 GDB、C++ 中调试 OpenCV 矩阵

如何使用 c++ 在带有 opencv 3.0.0 的视频中画一条线

使用 Opencv 时 C++ 调试断言失败