Matlab和OpenCV为同一图像计算不同的图像矩m00

时间:2015-01-12 02:04:42

标签: matlab opencv

对于完全相同的图像

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

有人有任何想法吗?如何统一他们?我认为他们使用不同的方法来寻找轮廓。

我在下面的链接上传了测试图像,以便对此感兴趣的人可以重现该过程

这是一个100 x 100的小8位灰度图像,只有0和255像素强度。为简单起见,它只有一个blob。 对于OpenCV,轮廓区域(图像力矩m00)为609.5(非常奇数值) 对于Matlab,轮廓区域(图像矩m00)为763。

由于

1 个答案:

答案 0 :(得分:3)

存在许多关于如何从二进制图像中提取轮廓的不同定义。例如,它可以是多边形,它是二进制图像中白色对象的周长。如果OpenCV使用此定义,则轮廓区域将与Matlab找到的连接组件区域相同。但这种情况并非如此。 findContour()函数找到的轮廓是连接邻居&#34;边缘像素&#34;的中心的多边形。边缘像素是在N4邻域中具有黑色邻居的白色像素。

示例:假设您的图像大小为100x100像素。对角线上方的每个像素都是黑色的。对角线下方或对角线上的每个像素都是白色(黑色三角形和白色三角形)。精确分离多边形在距离为1像素时将有近200个顶点:(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找到的轮廓,并在图像上使用函数moment()。我知道即将推出的OpenCV 3具有查找连接组件的功能,但我自己没有尝试过。