文档

检测和测量图像中的圆形物体

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

步骤1:加载图像

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

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

除了有很多圆需要检测之外,从圆检测的角度来看,这张图中还有一些有趣的事情:

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

  2. 请注意,一些芯片是彼此叠在一起的,而另一些芯片则靠得很近,几乎相互接触。物体边界重叠和物体遮挡通常是物体检测的挑战。

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

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

D = imdistline;

imdistline创建一个可拖动的工具,可以移动以适应芯片,并且可以读取数字以获得其半径的大致估计。大多数芯片的半径在21-23像素之间。为了确保起见,使用稍微大一点的半径范围,20-25像素。在那之前把imdistline工具。

删除(d)

步骤3:初步尝试寻找圆

调用imfindcircles在此图像上搜索半径为[2025]像素。在此之前,最好先问一下物体比背景亮还是暗。为了回答这个问题,看看这张图片的灰度版本。

Gray_image = rgb2gray(rgb);imshow (gray_image)

背景相当明亮,大部分芯片比背景暗。但是,默认情况下,imfindcircles查找比背景亮的圆形物体。所以,设置参数'ObjectPolarity'为'dark' inimfindcircles寻找黑眼圈。

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

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

第四步:提高检测灵敏度

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

[圆心,半径]= imfindcircles(rgb,[2025],“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。

[圆心,半径]= imfindcircles(rgb,[2025],“ObjectPolarity”“黑暗”“敏感”, 0.92);长度(中心)
Ans = 16

所以增加“灵敏度”会让我们得到更多的圆。再把这些圆画在图像上。

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

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

这个结果看起来更好。imfindcircles有两种不同的方法来找圆。到目前为止,默认方法称为相位编码方法,检测圆。还有另一种方法,通常被称为两级方法中提供的方法imfindcircles.使用两阶段法并展示结果。

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

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

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

中的两个方法imfindcircles准确地找到部分可见(遮挡)芯片的中心和半径。

第七步:为什么还是会漏掉一些圆圈?

看看最后的结果,很奇怪imfindcircles在图像中找不到黄色的碎片。黄色的芯片与背景没有强烈的对比。事实上,它们似乎与背景的强度非常相似。有没有可能这些黄色的碎片并不像人们想象的那样真的比背景“更暗”?要确认,请再次显示此图像的灰度版本。

imshow (gray_image)

步骤8:在图片中找到“明亮”的圆圈

与背景相比,黄色碎片几乎具有相同的强度,甚至可能更亮。因此,要检测黄色芯片,将“ObjectPolarity”更改为“bright”。

[centersBright,radiiBright] = imfindcircles(rgb,[2025],“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,[2025],“ObjectPolarity”“光明”“敏感”, 0.92,“EdgeThreshold”, 0.1);delete(hBright) hBright = viscircles(centersBright, radiiBright,“颜色”“b”);

步骤11:画“暗”和“亮”的圆圈在一起

现在imfindcircles找到了所有黄色的,还有一个绿色的。用蓝色绘制这些芯片,与之前发现的其他芯片(将“ObjectPolarity”设置为“dark”)一起用红色绘制。

H = viscircles(圆心,半径);

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

寻圈快乐!

这个话题有帮助吗?