检测噪声图像数据中的圆

信息处理 图像处理 matlab 计算机视觉 检测
2022-01-05 02:19:24

我有一张如下图所示的图片: 在此处输入图像描述

我试图找到圆的半径(或直径)。我尝试过使用圆形霍夫变换(通过 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,行(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);

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

2个回答

这是我的解决方案,它接近@Yoda 的想法,但我改变了一些步骤。

  • 标记所有像素,使其 7x7 邻域中至少有 6 个像素
  • 删除所有斑点,但最大的
  • 填充孔
  • 应用边缘检测
  • 使用霍夫变换查找圆

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

这是相关的Matlab代码。在我的代码中对 circles .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

使用图像处理非常简单。以下是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]}]]