Fill the circular paths in image [closed]

ⅰ亾dé卋堺 提交于 2019-12-13 10:27:33

问题


I have many images consisting of circles(varying from 1 to 4) in each image. I am trying to get a clear circle images by filling the missed pixels along the circle path.

I have tried Hough-transform, but its parameters are image specific: for each image I have to change the parameters. With this problem I am unable keep them in a single for loop.

Please provide some method to do it. Thanks


回答1:


imfindcircles Does not work
The most "natural" way to approach this problem is to use Matlab's imfindcircles. However, that function assume the circles in the image are "full", yet in your examples you only have the (incomplete) boundaries of the circles, thus imfindcircles cannot be directly applied to your data.

Alternative Approach
You can use ransac to fit circles to your data. Fit one circle at a time to as many points as you can, terminate when there are too few points left that fit no circle at all.

To use RanSac you basically need to implement two methods:

  1. Model fitting method, fitFcn, Given a small sample of your points - fit a circle to them.

  2. Distance to model method, distFcn, Given a circle ("model") find the distance of each point to that circle.

Once you have these two methods, RanSac operates roughly like:
- randomly sample very few points
- use fitFcn to fit a circle to these sampled points
- use distFcn to compute the distance of all points to estimated circle
- if enough points are close to the circle, accept this circle and remove all point that "belongs" to that circle
- terminate if no circle was found or not enough "unexplained" points

This can be easily implemented in Matlab.

First consider fitFcn: we need a function that compute (cx, cy, r) - the three parameters of a 2D circle (center and radii). Given a point (x, y) it fits a circle iff

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

We can write this equation as a linear relation between known points (x, y) and unknown circle (cx, cy, r) in the following manner

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

Using a least squares estimation (in a similar manner as in this answer), we can recover the circle parameters given enough points (at least 3) on the circle

This is how the code actually looks like

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)

Now that we can fit a circle to points, we need to compute the distance using distFcn that is quite simple

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));

Putting it all together with matlab's 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{:});

And the output of this function on your data is (using viscircles to plot the circles):



来源:https://stackoverflow.com/questions/56846801/fill-the-circular-paths-in-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!