检测和测量图像中的圆形目标
此示例说明如何自动检测图像中的圆或圆形目标并可视化检测到的圆。
步骤 1:加载图像
读取并显示包含各种颜色的圆形塑料片的图像。除了有大量要检测的圆之外,从圆检测的角度来看,此图像还有一些有趣的特点:
有不同颜色的塑料片,它们相对于背景有不同对比度。一方面,蓝色和红色塑料片在此背景上形成强烈的对比。另一方面,一些黄色塑料片与背景的对比不明显。
请注意一些塑料片重叠在一起,而另一些塑料片则靠得很近,几乎互相接触。对于目标检测来说,场景中存在重叠的对象边缘和对象遮挡通常具有挑战性。
rgb = imread("coloredChips.png");
imshow(rgb)
步骤 2:确定搜索圆的半径范围
使用 drawline
函数找到合适的圆半径范围。在塑料片的近似直径上绘制一条线。
d = drawline;
线 ROI 的长度就是塑料片的直径。通常的塑料片的直径在 40 到 50 个像素的范围内。
pos = d.Position; diffPos = diff(pos); diameter = hypot(diffPos(1),diffPos(2))
diameter = 45
步骤 3:寻找圆的初步尝试
imfindcircles
函数搜索符合半径范围的圆。搜索半径在 20 到 25 个像素范围内的圆。在此之前,最好要清楚对象是比背景亮还是比背景暗。要回答该问题,请看此图像的灰度版本。
gray_image = im2gray(rgb); imshow(gray_image)
背景相当亮,大多数塑料片比背景暗。但是,默认情况下,imfindcircles
会找到比背景亮的圆形目标。因此,在 imfindcircles
中将 ObjectPolarity
名称-值参量指定为 "dark"
以搜索较暗的圆。
[centers,radii] = imfindcircles(rgb,[20 25],ObjectPolarity="dark")
centers = [] radii = []
请注意,输出 centers
和 radii
为空,这意味着未找到圆。这种情况经常发生,因为 imfindcircles
是圆形检测器,与大多数检测器类似,imfindcircles
有内部检测阈值决定其敏感度。简而言之,这意味着检测器对某个(圆形)检测的信心必须大于某个水平,才将其视为有效检测。imfindcircles
有 Sensitivity
名称-值参量,可用于控制此内部阈值,从而控制算法的敏感度。Sensitivity
值越高,检测阈值设置得越低,并导致检测到更多圆。这类似于家庭安全系统中使用的运动检测器的敏感度控制。
步骤 4:提高检测敏感度
回到塑料片图像,在默认敏感度水平下,可能所有圆都低于内部阈值,因此未检测到圆。Sensitivity
是介于 0 和 1 之间的数字,默认设置为 0.85。将 Sensitivity
提高到 0.9。
[centers,radii] = imfindcircles(rgb,[20 25],ObjectPolarity="dark", ... Sensitivity=0.9)
centers = 8×2
146.1895 198.5824
328.8132 135.5883
130.3134 43.8039
175.2698 297.0583
312.2831 192.3709
327.1316 297.0077
243.9893 166.4538
271.5873 280.8920
radii = 8×1
23.1604
22.5710
22.9576
23.7356
22.9551
22.9995
22.9055
23.0298
这次,imfindcircles
发现了一些圆 - 准确地说是八个。centers
包含圆心的位置,radii
包含这些圆的估计半径。
步骤 5:在图像上绘制圆
函数 viscircles
可用于在图像上绘制圆。来自 imfindcircles
的输出变量 centers
和 radii
可以直接传递给 viscircles
。
imshow(rgb) h = viscircles(centers,radii);
圆心似乎定位正确,它们对应的半径似乎与实际塑料片匹配良好。但仍未检测到相当多的塑料片。请尝试将 Sensitivity
提高到 0.92。
[centers,radii] = imfindcircles(rgb,[20 25],ObjectPolarity="dark", ... Sensitivity=0.92); length(centers)
ans = 16
提高 Sensitivity
会找到更多的圆。再次在图像上绘制这些圆。
delete(h) % Delete previously drawn circles
h = viscircles(centers,radii);
步骤 6:使用第二种方法(两阶段)寻找圆
此方法的结果看起来更好。imfindcircles
有两种不同寻找圆的方法。到当前为止,默认方法(称为相位编码方法)用于检测圆。在 imfindcircles
中还可以使用另一种方法,通常称为两阶段方法。使用两阶段方法并显示结果。
[centers,radii] = imfindcircles(rgb,[20 25],ObjectPolarity="dark", ... Sensitivity=0.92,Method="twostage"); delete(h) h = viscircles(centers,radii);
两阶段方法在 Sensitivity
值为 0.92 处检测到更多圆。一般来说,这两种方法是互补的,因为它们各有优点。相位编码方法通常比两阶段方法更快,抗噪声的稳定性稍强。但是,它也可能需要更高的 Sensitivity
水平才能实现与两阶段方法相同数量的检测。例如,如果 Sensitivity
水平提高到 0.95,相位编码方法也会找到相同的塑料片。
[centers,radii] = imfindcircles(rgb,[20 25],ObjectPolarity="dark", ... Sensitivity=0.95); delete(h) viscircles(centers,radii);
请注意,imfindcircles
中的两种方法都能准确找到部分可见(遮挡)塑料片的中心和半径。
步骤 7:为什么有些圆仍检测不到?
查看最后一个结果,很奇怪 imfindcircles
没有在图像中找到黄色塑料片。黄色塑料片与背景的对比不够强烈。事实上,它们看起来和背景的强度非常相似。是不是黄色塑料片并没有想象中的那样比背景“更暗”?要确认这一点,请再次显示该图像的灰度版本。
imshow(gray_image)
步骤 8:在图像中找到“明亮”的圆
与背景相比,黄色塑料片的强度几乎相同,甚至更亮。因此,要检测黄色塑料片,请将 ObjectPolarity
更改为 "bright"
。
[centersBright,radiiBright] = imfindcircles(rgb,[20 25], ... ObjectPolarity="bright",Sensitivity=0.92);
步骤 9:用不同颜色绘制“Bright”圆
通过更改 viscircles
中的 Color
名称-值参量,以不同颜色绘制明亮的圆。
imshow(rgb)
hBright = viscircles(centersBright,radiiBright,Color="b");
请注意,找到了三个原先未检测到的黄色塑料片,但仍有黄色塑料片未检测到。这些黄色塑料片很难检测到,因为在这种背景下,它们没有呈现出与众不同。
步骤 10:降低 EdgeThreshold
的值
在这里还可以使用 imfindcircles
中的另一个名称-值参量,即 EdgeThreshold
。要查找圆,imfindcircles
仅使用图像中的边缘像素。这些边缘像素基本上是具有高梯度值的像素。EdgeThreshold
名称-值参量控制像素的梯度值必须有多高,才能将其视为边缘像素并包含在计算中。该参数的高值(更接近 1)只允许包含强边缘(较高梯度值),而低值(更接近 0)的宽容度更高,可在计算中包含较弱的边缘(较低梯度值)。对于检测不到黄色塑料片的情况,是因为对比度低,一些边界像素(在塑料片的圆周上)预期具有低梯度值。因此,请降低 EdgeThreshold
值,以确保黄色塑料片的大多数边缘像素都包含在计算中。
[centersBright,radiiBright,metricBright] = imfindcircles(rgb,[20 25], ... ObjectPolarity="bright",Sensitivity=0.92,EdgeThreshold=0.1); delete(hBright) hBright = viscircles(centersBright,radiiBright,Color="b");
步骤 11:同时绘制“暗”和“亮”圆
现在 imfindcircles
找到了所有黄色圆,还找到了一个绿色圆。用蓝色绘制这些塑料片,用红色绘制之前发现的其他塑料片(ObjectPolarity
设置为 "dark"
)。
h = viscircles(centers,radii);
所有圆都被检测到。最后 - 应注意,在检测中更激进地更改参数可能会发现更多圆,但也会增加检测到假圆的可能性。需要在可找到的真圆数量(检测率)和用它们找到的假圆数量(虚警率)之间实现某种平衡。
祝您能顺利检测到圆!
另请参阅
imfindcircles
| circles2mask
| viscircles