检测两张图像之间的差异

我正在处理以下代码

#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方法并不是高斯滤波器;它是一个方框滤波器,虽然速度更快,但可能会引入伪影。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注