我在研究检测硬币的图像处理问题。
我这里有一些像这样的图片:
想把那些连接错误的硬币分开。
我们已经尝试了MATLAB主页上所述的分水岭方法:
the-watershed-transform-strategies-for-image-segmentation.html
尤其是因为第一个例子正是我们的问题。
但是相反,我们得到了一个非常混乱的分离,你可以在这里看到:
我们已经使用regionprops
极值参数提取了硬币的面积,并将分水岭仅投射到所需的面积上。
我很感激你能帮我解决这个问题,或者用别的方法把它分开。
最佳答案
如果您有图像处理工具箱,我也可以建议您使用Circular Hough Transform到imfindcircles
但是,这至少需要版本r2012 a,所以如果您没有它,这将不起作用。
为了完整起见,我假设你拥有它这是一个很好的方法,如果你想让图像保持原样如果你不知道Hough Transform是什么,它是一种在图像中寻找直线的方法圆Hough变换是一种特殊情况,其目的是在图像中寻找圆。
圆Hough变换的另一个优点是能够检测出图像中的部分圆这意味着图像中那些连接的区域,我们可以将它们检测为单独的圆您如何调用imfindcircles
是以下方式:
[centers,radii] = imfindcircles(A, radiusRange);
A
将是对象的二进制图像,radiusRange
是一个两元素数组,它指定在图像中要检测的圆的最小半径和最大半径。输出为:centers
:一个N x 2
数组,它告诉您在图像中检测到的圆的每个中心的(x,y)
坐标-x
是列,y
是行。radii
:对于检测到的每个对应中心,这也给出了检测到的每个圆的半径这是一个N x 1
数组。您可能会发现
imfindcircles
的其他参数很有用,例如Sensitivity
更高的灵敏度意味着它能够检测出更不均匀的圆形,比如你在图像中显示的内容它们不是完美的圆形,但它们是圆形的默认灵敏度为0.85我把它设为0.9以获得好的结果另外,在你的图片中,我发现半径从50像素到150像素不等因此,我这样做了:im = im2bw(imread('http://dennlinger.bplaced.net/t06-4.jpg'));
[centers,radii] = imfindcircles(im, [50 150], 'Sensitivity', 0.9);
第一行代码直接从StackOverflow读取图像我还将其转换为
logical
或真正的黑白,因为您上传的图像类型为uint8
此图像存储在im
中接下来,在我们描述的方法中调用imfindcircles
。现在,如果我们想可视化检测到的圆,只需使用
imshow
来显示图像,然后使用viscircles
来绘制图像中的圆。imshow(im);
viscircles(centers, radii, 'DrawBackgroundCircle', false);
viscircles
默认情况下,在轮廓上绘制背景为白色的圆我想禁用这个,因为你的图像有白色圆圈,我不想显示假轮廓这就是我用上面的代码得到的:因此,您可以从中得到
centers
和radii
变量centers
将给出每个检测圆的中心,radii
将告诉您每个圆的半径。现在,如果您想模拟
regionprops
正在做的事情,我们可以迭代所有检测到的圆,并将它们物理地绘制到一个2D地图上,在这个地图上每个圆都会被一个ID号标记因此,我们可以这样做:[X,Y] = meshgrid(1:size(im,2), 1:size(im,1));
IDs = zeros(size(im));
for idx = 1 : numel(radii)
r = radii(idx);
cen = centers(idx,:);
loc = (X - cen(1)).^2 + (Y - cen(2)).^2 <= r^2;
IDs(loc) = idx;
end
我们首先使用
meshgrid
定义一个点的矩形网格,并初始化一个与图像大小相同的所有零的IDs数组接下来,对于每一对半径和每一个圆的中心,我们定义了一个在这个点上以中心为中心的圆,这个点延伸到给定的半径然后,我们将它们用作IDs数组中的位置,并将其设置为该特定圆的唯一IDIDs
的结果将类似于bwlabel
的输出因此,如果要提取idx
圆所在的位置,可以执行以下操作:cir = IDs == idx;
出于演示目的,这是当我们缩放IDs以使其在
[0-255]
范围内适合可见性时IDs数组的外观:imshow(IDs, []);
因此,不同灰度的每个阴影圆表示用
imfindcircles
检测到的唯一圆。然而,对于某些硬币来说,灰色的阴影可能有点模棱两可,因为这与背景融合在一起另一种可视化方法是对IDs数组应用不同的颜色映射我们可以尝试使用
cool
颜色图,颜色总数为背景的唯一圆圈数+1因此,我们可以这样做:cmap = cool(numel(radii) + 1);
RGB = ind2rgb(IDs, cmap);
imshow(RGB);
上面的代码将创建一个颜色映射,以便每个圆映射到
cool
颜色映射中的唯一颜色下一行应用一个映射,其中每个ID与ind2rgb
的颜色关联,最后显示图像。这就是我们得到的:
关于matlab - Matlab:单独的连接组件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27809254/