我正在尝试在视频中进行帧减法。
我在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/