视频中的帧减法

frame subtraction in video

我正在尝试在 video.Steps 我正在关注

中进行帧减法
  1. 获取图像,将其转换为灰度。
  2. 从上一帧灰度中减去它。

我在 diff2(和 diff 也是)中看到的全部黑色 image.One 我所做的观察是 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;
}

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

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

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

此外,150 的阈值差对于普通任务来说可能非常高,但对于您的特殊任务来说可能没问题。根据我的经验,前景提取的背景减法的典型差异 values/thresholds 大约为 20 到 30,但最终取决于您的 task/problem/domain。