出于某种原因,下面的代码不起作用.我有两个非常相似但不相同的640*480图像(至少几百/千像素应该是不同的).
这就是我比较它们和计算不同像素的方式:
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++;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在最后我得到3626号,这似乎没问题.
但是,我尝试打开MS Paint中的一个图像并在其上绘制粗红线,这应该会大大增加不同像素的数量.我又得到了相同的号码:3626.
显然我在这里做错了.
我在循环中比较这些图像.
这一行在循环之前:
IplImage* lastFIplImageHeader = cvCreateImageHeader(cvSize(640, 480), 8, 3);
Run Code Online (Sandbox Code Playgroud)
然后在循环内我加载这样的图像:
IplImage* fIplImageHeader = cvLoadImage( filePath.c_str() );
// here I compare the pixels (the first code snippet)
lastFIplImageHeader->imageData = fIplImageHeader->imageData;
Run Code Online (Sandbox Code Playgroud)
所以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);
}
Run Code Online (Sandbox Code Playgroud)
可能需要一些调整,但这是关于你如何做到这一点.另外,如果你真的使用c ++,你不应该搞乱cv*.使用新的c ++界面,不用担心释放图像.阅读图像,记住前一个图像变得如此简单
cv::Mat prev;
while (...) {
cv::Mat current = cv::imread(fn); // or whereever your image comes from
// ... do something ...
prev = current;
} // automatic memory management!
Run Code Online (Sandbox Code Playgroud)
在我看来,你不计算不同的像素,甚至根本不计算像素.
您正在计算第一个图像中一个像素的颜色通道与另一个图像中相应像素的通道的匹配频率.
你可能想要做的事情是这样的:
...
//in the inner for loop
if(row[x] != row2[x] || row[x+1] != row2[x+1] || row[x+2] != row2[x+2])
count++;
...
Run Code Online (Sandbox Code Playgroud)
然而,这将不考虑alpha通道(如果存在),并且将在灰度图像上失败,因为您可能读出数据数组的边界.
编辑: 只要您不释放旧图像,它应该没问题.但是,做一些事情可能会更好:
//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);
Run Code Online (Sandbox Code Playgroud)
或者,您可以只握住指向旧图像的指针,而不是复制,只要您不释放它.
lastFIplImageHeader = fIplImageHeader;
fIplImageHeader = cvLoadImage( filePath.c_str() );
Run Code Online (Sandbox Code Playgroud)
编辑2:如果差异就是你想要的,你可以看看cvSub(两个图像加载为灰度),然后是cvCountNonZero
| 归档时间: |
|
| 查看次数: |
18585 次 |
| 最近记录: |