Engine
Engine

Reputation: 5432

Getting the difference between two frames in opencv

I'm trying to get the the difference between two cv::Mat frames in OpenCv. So here is what I tried,

 #include<opencv2\opencv.hpp>
 #include<opencv2\calib3d\calib3d.hpp>
 #include<opencv2\core\core.hpp>
 #include <opencv2\highgui\highgui.hpp>
 int main ()
 {
    cv::VideoCapture cap(0);
    cv::Mat frame, frame1,frame2;
    int key=0;

    while(key!=27){
       cap >> frame;
       if(key=='c'){
          frame1 = frame;
          key = 0;
       }
       if(key =='x'){
          cv::absdiff(frame, frame1, frame2);  // I also tried frame2= (frame -frame1)*255;
          cv::imshow("difference ",frame2);
          key =0;
       }
       cv::imshow("stream",frame);
       key = cv::waitKey(10);
     }
  }

the result is always the same a 0 Matrix, any idea what I'm doing wrong here? thanks in advance for your help.

Upvotes: 3

Views: 13892

Answers (4)

GOPI
GOPI

Reputation: 131

I was looking for a similar program and I came across your post, here is a sample I have written for frameDifferencing, hope this helps, the below function will give you the difference between two frames

/** @function differenceFrame */
Mat differenceFrame( Mat prev_frame, Mat curr_frame ) 
{
    Mat image = prev_frame.clone();
    printf("frame rows %d Cols %d\n" , image.rows, image.cols);

    for (int rows = 0; rows < image.rows; rows++)
    {
        for (int cols = 0; cols < image.cols; cols++) 
        {   
          /*  printf("BGR value %lf %lf %lf\n" , abs(prev_frame.at<cv::Vec3b>(rows,cols)[0] - 
                                              curr_frame.at<cv::Vec3b>(rows,cols)[0]), 
                                              abs(prev_frame.at<cv::Vec3b>(rows,cols)[1] - 
                                              curr_frame.at<cv::Vec3b>(rows,cols)[0]),
                                              abs(prev_frame.at<cv::Vec3b>(rows,cols)[2] - 
                                              curr_frame.at<cv::Vec3b>(rows,cols)[0]));
            */
            image.at<cv::Vec3b>(rows,cols)[0] = abs(prev_frame.at<cv::Vec3b>(rows,cols)[0] - 
                                              curr_frame.at<cv::Vec3b>(rows,cols)[0]);
            image.at<cv::Vec3b>(rows,cols)[1] = abs(prev_frame.at<cv::Vec3b>(rows,cols)[1] - 
                                              curr_frame.at<cv::Vec3b>(rows,cols)[1]);
            image.at<cv::Vec3b>(rows,cols)[2] = abs(prev_frame.at<cv::Vec3b>(rows,cols)[2] - 
                                              curr_frame.at<cv::Vec3b>(rows,cols)[2]);
        }
    }
    return image;
} 

Upvotes: 0

sansuiso
sansuiso

Reputation: 9379

OpenCV overloads the affectation operator on cv::Mat objects so that the line mat1 = mat2 only affects the pointer to the data in mat1 (that points to the same data as mat2). This avoids time consuming copies of all the image data.

If you want to save the data of a matrix, you have to write mat1 = mat2.clone() or mat2.copyTo(mat1).

Upvotes: 4

djf
djf

Reputation: 6757

OpenCV Matrixes use pointers internally

The documentation of the Mat type states:

Mat is basically a class with two data parts: the matrix header and a pointer to the matrix containing the pixel values. [...] Whenever somebody copies a header of a Mat object, a counter is increased for the matrix. Whenever a header is cleaned this counter is decreased. When the counter reaches zero the matrix too is freed. Sometimes you will want to copy the matrix itself too, so OpenCV provides the clone() and copyTo() functions.

cv::Mat F = A.clone();
cv::Mat G;
A.copyTo(G);

Upvotes: 7

Fuat Coşkun
Fuat Coşkun

Reputation: 1055

Mat objects are pointer typed. After setting frame1 to frame directly using frame1 = frame, both matrices show the same point and same frame also. You have to copy frame value using "copyTo" method of Mat.

Upvotes: 11

Related Questions