Matlab和OpenCV针对同一张图片计算的图像矩m00不同。

4

对于完全相同的图像

OpenCV 代码:

img = imread("testImg.png",0);
threshold(img, img_bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
Mat tmp;
img_bwR.copyTo(tmp);
findContours(tmp, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

// Get the moment
vector<Moments> mu(contours.size() );
for( int i = 0; i < contours.size(); i++ )
 { mu[i] = moments( contours[i], false ); 

 }

// Display area (m00)
for( int i = 0; i < contours.size(); i++ )
 { 
     cout<<mu[i].m00 <<endl;
     // I also tried the code 
     //cout<<contourArea(contours.at(i))<<endl;  
     // But the result is the same
 }

Matlab 代码:

Img = imread('testImg.png');
lvl = graythresh(Img);
bw = im2bw(Img,lvl);
stats = regionprops(bw,'Area');
for k = 1:length(stats)
    Area = stats(k).Area; %m00
end

有人对此有何想法?如何统一它们?我认为他们使用不同的方法来查找轮廓。

我在下面的链接中上传了测试图像,以便有兴趣的人可以重复该过程。

这是一个100x100的小8位灰度图像,只有0和255的像素强度。为简单起见,它只有一个斑点。

对于OpenCV,轮廓的面积(图像矩m00)为609.5(非常奇怪的值) 对于Matlab,轮廓的面积(图像矩m00)为763。

谢谢


你能提供一个图片链接吗?这样我们就可以在我们这边重现结果了。由于你的声望不够,无法上传图片,所以请提供一个公共分享网站的链接,我会修改你的帖子。关于OpenCV和MATLAB如何找到轮廓,你可能是正确的。顺便问一下,你有注意到它们之间产生了多少轮廓吗?它们的数量是相同的吗? - rayryeng
你好,rayryeng!非常感谢您的快速回复。我已经上传了下面链接中的图片: https://www.flickr.com/photos/129846799@N07/16072821870/这是一张100x100的小型8位灰度图像,只有0和255像素强度。 对于OpenCV,轮廓的面积(图像矩m00)为609.5(非常奇怪的值)。 对于Matlab,轮廓的面积为763。 - SimaGuanxing
1个回答

3
存在许多不同的定义来从二进制图像中提取轮廓。例如,它可以是二进制图像中白色物体的周长的多边形。如果OpenCV使用了这个定义,那么轮廓的面积将与Matlab找到的连通组件的面积相同。但事实并非如此。findContour()函数找到的轮廓是连接相邻“边缘像素”的中心的多边形。边缘像素是在N4邻域中有黑色邻居的白色像素。
例如:假设您有一个大小为100x100像素的图像。对角线以上的每个像素都是黑色的。对角线下方或以下的每个像素都是白色的(黑色三角形和白色三角形)。精确分离多边形将具有几乎200个距离为1个像素的顶点:(0,0),(1,0),(1,1),(2,1),(2,2),....(100,99),(100,100),(0,100)。正如您所看到的,这个定义从实际角度来看并不是很好。OpenCV返回的多边形将恰好有3个顶点来定义三角形:(0,0),(99,99),(0,99)。它的面积是(99 x 99 / 2)像素。它不等于白色像素的数量。它甚至不是整数。但这个多边形比以前的一个更实用。
这些不是多边形提取的唯一可能定义。存在许多其他定义。其中一些(在我看来)可能比OpenCV使用的更好。但这是已经实现并被许多人使用的定义。
目前没有有效的解决方案来解决您的问题。如果您想从MATLAB和OpenCV中获得完全相同的数字,您将不得不在某个黑色图像上绘制foundContours找到的轮廓,并在图像上使用moments()函数。我知道即将推出的OpenCV 3有一个可以找到连通组件的函数,但我自己没有尝试过。

谢谢!那很有道理。 - SimaGuanxing

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接