我有一张看起来像下面的图像:


我试图找到圆的半径(或直径)。
我尝试使用圆形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