我正在尝试在视频中进行帧减法。

  • 获取图像,将其转换为灰度。
  • 从上一帧灰度中减去它。

  • 我在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;
    }
    

    最佳答案

    请尝试此代码。似乎您正在覆盖gray1,以便gray1和gray2使用相同的数据存储位置。

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

    #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可能很高,但对于特殊任务可能没问题。根据我的经验,用于前景提取的背景减法中的典型差异值/阈值大约为20到30,但最终取决于您的任务/问题/ Realm 。

    关于opencv - 视频中的帧减法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34174632/

    10-08 20:38