检测和测量图像中的圆形物体
这个例子展示了如何自动检测图像中的圆或圆形对象,并将检测到的圆可视化。
步骤1:加载图像
阅读并显示各种颜色的圆形塑料芯片的图像。除了有很多圆圈可以检测,从圆圈检测的角度来看,这张图中还有一些有趣的事情:
有不同颜色的芯片,相对于背景有不同的对比。在一端,蓝色和红色的在这个背景上有强烈的对比。另一方面,一些黄色的芯片与背景的对比不太好。
请注意,一些芯片是如何相互叠加的,而另一些芯片则靠得很近,几乎相互接触。重叠对象边界和对象遮挡通常是目标检测的挑战性场景。
RGB = imread(“coloredChips.png”);imshow (rgb)
第二步:确定搜索圆的半径范围
函数找到圆的适当半径范围画直线
函数。在芯片的大致直径上画一条线。
D =抽线;
线ROI的长度是芯片的直径。典型的芯片直径在40到50像素之间。
pos = d.位置;diffPos = diff(pos);直径= hypot(diffPos(1),diffPos(2)))
直径= 45.3448
第三步:最初尝试寻找圆
的imfindcircles
函数搜索半径范围内的圆。搜索半径在20到25像素范围内的圆。在此之前,一个很好的做法是询问物体是否比背景更亮或更暗。要回答这个问题,请看这张图片的灰度版本。
Gray_image = rgb2gray(rgb);imshow (gray_image)
背景相当明亮,大多数芯片比背景暗。但是,默认情况下,imfindcircles
寻找比背景更亮的圆形物体。因此,将参数“ObjectPolarity”设置为“dark”imfindcircles
寻找黑眼圈。
[centers,radii] = imfindcircles(rgb,[20 25],“ObjectPolarity”,“黑暗”)
中心=[]半径= []
请注意输出中心
而且半径
为空,这意味着没有找到任何圆圈。这种情况经常发生,因为imfindcircles
是一个圆探测器,与大多数探测器类似,imfindcircles
有一个内在的检测阈值这决定了它的敏感性。简单来说,它意味着探测器在某个(圆)检测中的置信度必须大于某个水平,然后才被认为是一个有效的检测。imfindcircles
有一个参数“灵敏度”,可以用来控制这个内部阈值,从而控制算法的灵敏度。较高的“灵敏度”值将检测阈值设置为较低,并导致检测到更多的圆。这类似于家庭安全系统中使用的运动探测器的灵敏度控制。
第四步:提高检测灵敏度
回到芯片图像,有可能在默认灵敏度级别下,所有的圆圈都低于内部阈值,这就是为什么没有检测到圆圈。默认情况下,“灵敏度”是一个0到1之间的数字,被设置为0.85。增加灵敏度到0.9。
[centers,radii] = imfindcircles(rgb,[20 25],“ObjectPolarity”,“黑暗”,...“敏感”, 0.9)
中心=8×2146.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
半径=8×123.1604 22.5710 22.9576 23.7356 22.9551 22.9995 22.9055 23.0298
这一次imfindcircles
发现了一些圆圈,准确地说是八个。中心
包含圆中心和的位置半径
包含这些圆的估计半径。
第五步:在图像上画圆
这个函数viscircles
可用于在图像上画圆。输出变量中心
而且半径
从imfindcircles
可以直接传递给viscircles
.
Imshow (rgb) h = viscircles(中心,半径);
圆圈中心的位置似乎是正确的,它们相应的半径似乎与实际的芯片很匹配。但还是少了不少筹码。试着增加灵敏度,到0.92。
[centers,radii] = imfindcircles(rgb,[20 25],“ObjectPolarity”,“黑暗”,...“敏感”, 0.92);长度(中心)
Ans = 16
所以增加“敏感度”会让我们得到更多的圆圈。再把这些圆画在图像上。
删除(h)删除先前绘制的圆H = viscircles(中心,半径);
第六步:使用第二种方法(两阶段)寻找圆
这个结果看起来更好。imfindcircles
有两种找圆的方法。到目前为止的默认方法,称为相位编码方法,用于检测圆。还有另一种方法,通常称为两级中可用的方法imfindcircles
.使用两阶段方法并展示结果。
[centers,radii] = imfindcircles(rgb,[20 25],“ObjectPolarity”,“黑暗”,...“敏感”, 0.92,“方法”,“二级”);删除(h) h = viscircles(中心,半径);
两阶段方法检测更多的圆,灵敏度为0.92。总的来说,这两种方法是互补的,因为它们有不同的长处。相位编码方法通常比两阶段方法更快,对噪声的鲁棒性稍强。但它也可能需要更高的“灵敏度”水平,以获得与两阶段方法相同的检测数量。例如,如果灵敏度提高到0.95,相位编码方法也会发现相同的芯片。
[centers,radii] = imfindcircles(rgb,[20 25],“ObjectPolarity”,“黑暗”,...“敏感”, 0.95);删除(h) viscircles(中心、半径);
中的两个方法请注意imfindcircles
准确地找到部分可见(遮挡)芯片的中心和半径。
7 .为什么有些圆圈还是被忽略了?
看看最后的结果,令人好奇的是imfindcircles
在图像中找不到黄色的筹码。黄色的筹码与背景没有强烈的对比。事实上,它们似乎与背景的强度非常相似。有没有可能,黄色的筹码并不像我们假设的那样真的比背景“暗”?要确认,请再次显示此图像的灰度版本。
imshow (gray_image)
第八步:在图片中找到“明亮的”圆圈
与背景相比,黄色碎片的强度几乎相同,甚至可能更亮。因此,要检测黄色芯片,将“ObjectPolarity”更改为“bright”。
[centersBright,radiiBright] = imfindcircles(rgb,[20 25],...“ObjectPolarity”,“光明”,“敏感”, 0.92);
第九步:画不同颜色的“亮”圆
画出明亮的中,通过改变“color”参数,使圆圈变成不同的颜色viscircles
.
imshow(rgb) hBright = viscircles(centersBright, radiiBright,“颜色”,“b”);
请注意,丢失的黄色筹码中有三枚已经找到,但仍然丢失了一枚黄色筹码。这些黄色的碎片很难找到,因为它们不存在脱颖而出以及其他有此背景的人。
步骤10:降低“EdgeThreshold”的值
这里还有一个参数imfindcircles
这里可能有用,即'EdgeThreshold'。为了找到圆,imfindcircles
仅使用图像中的边缘像素。这些边缘像素本质上是具有高梯度值的像素。“EdgeThreshold”参数控制如何操作高在一个像素被认为是边缘像素并包含在计算中之前,它的梯度值必须是。该参数的高值(接近1)将只允许包括强边(更高的梯度值),而低值(接近0)则更允许,甚至包括计算中较弱的边(较低的梯度值)。在缺少黄色芯片的情况下,由于对比度较低,一些边界像素(在芯片的周长上)预计具有低梯度值。因此,降低“EdgeThreshold”参数,以确保黄色芯片的大部分边缘像素都包含在计算中。
[centersBright,radiiBright,metricBright] = imfindcircles(rgb,[20 25],...“ObjectPolarity”,“光明”,“敏感”, 0.92,“EdgeThreshold”, 0.1);delete(hBright) hBright = viscircles(centersBright, radiiBright,“颜色”,“b”);
步骤11:在一起画“暗圈”和“亮圈”
现在imfindcircles
找到所有黄色的,还有一个绿色的。用蓝色绘制这些芯片,以及之前找到的其他芯片(将“ObjectPolarity”设置为“dark”),用红色。
H = viscircles(中心,半径);
所有的圆都被检测到。最后,需要注意的是,将参数更改为更积极的检测可能会发现更多的圆,但也会增加检测到假圆的可能性。可以发现的真圆数量(检出率)和发现的假圆数量(假报警率)之间存在权衡。
寻宝快乐!