欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

1.2 检测和测量图像中的圆形目标

发布时间:2025/4/16 编程问答 49 豆豆
生活随笔 收集整理的这篇文章主要介绍了 1.2 检测和测量图像中的圆形目标 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

此示例说明如何自动检测图像中的圆形目标并可视化检测到的圆。

步骤 1:加载图像
读取并显示包含各种颜色的圆形塑料片的图像。除了有大量要检测的圆之外,从圆检测的角度来看,此图像还有一些有趣的特点:

有不同颜色的塑料片,它们相对于背景有不同对比度。一方面,蓝色和红色塑料片在此背景上形成强烈的对比。另一方面,一些黄色塑料片与背景的对比不明显。

请注意一些塑料片重叠在一起,而另一些塑料片则靠得很近,几乎互相接触。对于目标检测来说,场景中存在重叠的对象边缘和对象遮挡通常具有挑战性。

rgb = imread('coloredChips.png'); %加载图像 imshow(rgb); title('coloredChips');

步骤 2:确定搜索圆的半径范围
使用 drawline 函数找到合适的圆半径范围。在塑料片的近似直径上绘制一条线。

rgb = imread('coloredChips.png'); %加载图像 imshow(rgb); title('coloredChips'); d = drawline; %使用 drawline 函数找到合适的圆半径范围 pos = d.Position; diffPos = diff(pos); diameter = hypot(diffPos(1),diffPos(2));

步骤 3:寻找圆的初步尝试
imfindcircles 函数搜索符合半径范围的圆。搜索半径在 20 到 25 个像素范围内的圆。在此之前,最好要清楚对象是比背景亮还是比背景暗。要回答该问题,请看此图像的灰度版本。

rgb = imread('coloredChips.png'); %加载图像 subplot(1,2,1); imshow(rgb); title('coloredChips'); %d = drawline; %使用 drawline 函数找到合适的圆半径范围 % pos = d.Position; % diffPos = diff(pos); % diameter = hypot(diffPos(1),diffPos(2)); gray_image = rgb2gray(rgb); %转为灰度图像 subplot(1,2,2); imshow(gray_image); %显示灰度图像 title('coloredChips灰度图');


背景相当亮,大多数塑料片比背景暗。但是,默认情况下,imfindcircles 会找到比背景亮的圆形目标。因此,在 imfindcircles 中将参数 ‘ObjectPolarity’ 设置为 ‘dark’ 以搜索较暗的圆。

>> [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark') %在 imfindcircles 中将参数 '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) %将 'Sensitivity' 设置为 0.9centers =146.1895 198.5824328.8132 135.5883130.3134 43.8039175.2698 297.0583312.2831 192.3709327.1316 297.0077243.9893 166.4538271.5873 280.8920radii =23.160422.571022.957623.735622.955122.999522.905523.0298

这次,imfindcircles 发现了一些圆 - 准确地说是八个centers 包含圆心的位置,radii 包含这些圆的估计半径。

步骤 5:在图像上绘制圆
函数 viscircles 可用于在图像上绘制圆。来自 imfindcircles 的输出变量 centers 和 radii 可以直接传递给 viscircles。

rgb = imread('coloredChips.png'); %加载图像 subplot(2,2,1); imshow(rgb); title('coloredChips');[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', 'Sensitivity',0.9); subplot(2,2,2); imshow(rgb); h = viscircles(centers,radii); %在图像上绘制灵敏度为0.9时找到的圆 title('灵敏度为0.9时找到的圆'); a1 = length(centers) %计算找到绘制灵敏度为0.9时的圆的个数[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', 'Sensitivity',0.92); subplot(2,2,3); imshow(rgb); h = viscircles(centers,radii); %在图像上绘制灵敏度为0.92时找到的圆 title('灵敏度为0.92时找到的圆'); a2 = length(centers) %计算找到绘制灵敏度为0.92时的圆的个数[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', 'Sensitivity',0.95); subplot(2,2,4); imshow(rgb); h = viscircles(centers,radii); %在图像上绘制灵敏度为0.95时找到的圆 title('灵敏度为0.95时找到的圆'); a3 = length(centers) %计算找到绘制灵敏度为0.95时的圆的个数%计算结果 a1 =8a2 =16a3 =22


步骤 6:使用第二种方法(两阶段)寻找圆
此方法的结果看起来更好。imfindcircles 有两种不同寻找圆的方法。到当前为止,默认方法(称为相位编码方法)用于检测圆。在 imfindcircles 中还可以使用另一种方法,通常称为两阶段方法。使用两阶段方法并显示结果。

rgb = imread('coloredChips.png'); %加载图像 subplot(2,2,1); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', 'Sensitivity',0.9); imshow(rgb); h = viscircles(centers,radii); %用相位编码方法在图像上绘制灵敏度为0.9时找到的圆 title('相位编码方法:灵敏度为0.9时找到的圆'); a1 = length(centers) %计算相位编码方法找到绘制灵敏度为0.9时的圆的个数subplot(2,2,2); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', 'Sensitivity',0.9,'Method','twostage'); imshow(rgb); h = viscircles(centers,radii); %用两阶段方法在图像上绘制灵敏度为0.9时找到的圆 title('两阶段方法:灵敏度为0.9时找到的圆'); a2 = length(centers) %计算两阶段方法找到绘制灵敏度为0.9时的圆的个数subplot(2,2,3); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', 'Sensitivity',0.92); imshow(rgb); h = viscircles(centers,radii); %用相位编码方法在图像上绘制灵敏度为0.92时找到的圆 title('相位编码方法:灵敏度为0.92时找到的圆'); a3 = length(centers) %计算相位编码方法找到绘制灵敏度为0.92时的圆的个数subplot(2,2,4); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', 'Sensitivity',0.92,'Method','twostage'); imshow(rgb); h = viscircles(centers,radii); %用两阶段方法在图像上绘制灵敏度为0.92时找到的圆 title('两阶段方法:灵敏度为0.92时找到的圆'); a4 = length(centers) %计算两阶段方法找到绘制灵敏度为0.92时的圆的个数!%统计结果 a1 =8 %相位编码方法找到绘制灵敏度为0.9时的圆的个数为8个a2 =22 %两阶段方法找到绘制灵敏度为0.9时的圆的个数为22个a3 =16 %相位编码方法找到绘制灵敏度为0.92时的圆的个数为16个a4 =22 %两阶段方法找到绘制灵敏度为0.92时的圆的个数为22个


两阶段方法使用敏感度0.9和 0.92 检测更多圆。一般来说,这两种方法是互补的,因为它们有不同优点。相位编码方法通常比两阶段方法更快,抗噪声的稳定性稍强。但是,它也可能需要更高的 ‘Sensitivity’ 水平才能实现与两阶段方法相同数量的检测。例如,如果 ‘Sensitivity’ 水平提高到 0.95,相位编码方法也会找到相同的塑料片。

rgb = imread('coloredChips.png'); %加载图像 subplot(1,2,1); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', 'Sensitivity',0.95); imshow(rgb); h = viscircles(centers,radii); %用相位编码方法在图像上绘制灵敏度为0.95时找到的圆 title('相位编码方法:灵敏度为0.95时找到的圆'); a1 = length(centers) %计算相位编码方法找到绘制灵敏度为0.95时的圆的个数subplot(1,2,2); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', 'Sensitivity',0.95,'Method','twostage'); imshow(rgb); h = viscircles(centers,radii); %用两阶段方法在图像上绘制灵敏度为0.95时找到的圆 title('两阶段方法:灵敏度为0.95时找到的圆'); a2 = length(centers) %计算两阶段方法找到绘制灵敏度为0.95时的圆的个数%统计结果 a1 =22 %相位编码方法找到绘制灵敏度为0.95时的圆的个数为22个a2 =22 %两阶段方法找到绘制灵敏度为0.95时的圆的个数为22个


请注意,imfindcircles 中的两种方法都能准确找到部分可见(遮挡)塑料片的中心和半径。

步骤 7:为什么有些圆仍检测不到?
查看最后一个结果,很奇怪 imfindcircles 没有在图像中找到黄色塑料片。黄色塑料片与背景的对比不够强烈。事实上,它们看起来和背景的强度非常相似。是不是黄色塑料片并没有想象中的那样比背景“更暗”?要确认这一点,请再次显示该图像的灰度版本。

步骤 8:在图像中找到“明亮”的圆
查看图像的灰度图,可发现与背景相比,黄色塑料片的强度几乎相同,甚至更亮。因此,要检测黄色塑料片,请将 ‘ObjectPolarity’ 更改为 ‘bright’。

rgb = imread('coloredChips.png'); %加载图像 subplot(1,2,1); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','bright', 'Sensitivity',0.92); imshow(rgb); h = viscircles(centers,radii); %用相位编码方法在图像上绘制灵敏度为0.92时找到的圆 title('相位编码方法:灵敏度为0.92时找到的圆'); a1 = length(centers) %计算相位编码方法找到绘制灵敏度为0.92时的圆的个数subplot(1,2,2); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','bright', 'Sensitivity',0.92,'Method','twostage'); imshow(rgb); h = viscircles(centers,radii); %用两阶段方法在图像上绘制灵敏度为0.92时找到的圆 title('两阶段方法:灵敏度为0.92时找到的圆'); a2 = length(centers) %计算两阶段方法找到绘制灵敏度为0.92时的圆的个数%统计结果 a1 =3a2 =5


步骤 9:用不同颜色绘制 ‘Bright’ 圆
通过更改 viscircles 中的 ‘Color’ 参数,以不同颜色绘制明亮的圆。

h = viscircles(centers,radii,'Color','b'); %将上面程序中的代码改为此代码即可


请注意,找到了三个原先未检测到的黄色塑料片,但仍有黄色塑料片未检测到。这些黄色塑料片很难检测到,因为在这种背景下,它们没有呈现出与众不同。

步骤 10:降低 ‘EdgeThreshold’ 的值
在这里还可以使用 imfindcircles 中的另一个参数,即 ‘EdgeThreshold’。要查找圆,imfindcircles 仅使用图像中的边缘像素。这些边缘像素基本上是具有高梯度值的像素。‘EdgeThreshold’ 参数控制像素的梯度值必须有多高,才能将其视为边缘像素并包含在计算中。该参数的高值(更接近 1)只允许包含强边缘(较高梯度值),而低值(更接近 0)的宽容度更高,可在计算中包含较弱的边缘(较低梯度值)。对于检测不到黄色塑料片的情况,是因为对比度低,一些边界像素(在塑料片的圆周上)预期具有低梯度值。因此,请降低 ‘EdgeThreshold’ 参数,以确保黄色塑料片的大多数边缘像素都包含在计算中。

rgb = imread('coloredChips.png'); %加载图像 subplot(1,2,1); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','bright', 'Sensitivity',0.92,'EdgeThreshold',0.1); imshow(rgb); h = viscircles(centers,radii,'Color','b'); %用相位编码方法在图像上绘制灵敏度为0.92时找到的圆 title('相位编码方法:灵敏度为0.92时找到的圆'); a1 = length(centers) %计算相位编码方法找到绘制灵敏度为0.92时的圆的个数subplot(1,2,2); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','bright', 'Sensitivity',0.92,'Method','twostage','EdgeThreshold',0.1); imshow(rgb); h = viscircles(centers,radii,'Color','b'); %用两阶段方法在图像上绘制灵敏度为0.92时找到的圆 title('两阶段方法:灵敏度为0.92时找到的圆'); a2 = length(centers) %计算两阶段方法找到绘制灵敏度为0.92时的圆的个数%统计结果 a1 =5a2 =6


步骤 11:同时绘制“暗”和“亮”圆
现在 imfindcircles 找到了所有黄色圆,还找到了一个绿色圆。用蓝色绘制这些塑料片,用红色绘制之前发现的其他塑料片(‘ObjectPolarity’ 设置为 ‘dark’)。

用相位编码法找到的所有圆

**

rgb = imread('coloredChips.png'); %加载图像 %subplot(2,2,1); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','bright', 'Sensitivity',0.92); imshow(rgb); h = viscircles(centers,radii,'color','b'); %用相位编码方法在图像上绘制灵敏度为0.92时找到"亮"圆 title('相位编码方法:灵敏度为0.92时找到的圆'); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', 'Sensitivity',0.92); h = viscircles(centers,radii); %找到"暗"圆 a1 = length(centers) %计算相位编码方法找到绘制灵敏度为0.92时的圆的个数%统计个数 a1 =16

用两阶段法找到的圆

rgb = imread('coloredChips.png'); %加载图像 %subplot(2,2,1); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','bright', 'Sensitivity',0.92,'Method','twostage'); imshow(rgb); h = viscircles(centers,radii,'color','b'); %用两阶段方法在图像上绘制灵敏度为0.92时找到"明"圆 title('两阶段方法:灵敏度为0.92时找到的圆'); [centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', 'Sensitivity',0.92,'Method','twostage'); h = viscircles(centers,radii); %找到"暗"圆 a2 = length(centers) %计算两阶段方法找到绘制灵敏度为0.92时的圆的个数%统计结果 a2 = 22

《新程序员》:云原生和全面数字化实践50位技术专家共同创作,文字、视频、音频交互阅读

总结

以上是生活随笔为你收集整理的1.2 检测和测量图像中的圆形目标的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。