OpenCV图像操纵

OpenCV Image Manipulation

本文关键字:操纵 图像 OpenCV      更新时间:2023-10-16

我正试图找出两张图像中的差异。

场景:假设我有两张图像,一张是背景,另一张是在背景前面的人,我想把这两张图像相减,这样我就可以得到人的位置,也就是说,程序可以检测出人站在哪里,并将相减后的图像作为输出。

我设法想出的代码是从相机中拍摄两张图像并重新调整它们的大小,并将这两张图像转换为灰度。我想知道这之后该怎么办。我检查了OpenCV提供的减法函数,但它以数组作为输入,所以我不知道如何进行。

我写的代码是:

cap>>frame; //gets the first image
cv::cvtColor(frame,frame,CV_RGB2GRAY); //converts it to gray scale
cv::resize(frame,frame,Size(30,30));  //re-sizes it
cap>>frame2;//gets the second image
cv::cvtColor(frame2,frame2,CV_RGB2GRAY); //converts it to gray scale
cv::resize(frame2,frame2,Size(30,30)); //re-sizes it

现在我可以简单地使用减法函数了吗?比如:

cv::subtract(frame_gray,frame,frame);

还是先应用一些滤波器,然后使用减法函数?

正如其他人所注意到的,这是一个棘手的问题:很容易想出一个有时会奏效的破解方法,很难想出一个在大多数情况下只需最少人工干预就能奏效的解决方案。此外,如果可以严格控制背景的材质和照明,则操作会容易得多。专业应用程序被称为"镀铬"(特别是在电视行业)、"蓝屏"、"遮片"或"旅行遮片"(在电影摄影中)、计算机视觉中的"背景去除"。

Petro Vlahos多年前就完成了对准均匀背景进行抠图的开创性工作。其基本算法的专利已经过期,所以你可以带着它们进城(并找到各种质量的开源实现)。不用说,IANAL,所以请做好专利主题的功课。

消除更复杂的背景仍然是一个活跃的研究领域,尤其是在没有3D信息的情况下。你可能想看看MS research最近发表的几篇研究论文(a.Criminisi在这方面做了一些工作)。

使用减法是不合适的,因为它可能会导致某些值变为负值,并且只有当您试图查看是否存在差异(布尔值true/false)时才有效。

如果你需要得到不同的像素,你应该逐个像素进行比较,比如:

int rows = frame.rows;
int cols = frame.cols;
cv::Mat diffImage = cv::Mat::zeros(rows, cols, CV_8UC1);
for(int i = 0; i < rows; ++i)
{
    for(int j = 0; j < cols; ++j)
    {
        if(frame.at<uchar>(i,j) != frame2.at<uchar>(i,j))
            diffImage.at<uchar>(i, j) = 255;
    }
}

现在,您可以显示或保存diffImage。所有不同的像素都将是白色的,而相似的像素将是黑色的