视频中的帧减法

时间:2015-12-09 09:05:51

标签: opencv background-subtraction

我正在尝试在视频中进行帧减法。步骤我正在关注

  1. 获取图像,将其转换为灰度。
  2. 从之前的帧灰度中减去它。
  3. 所有我在diff2(和diff)中看到一个完整的黑色图像。我做的一个观察是gray1和gray2的像素值变得相等。

    我的代码

    #include "opencv2/core/core.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/objdetect/objdetect.hpp"
    #include <opencv2/video/background_segm.hpp>
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    RNG rng(12345);
    
        int main( int argc, const char** argv )
    
    {
       VideoCapture cap(0);
    
        if ( !cap.isOpened() ) 
        {
             cout << "Cannot open the web cam" << endl;
             return -1;
        }
    
        Mat img1,img2,diff,gray1,gray2,diff2;
    
    
            bool bSuccess = cap.read(img1); // read a new frame from video
    
             if (!bSuccess) //if not success, break loop
            {
                 cout << "Cannot read a frame from video stream" << endl;
                 return -1;
            }
    
            cvtColor( img1,gray1, CV_BGR2GRAY );
    
         while (true)
        {
    
    
            bSuccess = cap.read(img2); // read a new frame from video
    
             if (!bSuccess) //if not success, break loop
            {
                 cout << "Cannot read a frame from video stream" << endl;
                 break;
            }
            cvtColor( img2,gray2, CV_BGR2GRAY );
    
            absdiff(gray2,gray1,diff);
            threshold(diff, diff2, 150, 255, CV_THRESH_BINARY); 
            cout<<gray2.at<uchar>(100,200) <<endl;
            cout<<gray1.at<uchar>(100,200) <<endl;
    
            gray1=gray2;
            imshow("1",gray1);
            imshow("2",diff2);
    
    
        if (waitKey(1000) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
           {
                cout << "esc key is pressed by user" << endl;
                break; 
           }
        }
    
    
         return -1;
    }
    

1 个答案:

答案 0 :(得分:2)

请尝试此代码。看起来您正在覆盖gray1,因此gray1和gray2使用相同的数据存储位置。

您可以使用gray1=gray2.clone();代替,也可以使用真正的&#34;交换&#34;缓冲区而不是覆盖。我的代码应该执行一个简单的缓冲区交换,并对该问题有一些评论。

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include <opencv2/video/background_segm.hpp>
#include <iostream>

using namespace cv;
using namespace std;
RNG rng(12345);

int main( int argc, const char** argv )

{
   VideoCapture cap(0);

    if ( !cap.isOpened() ) 
    {
         cout << "Cannot open the web cam" << endl;
         return -1;
    }

    Mat img1,img2,diff,gray1,gray2,diff2;

    Mat tmp; // used to swap the buffers


    bool bSuccess = cap.read(img1); // read a new frame from video

    if (!bSuccess) //if not success, break loop
    {
         cout << "Cannot read a frame from video stream" << endl;
         return -1;
    }

    // this will allocate memory of gray1 if not allocated yet
    cvtColor( img1,gray1, CV_BGR2GRAY );

    while (true)
    {


        bSuccess = cap.read(img2); // read a new frame from video

         if (!bSuccess) //if not success, break loop
        {
         cout << "Cannot read a frame from video stream" << endl;
         break;
        }

        // memory for gray2 won't be allocated if it is present already => if gray2 and gray1 use the same data memory, you'll overwrite gray1's pixels here and obviously gray1 and gray2 will have the same pixel values then
        cvtColor( img2,gray2, CV_BGR2GRAY );

        absdiff(gray2,gray1,diff);
        threshold(diff, diff2, 150, 255, CV_THRESH_BINARY); 
        cout<<gray2.at<uchar>(100,200) <<endl;
        cout<<gray1.at<uchar>(100,200) <<endl;

        // don't lose the memory of gray1
        tmp = gray1;

        // this means gray1 and gray2 will use the same data memory location
        gray1=gray2;

        // give gray2 a new data memory location. Since previous gray1 memory is still present but wont be used anymore, use it here.
        gray2=tmp;

        imshow("1",gray1);
        imshow("2",diff2);


    if (waitKey(1000) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
       {
            cout << "esc key is pressed by user" << endl;
            break; 
       }
    }


     return -1;
}

此外,对于常见任务,thres差异阈值150可能非常高,但它可能适合您的特殊任务。根据我的经验,前景提取的背景扣除中的典型差异值/阈值大约是20到30,但最后它取决于您的任务/问题/域。