Separate two overlapping circles in the image with MATLAB

How to separate two connected circles in the image below using MATLAB? I tried to use imerode , but it does not give good results. Erosion does not work, because for erosion sufficient to separate the circles, the lines disappear or become distorted. In other initial images, the circle and line overlap, so the isolation of overlapping objects also does not work.

The image shows the objects indicated by bwboundaries , each object is painted in its own color. As you can see, the two light blue circles are combined, and I want to separate them by creating two separate circles. Thanks

+5
source share
3 answers

I would recommend you use Circular Hough Transform through imfindcircles . However, you need version 8 of the Image Processing Toolbox, which has been available from R2012a onwards. If you do not have this, then, unfortunately, this will not work: (... but let go with the assumption that you have it. However, if you use something older than R2012a, Dev-iL in his / her the comment above is related to some MATLAB File Exchange code on the implementation of this, most likely, was created before the Circular Hough Transform was available: http://www.mathworks.com/matlabcentral/fileexchange/9168-detect-circles-with- various-radii-in-grayscale-image-via-hough-transform /


This is a special case of the Hough Transform transform, in which you try to find circles in your image, not lines. The beauty is that you can find circles even if the circle is partially completed or overlaps.

I will take the image you specified above and do some post processing on it. I am going to convert the image to a binary file and remove the border that is white and contains the title. I am also going to fill in any holes that will cause all objects to be filled with solid white. After I take this step, there is some residual quantization noise, so I'm going to a small hole with a 3 x 3 square element. After that, I’m going to close the shapes with a 3 x 3 square element, because I see that spaces are noticeable in the shapes. Therefore:

Therefore, direct reading in your image from the place where you placed it:

 im = imread('http://s29.postimg.org/spkab8oef/image.jpg'); %// Read in the image im_gray = im2double(rgb2gray(im)); %// Convert to grayscale, then [0,1] out = imclearborder(im_gray > 0.6); %// Threshold using 0.6, then clear the border out = imfill(out, 'holes'); %// Fill in the holes out = imopen(out, strel('square', 3)); out = imclose(out, strel('square', 3)); 

This is the image I get:

enter image description here

Now apply the circular transform. The general syntax for this is:

 [centres, radii, metric] = imfindcircles(img, [start_radius, end_radius]); 

img will be the binary image that contains your shapes, start_radius and end_radius will be the smallest and largest radius of the circles you want to find. The Circular Hough Transform transformation is performed in such a way that it finds any circles that are in this range (in pixels). Outputs:

  • centres : which returns the position (x,y) centers of each detected circle.
  • radii : radius of each circle
  • metric : A measure of the purity of a circle. Higher values ​​mean that the shape is more likely for the circle and vice versa.

I was looking for circles with a radius of 30 to 60 pixels. Therefore:

 [centres, radii, metric] = imfindcircles(out, [30, 60]); 

Then we can demonstrate the detected circles as well as the radii with a combination of plot and viscircles . Therefore:

 imshow(out); hold on; plot(centres(:,1), centres(:,2), 'r*'); %// Plot centres viscircles(centres, radii, 'EdgeColor', 'b'); %// Plot circles - Make edge blue 

Here is the result:

enter image description here

As you can see, even with overlapping circles to the top, the Circular Hough Transform was able to detect two different circles in this shape.


Edit - November 16, 2014

You want the objects to be split before you make bwboundaries . This is a little hard to do. The only way to see that you are doing this is to not use bwboundaries at all and do it yourself. I assume that you will want to analyze the properties of each figure yourself, so I suggest you iterate through each circle, and then place each circle in a new empty image, make a regionprops call on this form, and then add it to a separate array. You can also track all circles with a separate array that adds circles one at a time to this array.

Once you are done with all the circles, you will have an array of structures containing all the measured properties for all the measured circles that you found. You should use an array that contains only the circles on top, and then use them and remove from the original image to get only the rows. Then you call another regionprops on this image to get row information and add this to your final structural array.

Here is the first part of the procedure described above:

 num_circles = numel(radii); %// Get number of circles struct_reg = []; %// Save the shape analysis per circle / line here %// For creating our circle in the temporary image [X,Y] = meshgrid(1:size(out,2), 1:size(out,1)); %// Storing all of our circles in this image circles_img = false(size(out)); for idx = 1 : num_circles %// For each circle we have... %// Place our circle inside a temporary image r = radii(idx); cx = centres(idx,1); cy = centres(idx,2); tmp = (X - cx).^2 + (Y - cy).^2 <= r^2; % // Save in master circle image circles_img(tmp) = true; %// Do regionprops on this image and save struct_reg = [struct_reg; regionprops(tmp)]; end 

The above code may be a little hard to learn, but slowly skip it. First I will find out how many circles we have, which just looks at how many radii we found. I save a separate array called struct_reg , which will add regionprops struct for each circle and row that we have in our image. I use meshgrid to determine the coordinates (x,y) with respect to the image containing our shapes so that I can draw one circle on an empty image in each iteration. To do this, you just need to find the Euclidean distance relative to the center of each circle and set the pixels to true only if this location has a distance less than r . After completing this operation, you will create only one circle and filter out all of them. Then you would use regionprops in that circle, adding it to our circles_img array that would only contain circles, and then continue with the rest of the circles.

At this moment, we will keep all our circles. Here is what circles_img looks circles_img :

enter image description here

You will notice that the drawn circles are clean, but the actual circles in the original image are a bit jagged. If we try to remove circles with this clean image, you will get some residual pixels along the border, and you cannot completely remove the circles themselves. To illustrate what I mean, this is what your image looks like if I try to delete circles using circles_img myself:

enter image description here

... not good, right?

If you want to completely remove the circles, perform a morphological reconstruction through imreconstruct , where you can use this image as a seed image and indicate the original image we are working on. Morphological reconstruction work is essentially a flood. You specify the seed pixels and the image you want to work on, and the imreconstruct task is from these seeds, the fill is filled with white until we reach the boundaries of the objects in which the seed pixels lived. Therefore:

 out_circles = imreconstruct(circles_img, out); 

Therefore, we get this for our final reconstructed circles image:

enter image description here

Excellent! Now use this and remove the circles from the original image. After that, run regionprops again on this destination image and add struct_reg to your variable. Obviously, keep a copy of the original image before doing this:

 out_copy = out; out_copy(out_circles) = false; struct_reg = [struct_reg; regionprops(out_copy)]; 

Just for the sake of argument, here is what the image with deleting circles looks like:

enter image description here

Now we have analyzed all our forms. Keep in mind that I made a complete call to regionprops because I don’t know exactly what you want in my analysis ... so I just decided to give you everything.


Hope this helps!

+4
source

erosion is the way to go. You should probably use a larger structuring element.

-1
source

What about

1 erode

2 detection of your objects

3 expands each object for itself using the same structuring element

-1
source

Source: https://habr.com/ru/post/1206794/


All Articles