如果您拥有图像处理工具箱,我还可以建议通过
imfindcircles
使用
圆形哈夫变换。然而,这需要至少R2012a版本,因此如果您没有它,这将无法工作。
为了完整起见,我将假设您已经安装了它。如果您不知道
霍夫变换是什么,那么它是一种在图像中查找直线的方法。圆形霍夫变换是一个特殊情况,旨在查找图像中的圆。
圆形霍夫变换的附加优势是它能够检测到图像中的部分圆。这意味着我们可以将连接的图像区域检测为单独的圆。您将如何调用
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中读取您的图像。我还将其转换为逻辑或真正的黑白,因为您上传的图像是
uint8
类型。这个图像存储在
im
中。接下来,我们按照所描述的方法调用
imfindcircles
。
现在,如果我们想要可视化检测到的圆,只需使用
imshow
显示您的图像,然后使用
viscircles
在图像中绘制圆。
imshow(im);
viscircles(centers, radii, 'DrawBackgroundCircle', false);
viscircles
默认在轮廓上方用白色背景绘制圆圈。我想要禁用这个选项,因为图片已经有了白色的圆圈,我不想显示虚假的轮廓。使用以上代码得到的结果如下:
![enter image description here](https://istack.dev59.com/oBwdA.webp)
因此,你可以从中获得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
定义一个矩形点网格,并初始化一个大小与图像相同的全零ID数组。接下来,对于每个圆的半径和中心点,我们定义以该点为中心向外延伸给定半径的圆。然后将这些位置用作ID数组中的位置,并将其设置为该特定圆的唯一ID。
IDs
的结果将类似于
bwlabel
的输出。因此,如果您想要提取
idx
圆的位置,您可以执行以下操作:
cir = IDs == idx
为了演示,这是当我们将ID缩放以适合可见的[0-255]
范围时,IDs数组的样子:
imshow(IDs, []);
![enter image description here](https://istack.dev59.com/SiIjt.webp)
因此,不同灰度阴影的每个阴影圆表示使用imfindcircles
检测到的唯一圆。
然而,对于某些硬币来说,灰度可能有点模糊,因为它与背景混合在一起。我们可以尝试将不同的颜色映射应用于ID数组以可视化它们。我们可以尝试使用cool
颜色映射,并将总颜色数设置为唯一圆的数量+1(包括背景)。因此,我们可以像这样做:
cmap = cool(numel(radii) + 1);
RGB = ind2rgb(IDs, cmap);
imshow(RGB);
以上代码将创建一个颜色映射,使得每个圆都被映射到
cool
颜色映射中的唯一颜色。接下来的代码行应用了一个映射,其中每个ID都与
ind2rgb
中的一种颜色相关联,并最终显示图像。
我们得到的结果如下所示:
![enter image description here](https://istack.dev59.com/FGail.webp)
imhmin
)或其他形式的平滑处理,然后再应用分水岭算子来简单解决。链接教程页面中的第三个示例正是这样做的。 - Cris Luengo