简体   繁体   English

OpenCV比较两个图像并获得不同的像素

[英]OpenCV compare two images and get different pixels

For some reason the code bellow is not working. 出于某种原因,下面的代码不起作用。 I have two 640*480 images which are very similar but not the same (at least few hundred/thousand pixels should be different). 我有两个非常相似但不相同的640 * 480图像(至少几百/千像素应该是不同的)。

This is how I am comparing them and counting different pixels: 这就是我比较它们和计算不同像素的方式:

unsigned char* row;
unsigned char* row2;
int count = 0;

// this happens in a loop
// fIplImageHeader is current image
// lastFIplImageHeader is image from previous iteration
if ( NULL != lastFIplImageHeader->imageData ) {
for( int y = 0; y < fIplImageHeader->height; y++ )
{
    row = &CV_IMAGE_ELEM( fIplImageHeader, unsigned char, y, 0 );
    row2 = &CV_IMAGE_ELEM( lastFIplImageHeader, unsigned char, y, 0 );
    for( int x = 0; x < fIplImageHeader->width*fIplImageHeader->nChannels; x += fIplImageHeader->nChannels )
    {
        if(row[x] != row2[x] || row[x+1] != row2[x+1] || row[x+2] != row2[x+2])
            count++;
        }
    }
}
}

Now at the end I get number 3626 which would seem alright. 现在最后我得到3626号,这似乎没问题。

But, I tried opening one of the images in MS Paint and drawing thick red lines all over it which should increase the number of different pixels substantially. 但是,我尝试打开MS Paint中的一个图像并在其上绘制粗红线,这应该会大大增加不同像素的数量。 I got the same number again: 3626. 我又得到了相同的号码:3626。

Obviously I am doing something wrong here. 显然我在这里做错了。

I am comparing these images in a loop. 我在循环中比较这些图像。

This line is before the loop: 这一行在循环之前:

IplImage* lastFIplImageHeader = cvCreateImageHeader(cvSize(640, 480), 8, 3);

Then inside the loop I load images like this: 然后在循环内我加载这样的图像:

IplImage* fIplImageHeader = cvLoadImage( filePath.c_str() );

// here I compare the pixels (the first code snippet)

lastFIplImageHeader->imageData = fIplImageHeader->imageData;

So lastFIplImageHeader is storing the image from the previous iteration and fIplImageHeader is storing the current image. 所以lastFIplImageHeader存储上一次迭代的图像,fIplImageHeader存储当前图像。

int count_diff_pixels(cv::Mat in1, cv::Mat in2) {
    cv::Mat diff;
    cv::compare(in1, in2, diff, cv::CMP_NE);
    return cv::countNonZero(diff);
}

Might need some tweaking, but that's about how you do it. 可能需要一些调整,但这是关于你如何做到这一点。 Also, you shouldn't be messing with cv* if you really use c++. 另外,如果你真的使用c ++,你不应该搞乱cv *。 Use the new c++ interface, and don't worry about freeing images. 使用新的c ++界面,不用担心释放图像。 reading images, remembering the previous one becomes as simple as 阅读图像,记住前一个图像变得如此简单

cv::Mat prev;
while (...) {
    cv::Mat current = cv::imread(fn); // or whereever your image comes from
    // ... do something ...
    prev = current;
} // automatic memory management!

It seems to me you aren't counting different pixels, not even pixels at all. 在我看来,你不计算不同的像素,甚至根本不计算像素。
You are counting how often a color channel of one pixel in the first image matches the channel of the corresponding pixel in the other image. 您正在计算第一个图像中一个像素的颜色通道与另一个图像中相应像素的通道的匹配频率。

You probably meant to do something along the lines of: 你可能想要做的事情是这样的:

...
//in the inner for loop
if(row[x] != row2[x] || row[x+1] != row2[x+1] || row[x+2] != row2[x+2])
  count++;
...

This will however not account for the alpha channel (if present) and will fail on grayscale images as you might read out of bounds of the data array. 然而,这将不考虑alpha通道(如果存在),并且将在灰度图像上失败,因为您可能读出数据数组的边界。

EDIT: As long as you don't release the old image it should be fine. 编辑:只要您不释放旧图像,它应该没问题。 However, it might be better to do something like: 但是,做以下事情可能会更好:

//make sure size and channels are correct.
//If unsure, load the image first and then create with the parameters taken from the loaded image.
cvCreateImage(cvSize(640, 480), 8, 3);

//use cvCopy to copy the contents and proceed as normal
cvCopy(fIplImageHeader , lastFIplImageHeader);

Alternatively, instead of copying, you could just hold a pointer to the old image and use that, as long as you don't release it. 或者,您可以只握住指向旧图像的指针,而不是复制,只要您不释放它。

lastFIplImageHeader = fIplImageHeader;
fIplImageHeader = cvLoadImage( filePath.c_str() );

EDIT2: If the difference is all you want, you could have a look at cvSub (with both images loaded as grayscale), followed by cvCountNonZero 编辑2:如果差异就是你想要的,你可以看看cvSub (两个图像加载为灰度),然后是cvCountNonZero

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM