我试图找到圆的半径(或直径)。
我尝试使用圆形Hough转换(通过matlab的
imfindcircles(bw,[rmin rmax],'ObjectPolarity','bright')
),并拟合到圆形或椭圆形(对于噪声较小的数据,效果很好的自制函数,请参见下文)。 我还尝试了一些图像处理以获得更清晰的圆圈,例如,请参见以下内容:
se = strel('disk', 2);
bw = imdilate(bw, se);
bw = bwareaopen(bw,100000);
bw = edge(bw);
但是,当我将处理后的图像提供给任何一种技术(霍夫圆和椭圆\椭圆拟合)时,它们都无法以体面的方式检测到圆。
这是我写的寻圈器(matlab)
[行col] = find(bw);
轮廓= bwtraceboundary(bw,row(1),col(1)],'N',连接性,num_points) ;
x = contour(:,2);
y = contour(:,1);
% solve for parameters a, b, and c in the least-squares sense by
% using the backslash operator
abc = [x y ones(length(x),1)] \ -(x.^2+y.^2);
a = abc(1); b = abc(2); c = abc(3);
% calculate the location of the center and the radius
xc = -a/2;
yc = -b/2;
radius = sqrt((xc^2+yc^2)-c);
其他方法也将受到赞赏...
#1 楼
这是我的解决方案,它与@Yoda的想法很接近,但是我更改了一些步骤。标记所有像素,以使其7x7邻域中至少有6个像素
删除所有斑点,但最大的斑点
填充孔
应用边缘检测
使用霍夫变换查找圆
这是相关的Matlab代码。我在代码中将Hough变换用于圈子.m文件。
function FindCircle()
close all;
im = imread('C:\circle.png');
im = im(:,:,2);
ims = conv2(double(im), ones(7,7),'same');
imbw = ims>6;
figure;imshow(imbw);title('All pixels that there are at least 6 white pixels in their hood');
props = regionprops(imbw,'Area','PixelIdxList','MajorAxisLength','MinorAxisLength');
[~,indexOfMax] = max([props.Area]);
approximateRadius = props(indexOfMax).MajorAxisLength/2;
largestBlobIndexes = props(indexOfMax).PixelIdxList;
bw = false(size(im));
bw(largestBlobIndexes) = 1;
bw = imfill(bw,'holes');
figure;imshow(bw);title('Leaving only largest blob and filling holes');
figure;imshow(edge(bw));title('Edge detection');
radiuses = round ( (approximateRadius-5):0.5:(approximateRadius+5) );
h = circle_hough(edge(bw), radiuses,'same');
[~,maxIndex] = max(h(:));
[i,j,k] = ind2sub(size(h), maxIndex);
radius = radiuses(k);
center.x = j;
center.y = i;
figure;imshow(edge(bw));imellipse(gca,[center.x-radius center.y-radius 2*radius 2*radius]);
title('Final solution (Shown on edge image)');
figure;imshow(im);imellipse(gca,[center.x-radius center.y-radius 2*radius 2*radius]);
title('Final solution (Shown on initial image)');
end
评论
$ \ begingroup $
Hough变换在这里进行了什么操作,以使其求解并找到蓝色圆圈?是否在图像的不同位置投影了许多不同半径的圆,并找到最合适的圆?
$ \ endgroup $
–太空
2012年11月8日,下午2:26
$ \ begingroup $
@Mohammad,它是通常的圆形探测器。它使用合并和投票。
$ \ endgroup $
–安德烈(Andrey Rubshtein)
2012年11月8日在8:18
$ \ begingroup $
您也可以在此答案的第一步之后使用快速径向对称变换(FRST)。
$ \ endgroup $
– Geniedesalpages
14-10-21在15:28
#2 楼
使用图像处理非常简单。以下是Mathematica中概念的证明。您必须将其转换为MATLAB。首先,修剪轴并仅保留其中的图像部分。我将此变量称为
img
。对图像进行二值化处理并对其进行扩张,然后进行填充变换。我还将删除未连接到主Blob的杂散小的组件。它应该为您提供以下内容:
filled = Binarize@img ~Dilation~ 3 // FillingTransform // DeleteSmallComponents
接下来,找到该blob的质心和等效项Blob的磁盘半径(openCV,MATLAB都有等效的命令可以执行此操作)
{center, radius} = 1 /. ComponentMeasurements[filled, {"Centroid", "EquivalentDiskRadius"}]
就这样!现在绘制原始图像和一个具有上述中心和半径的圆,以查看其适合度:
评论
$ \ begingroup $
很棒的答案!您能扩展一下膨胀和填充转换吗?
$ \ endgroup $
–太空
2012年11月7日,下午3:13
$ \ begingroup $
@Mohammad Dilation是一个基本操作,维基文章很容易解释。填充变换填充“孔”,换言之,填充被较高值的像素包围的像素集。请参阅此处的“更多信息”部分
$ \ endgroup $
–乳香
2012年11月7日,3:20
$ \ begingroup $
抱歉,我打错了。我对膨胀转换有些熟悉,实际上我想知道您是否可以扩展“填充转换”。它正在使用什么规则集?我似乎找不到与之相关的信息。也许它有别的名字了?
$ \ endgroup $
–太空
2012年11月7日,下午3:44
$ \ begingroup $
@yoda,谢谢您的回答,但是如果您阅读了该问题,您会发现我已经尝试了扩张和调整。在我检测到边缘之前产生的图像与您的图像相似。我有些适应,这并不准确。对于您的拟合也是如此,您可以看到拟合圆的顶部太大,大概是因为您考虑了圆上方的顶部的噪点。我也尝试过拟合椭圆(如问题中所述),问题是拟合度不够好。我认为也许更好的方法是使用圆的更好的部分(圆弧)进行拟合。
$ \ endgroup $
– bla
2012年11月7日5:11
$ \ begingroup $
@nate我不明白您所说的“拟合圆的顶部”和“较好圆的部分”是什么意思。您可以使用不同的指标...边界框,长轴长度,短轴长度,距质心的平均距离,距质心的中值距离等。所有这些都取决于您想要的内容。
$ \ endgroup $
–乳香
2012年11月7日下午6:33
评论
霍夫变换寻找一个圆,而不是一个填充的光盘。您首先需要进行边缘检测,以将填充的光盘转换为一个空圆。您圈子的属性是什么?大小恒定吗?他们可以是椭圆吗?点可以不同地分布吗?我试过了(请参见编辑示例),它是否太嘈杂或不够圆?此外,尺寸是恒定的,并且由于相机角度误差而可能具有微小的椭圆度(尽管实际上它是一个完美的圆形窗口)。
如果大小和形状不变,则可以尝试将已填充光盘模板与原始点图像进行互相关
除了我的回答,我认为您可能正在图像处理管道的较晚阶段尝试这样做。您能告诉我们更多有关该问题的信息,并显示一些先前的步骤吗?