主要内容

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

此示例演示如何自动检测图像中的圆或圆形对象,并可视化检测到的圆。

步骤1:加载图像

阅读并显示各种颜色的圆形塑料芯片的图像。除了有足够的圈子来检测,来自圆形检测点的此图像中有一些有趣的事情发生:

  1. 有不同颜色的芯片,这对背景具有不同的对比。在一端,蓝色和红色的在这个背景上具有强烈的对比。另一端,一些黄色芯片与背景上没有鲜明。

  2. 请注意一些筹码如何彼此顶部,其他一些靠近在一起,几乎互相触摸的其他芯片。重叠的对象边界和对象遮挡通常是对象检测的具有挑战性的场景。

rgb=imread('coloredChips.png'); imshow(rgb)

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

使用画直线作用在切屑的近似直径上画一条线。

d=抽绳;

线ROI的长度是芯片的直径。典型的芯片直径在40到50像素之间。

pos=d.位置;diffPos=diff(pos);直径=hypot(diffPos(1),diffPos(2))
直径=45.3448

步骤3:初始尝试查找圆

这个imfindcircles.函数搜索半径范围内的圆。搜索半径范围为20到25像素的圆。在此之前,最好询问对象比背景亮还是暗。要回答此问题,请查看此图像的灰度版本。

灰度图像=rgb2gray(rgb);imshow(灰度图像)

背景非常明亮,大部分芯片比背景更暗。但是,默认情况下,imfindcircles.找到比背景更亮的圆形物体。所以,将参数“objorpolarity”设置为“黑暗”imfindcircles.寻找黑眼圈。

[中心,半径]=imfind圆(rgb,[20 25],“对象极性”,'黑暗的')
中心=[]半径=[]

请注意,输出中心radii.是空的,这意味着没有找到圆。这种情况经常发生,因为imfindcircles.是一个圆圈探测器,和类似于大多数探测器,imfindcircles.有一个内部的检测阈值这决定了它的敏感性。简单来说,它意味着检测器对某个(圆圈)检测的置信度必须大于某个级别之前被认为是一个有效的侦查imfindcircles.具有参数“灵敏度”,可用于控制该内部阈值,从而控制算法的灵敏度。“灵敏度”值越高,检测阈值越低,检测到的圆圈越多。这类似于家庭安全系统中使用的运动探测器的灵敏度控制。

步骤4:提高检测灵敏度

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

[中心,半径]=imfind圆(rgb,[20 25],“对象极性”,'黑暗的',...'灵敏度',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 297.0077 243.97/323.9893 166.4538 271166。4538 297166/2538 297197731229939709929920990
radii =8×123.1604 22.5710 22.9576 23.7356 22.9551 22.9995 22.9055 23.0298

这次imfindcircles.找到了一些圆圈-准确地说是八个。中心包含圆形中心的位置和radii.包含这些圆的估计半径。

第5步:在图像上绘制圆圈

这个函数viscircles.可用于在图像上绘制圆。输出变量中心radii.imfindcircles.可以直接传递给viscircles..

imshow(rgb)h=内圆(中心、半径);

圆心的位置似乎正确,其相应的半径似乎与实际切屑非常匹配。但仍有相当多的切屑丢失。请尝试将“灵敏度”进一步提高到0.92。

[中心,半径]=imfind圆(rgb,[20 25],“对象极性”,'黑暗的',...'灵敏度',0.92); 长度(中心)
ans = 16.

因此,增加“灵敏度”会让我们看到更多的圆圈。在图像上再次绘制这些圆圈。

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

步骤6:使用第二种方法(两级)来查找圆圈

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

[中心,半径]=imfind圆(rgb,[20 25],“对象极性”,'黑暗的',...'灵敏度',0.92,“方法”,'扭曲');删除(h)h = Viscircles(中心,半径);

两级方法在0.92的灵敏度下检测更多圆圈。通常,这两种方法是互补的,它们具有不同的优点。相位编码方法通常比两级方法更快,更易于稳健。但它也可能需要更高的“敏感性”水平来获得与两级方法相同的检测。例如,相位编码方法如果“灵敏度”级别提高,则发现相同的芯片,如0.95。

[中心,半径]=imfind圆(rgb,[20 25],“对象极性”,'黑暗的',...'灵敏度',0.95); 删除(h)内圆(中心、半径);

请注意,中的两个方法imfindcircles.准确找到部分可见(遮挡)切屑的中心和半径。

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

看着最后的结果,很好奇imfindcircles.未在图像中找到黄色的碎片。黄色芯片与背景对比度不强。事实上,它们的强度似乎与背景非常相似。是否有可能,黄色的芯片并不像假设的那样真的比背景“暗”?若要确认,请再次显示此图像的灰度版本。

imshow(gray_image)

第8步:在图像中找到“明亮”圈子

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

[centersBright,radibright]=imfind圆(rgb,[20 25],...“对象极性”,'明亮的','灵敏度',0.92);

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

画出明亮的通过更改中的“颜色”参数,以不同的颜色圆viscircles..

imshow(rgb)hBright=内圆(中心光、半径光、,'颜色',“b”);

请注意,三枚失踪的黄筹码已经找到,但仍有一枚黄筹码下落不明。这些黄色筹码很难找到,因为它们没有脱颖而出以及这个背景上的其他人。

第10步:降低'Edgethreshold'的值

还有另一个参数imfindcircles.这里可能有用,即'Edgethreshold'。找到圈子,imfindcircles.仅使用图像中的边缘像素。这些边缘像素基本上是具有高梯度值的像素。'edgethreshold'参数控制如何高的一个像素上的梯度值必须在它被认为是边缘像素并包含在计算中之前。这个参数的高值(接近1)将只允许包含强边(更高的梯度值),而低值(接近0)更宽容,甚至包括计算中较弱的边(更低的梯度值)。在缺少黄色芯片的情况下,由于对比度较低,一些边界像素(在芯片的圆周上)预计有较低的梯度值。因此,降低“EdgeThreshold”参数,以确保计算中包含黄色芯片的大多数边缘像素。

[Centsbright,Radiibright,Metricbright] = IMFindcircles(RGB,[20 25],...“对象极性”,'明亮的','灵敏度',0.92,“EdgeThreshold”,0.1); 删除(hBright)hBright=VIS圆(中心亮度、半径亮度、,'颜色',“b”);

第11步:画“暗”和“亮”的圆圈

现在imfindcircles.找到所有的黄色,也是一个绿色的。用早期发现的其他芯片绘制蓝色的这些芯片(用'objectpolarity'设置为'黑暗'),红色。

H = Viscircles(中心,半径);

所有圆圈都被检测到。最后一个词 - 应该注意的是,在检测中改变参数更具侵略性可能会找到更多圆圈,但它也增加了检测假圆的可能性。在可以找到(检测率)的真圆数之间存在权衡,以及与它们一起发现的虚假圆数(误报率)。

幸福的圈狩猎!

另见

|

相关的话题