我正在处理以下代码
#include <iostream>#include <opencv2/core/core.hpp>#include <string>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/video/background_segm.hpp>using namespace std;using namespace cv;int main(){ Mat current,currentGrey,next,abs; VideoCapture cam1,cam2; std:: vector<vector<Point>>contours; vector<vector<Point>>contoursPoly(contours.size()); cam1.open(0); cam2.open(0); namedWindow("Normal"); namedWindow("Difference"); if(!cam1.isOpened()) { cout << "Cam not found" << endl; return -1; } while(true) { //Take the input cam1 >> current; currentGrey = current; cam2 >> next; //Convert to grey cvtColor(currentGrey,currentGrey,CV_RGB2GRAY); cvtColor(next,next,CV_RGB2GRAY); //Reduce Noise cv::GaussianBlur(currentGrey,currentGrey,Size(0,0),4); cv::GaussianBlur(next,next,Size(0,0),4); imshow("Normal",currentGrey); //Get the absolute difference absdiff(currentGrey,next,abs); imshow("Difference",abs); for(int i=0;i<abs.rows;i++) { for(int j=0;j<abs.cols;j++) { if(abs.at<int>(j,i)>0) { cout << "Change Detected" << endl; j = abs.cols+1; i = abs.rows+1; } } } if(waitKey(30)>=0) { break; } }}
在这里,我试图在检测到图像之间的差异时打印一条消息。以下是技术部分
for(int i=0;i<abs.rows;i++) { for(int j=0;j<abs.cols;j++) { if(abs.at<int>(j,i)>0) { cout << "Change Detected" << endl; j = abs.cols+1; i = abs.rows+1; } } }
遗憾的是,它并不是在检测到差异时才打印消息,而是总是打印消息。这是为什么呢?
回答:
您应该计算两帧之间的均方误差。
MSE = sum((frame1-frame2)^2 ) / 像素数量
在OpenCV教程中有一个计算它的例子。
基于那个代码,您可以有以下内容
double getMSE(const Mat& I1, const Mat& I2){ Mat s1; absdiff(I1, I2, s1); // |I1 - I2| s1.convertTo(s1, CV_32F); // 不能对8位数进行平方运算 s1 = s1.mul(s1); // |I1 - I2|^2 Scalar s = sum(s1); // 按通道求和元素 double sse = s.val[0] + s.val[1] + s.val[2]; // 求和通道 if( sse <= 1e-10) // 对于小值返回零 return 0; else { double mse =sse /(double)(I1.channels() * I1.total()); return mse; // 教程代码返回PSNR(如下),而不是返回MSE。 //double psnr = 10.0*log10((255*255)/mse); //return psnr; }}
您可以在代码中这样使用它:
if(getMSE(currentGrey,next) > some_threshold) cout << "Change Detected" << endl;
由您决定在什么样的MSE值以下认为图像是相同的。您还应该像您已经做的那样使用GaussianBlur()
来预先过滤以减少噪声。@fatih_k建议的blur
方法并不是高斯滤波器;它是一个方框滤波器,虽然速度更快,但可能会引入伪影。