在嘈杂的图像数据中检测圆


17

我有一张看起来像下面的图像: 在此处输入图片说明

我试图找到圆的半径(或直径)。我尝试使用圆形Hough变换(通过matlab imfindcircles(bw,[rmin rmax],'ObjectPolarity','bright')),并拟合到圆形或椭圆形(自制函数,对于噪声较小的数据效果很好,请参见下文)。

我还尝试了一些图像处理以获得更清晰的圆圈,例如,请参见下文:

se = strel('disk', 2);
bw = imdilate(bw, se);
bw = bwareaopen(bw,100000); 
bw =  edge(bw); 

在此处输入图片说明

但是,当我将处理后的图像馈给这两种技术(霍夫和圆\椭圆拟合)时,它们都无法以体面的方式检测到圆。

这是我写的寻圈器的代码片段(matlab)[row 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);

替代方法将不胜感激...


霍夫变换寻找一个圆,而不是一个填充的光盘。您首先需要进行边缘检测,以将填充的光盘转换为一个空圆。您圈子的属性是什么?大小恒定吗?他们可以是椭圆吗?点可以不同地分布吗?
endlith 2012年

我试过了(请参见编辑后的示例),它是否太嘈杂或不够循环?此外,尺寸是恒定的,由于相机角度误差,它可能具有微小的椭圆度(尽管实际上它是一个完美的圆形窗口)。
bla 2012年

如果大小和形状恒定,则可以尝试将填充的圆盘模板与原始点图像进行互相关处理
endolith 2012年

除了我的回答,我认为您可能正在图像处理管道的较晚阶段尝试这样做。您能否告诉我们更多有关该问题的信息,并说明一些先前的步骤?
Andrey Rubshtein 2012年

Answers:


13

这是我的解决方案,它与@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

1
霍夫变换在这里进行了什么操作,以使其求解并找到蓝色圆圈?是否在图像的不同位置投影了许多不同半径的圆,并找到最合适的圆?
Spacey 2012年

@Mohammad,这是通常的圆形探测器。它使用合并和投票。
Andrey Rubshtein 2012年

您也可以在此答案的第一步之后使用快速径向对称变换(FRST)。
Geniedesalpages 2014年

10

使用图像处理非常简单。以下是Mathematica中概念的证明。您必须将其转换为MATLAB。

  • 首先,修剪轴并仅保留其中的图像部分。我称这个变量img
  • 对图像进行二值化处理并进行扩张,然后进行填充变换。我还将删除未连接到主Blob的杂散小的组件。它应该给您类似以下内容:

    filled = Binarize@img ~Dilation~ 3 // FillingTransform // DeleteSmallComponents
    

  • 接下来,找到该Blob的质心和该Blob的等效磁盘半径(openCV,MATLAB都有等效的命令来执行此操作)

    {center, radius} = 1 /. ComponentMeasurements[filled, {"Centroid", "EquivalentDiskRadius"}]
    
  • 而已!现在绘制原始图像和一个具有上述中心和半径的圆,以查看其适合度:

    Show[img, Graphics[{Red, Circle[center, radius]}]]
    


很棒的答案!您能否扩展和填充变换?
Spacey 2012年

@Mohammad 扩张是一个基本的操作,并将由维基文章很容易解释。填充变换填充“孔”,换言之,填充被较高值的像素包围的像素集。请参阅此处
Lorem Ipsum 2012年

抱歉,我打错了。我对膨胀转换有些熟悉,实际上我想知道您是否可以扩展“填充转换”。它正在使用什么规则集?我似乎找不到与之相关的信息。也许它有别的名字了?
Spacey 2012年

@yoda,谢谢您的回答,但是,如果您阅读了该问题,您会发现我已经尝试了扩张和调整。在我检测到边缘之前产生的图像与您的图像相似。我有些适应,这不准确。对于您的拟合也是如此,您可以看到拟合圆的顶部太大,大概是因为您考虑了圆上方的顶部的噪点。我也尝试过拟合椭圆(如问题中所述),问题是拟合度不够好。我认为也许更好的方法是使用圆的更好的部分(圆弧)进行拟合。
bla 2012年

@nate我不明白您所说的“拟合圆的顶部”和“较好圆的部分”是什么意思。您可以使用不同的度量标准...边界框,长轴长度,短轴长度,距质心的平均距离,距质心的中值距离等。所有这些都取决于您想要的内容。
Lorem Ipsum 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.