【问题标题】:Fill the circular paths in image [closed]填充图像中的圆形路径[关闭]
【发布时间】:2019-11-12 18:24:53
【问题描述】:

我在每张图片中有很多由圆圈组成的图片(从 1 到 4 不等)。我试图通过沿圆形路径填充丢失的像素来获得清晰的圆形图像。

我尝试过霍夫变换,但它的参数是特定于图像的:对于每个图像,我都必须更改参数。有了这个问题,我无法将它们放在一个 for 循环中。

请提供一些方法来做到这一点。谢谢

【问题讨论】:

    标签: python-3.x matlab image-processing image-segmentation edge-detection


    【解决方案1】:

    imfindcircles 不起作用
    解决这个问题最“自然”的方法是使用 Matlab 的imfindcircles。但是,该函数假定图像中的圆圈是“完整的”,但在您的示例中,您只有圆圈的(不完整)边界,因此 imfindcircles 不能直接应用于您的数据。

    替代方法
    您可以使用ransac 将圆圈与您的数据相匹配。一次将一个圆拟合到尽可能多的点,当剩下的点太少根本不适合任何圆时终止。

    要使用RanSac,你基本上需要实现两个方法:

    1. 模型拟合方法fitFcn,给定一个小样本点 - 为它们拟合一个圆。

    2. 到模型的距离方法distFcn,给定一个圆(“模型”),找出每个点到那个圆的距离。

    一旦有了这两种方法,RanSac 的操作大致如下:
    - 随机抽样很少的点
    - 使用fitFcn 将圆拟合到这些采样点
    - 使用distFcn 计算所有点到估计圆的距离
    - 如果有足够多的点靠近圆,则接受该圆并删除所有“属于”该圆的点
    - 如果没有找到圆圈或没有足够的“无法解释”的点,则终止

    这在 Matlab 中很容易实现。

    首先考虑fitFcn:我们需要一个计算(cxcyr)的函数——二维圆的三个参数(中心和半径)。给定一个点 (x, y) 它适合一个圆当且仅当

    (x - cx)^2 + (y - cy)^2 = r^2
    

    我们可以将这个方程写成已知点(xy)和未知圆(cxcyr)之间的线性关系,如下所示

    [-2*x, -2*y, 1] [ cx ; 
                      cy ;                 = [-x^2-y^2]
                      cx^2 + cy^2 - r^2 ]
    

    使用最小二乘估计(以与this answer 类似的方式),我们可以在给定圆上足够多的点(至少 3 个)的情况下恢复圆参数

    这就是代码的实际样子

    function crc = fit_circle(xy)  % xy is n-by-2 matrix of point coordinates
    % fit in least squares sens
    x = xy(:, 1);
    y = xy(:, 2);
    X = [-2*x, -2*y, ones(size(x))]; 
    Y = -x.^2 - y.^2;
    crc = (X\Y).';  % least squares solution
    r2 = -crc(3) +crc(1).^2 + crc(2).^2; 
    if r2 <= 0
        crc(3) = 0;
    else    
        crc(3) = sqrt(r2);
    end
    % output crc is a 3 vector (cx, cy, r)
    

    现在我们可以用圆拟合点,我们需要使用 distFcn 计算距离,这很简单

    function dst = distFcn(crc, xy)
    % how good a fit circle for points
    x = xy(:, 1) - crc(1);
    y = xy(:, 2) - crc(2);
    dst = abs(sqrt(x.^2 + y.^2) - crc(3));
    

    把它和matlab的ransac放在一起:

    function circles = find_circles(bw)
    % parameters
    sample_size = 4;
    max_distance = 10;
    min_num_points_in_circle = 50;
    
    [y, x] = find(bw > max(bw(:))/2);  % all edges in the image
    
    circles = {};
    counter = 0;
    while numel(x) > 10 * sample_size && counter < 10
        try
            [circle, inlierIdx] = ransac([x, y], @fit_circle, @distFcn, ...
                sample_size, max_distance);
        catch
            break
        end
        % refit using only inliers
        circle = fit_circle([x(inlierIdx) y(inlierIdx)]);
        dst = distFcn(circle, [x y]);
        founfit = dst < max_distance;
        if sum(founfit) > min_num_points_in_circle
            % this model fits enough points
            circles{end+1} = circle;
            x(founfit) = [];
            y(founfit) = [];
        else
            counter = counter + 1;
        end    
    end
    circles = vertcat(circles{:});
    

    此函数对您的数据的输出是(使用viscircles 绘制圆圈):

    【讨论】:

      猜你喜欢
      • 2019-07-06
      • 2019-11-06
      • 2012-05-13
      • 2015-04-24
      • 1970-01-01
      • 2014-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多