debugging a method for finding running average of frames from video for motion detection using OpenCV in C++

So to practice C++ I'm writing a motion detection program that uploads photos to dropbox using the OpenCV library, a project that I did last summer in pyton following this tutorial: https://www.pyimagesearch.com/2015/05/25/basic-motion-detection-and-tracking-with-python-and-opencv/

This section of code is running once, and then throwing an error on the second loop.

This is the code:

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;
}

I'm getting this error:

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

the error is being generated by the accumulate Weighted function, which I tried to fix by creating a local array Acc after reading these pages:

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

Assertion failed with accumulateWeighted in OpenCV

I need to find out why this is terminating on the second loop. I think this is a symantic error. the code runs as written, but my instructions aren't actually what I intend/need it to do.

some possibly useful information:

Acc was originally based off gray_frame but I realized the design of this method depended on the global value average, causing the delta frame to have an outline of the original frame in all proceeding frames. So I'm trying to redesign it to stick to using global average.

The channels for all 3 (gray_frame, average, and Acc) is one. The depth of gray frame stays at 0. The depth for average at first is 5(after the if statement), then 0, whereas the depth of Acc stays at 5. It seems as is the main loop executes once and then quits.

a single average value of average before the accumulate weighted of the second loop is the same as the average of the first. around 97.89

The entire C++ program (work in progress) can be found here: https://github.com/skewballfox/SauronsEye/blob/master/SauronsEye.cpp

My work from last summer that I'm somewhat using as a guide (this was mainly for me to practice and never really was intended to be viewed so it's kinda messy): https://github.com/skewballfox/opencv-practice/blob/master/pi_surveillance.py

1 answer

  • answered 2017-12-27 15:17 Spider Jerusalem

    The issue is when scaling average in convertScaleAbs() this changes the type of average to 0 or CV_8U. this was fixed by creating an empty Mat() and storing the results in there, as opposed to scaling average itself:

    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;
    }