检测和测量图像中的圆形对象

这个例子展示了如何使用imfindcircles自动检测图像中的圆或圆形物体。它还展示了viscircles使探测到的圆形象化。

步骤1:加载图像

这个例子使用了一个各种颜色的圆形塑料碎片的图像。

rgb = imread (“coloredChips.png”);imshow (rgb)

除了有大量的圆要检测,从圆检测的角度来看,这幅图中还有一些有趣的事情:

  1. 有不同颜色的碎片,与背景有不同的对比。在一端,蓝色和红色在这个背景上有强烈的对比。另一方面,一些黄色的筹码与背景的对比并不好。

  2. 请注意一些芯片是如何相互叠在一起的,而另一些则紧密地挨在一起,几乎是相互接触的。物体边界重叠和物体遮挡是物体检测的难点。

步骤2:确定搜索圆的半径范围

imfindcircles需要一个半径范围来搜索圆圈。找到合适的半径范围的一个快速方法是使用交互式工具imdistline以得到各种物体半径的近似估计。

d = imdistline;

imdistline创建一个可拖动的工具,可以移动到适合的芯片和数字可以读取,以获得其半径的近似估计。大多数芯片的半径在21-23像素之间。使用稍微大一点的半径范围20-25像素,只是为了确保。在此之前,移除imdistline工具。

删除(d)

第三步:初步尝试寻找圆圈

调用imfindcircles在这张搜索半径为[20 25]像素的图像上。在那之前,问一下物体比背景亮还是暗是一个好习惯。要回答这个问题,看看这个图像的灰度版本。

gray_image = rgb2gray (rgb);imshow (gray_image)

背景相当明亮,大多数芯片都比背景暗。但是,默认情况下,imfindcircles寻找比背景更亮的圆形物体。因此,将参数object极性设置为“dark”imfindcircles寻找黑眼圈。

[中心,半径]= imfindcircles(rgb,[20 25],“ObjectPolarity”“黑暗”
[]半径= []

注意,输出中心半径都是空的,也就是说没有发现圆圈。这种情况经常发生,因为imfindcircles是一个圆探测器,与大多数探测器类似,imfindcircles有一个内部检测阈值这决定了它的灵敏度。简单地说,它意味着探测器在某一(圆)检测中的置信度必须大于某一水平,然后才被认为是一个有效的检测。imfindcircles有一个参数“灵敏度”,可以用来控制这个内部阈值,从而控制算法的灵敏度。“灵敏度”值越高,检测阈值越低,可以检测到更多的圆。这与家庭安全系统中使用的运动探测器的灵敏度控制类似。

第四步:增加检测灵敏度

回到芯片图像,有可能在默认灵敏度水平下所有的圆都低于内部阈值,这就是为什么没有检测到圆。默认情况下,'Sensitivity'是一个介于0和1之间的数字,设置为0.85。将“灵敏度”提高到0.9。

[中心,半径]= 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找到了一些圆圈,准确地说是八个。中心包含圆心的位置和半径包含这些圆的估计半径。

步骤5:在图像上画圆圈

功能viscircles可用于在图像上画圆。输出变量中心半径imfindcircles可以直接传递给viscircles

Imshow (rgb) h = viscircles(圆心,半径);

圆心的位置似乎是正确的,其相应的半径似乎与实际芯片匹配得很好。但还是少了不少筹码。试着把“灵敏度”提高到0.92。

[中心,半径]= imfindcircles(rgb,[20 25],“ObjectPolarity”“黑暗”...“敏感”, 0.92);长度(中心)
ans = 16

所以增加“敏感性”会让我们有更多的圆圈。在图像上再次画出这些圆圈。

删除(h)%删除先前绘制的圆圈h = viscircles(中心、半径);

第六步:使用第二种方法(两步)寻找圆圈

这个结果看起来更好。imfindcircles有两种不同的求圆方法。到目前为止,默认的方法叫做相位编码方法,用于检测圆圈。有另一种方法,普遍称为两阶段方法,该方法在imfindcircles.使用两阶段方法并展示结果。

[中心,半径]= imfindcircles(rgb,[20 25],“ObjectPolarity”“黑暗”...“敏感”, 0.92,“方法”“二级”);Delete (h) h = viscircles(圆心,半径);

两阶段法检测更多的圆,灵敏度为0.92。总的来说,这两种方法是互补的,因为它们有不同的优势。相位编码方法通常比两级方法更快,对噪声的鲁棒性略强。但它可能还需要更高的“灵敏度”水平,才能获得与两阶段法相同数量的检测。例如,如果“灵敏度”水平提高到0.95,相位编码方法也能找到相同的芯片。

[中心,半径]= imfindcircles(rgb,[20 25],“ObjectPolarity”“黑暗”...“敏感”, 0.95);删除(h) viscircles(中心、半径);

注意,这两个方法imfindcircles准确找到部分可见(闭塞)芯片的中心和半径。

第七步:为什么有些圈子仍然被忽略?

看看最后的结果,很奇怪imfindcircles没有在图像中找到黄色的芯片。黄股与背景没有强烈的对比。事实上,它们的强度和背景非常相似。有没有可能黄色的筹码并不是真的像假设的那样比背景“暗”?为了确认,再次显示这个图像的灰度版本。

imshow (gray_image)

第八步:在图片中找到“明亮的”圆圈

与背景相比,黄色的筹码几乎是同样的强度,甚至可能更亮。因此,要检测黄色的芯片,将“object极性”改为“亮”。

[centersBright,radiiBright] = imfindcircles(rgb,[20 25],...“ObjectPolarity”“光明”“敏感”, 0.92);

第九步:用不同的颜色画出明亮的圆圈

画出明亮的中的“颜色”参数可以改变颜色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找到所有黄色的,还有一个绿色的。用蓝色绘制这些芯片,以及之前发现的其他芯片(将“object极性”设置为“暗”),用红色。

h = viscircles(中心、半径);

所有的圆都被检测出来了。最后,应该注意的是,在检测中更积极地改变参数可能会发现更多的圆,但它也增加了检测错误圆的可能性。在可发现的真实圆的数量(检测率)和与它们一起发现的错误圆的数量(误报警率)之间存在一种权衡。

圆狩猎快乐!

另请参阅

|

相关话题