Detect concentric empty rough circles

Hello,

I want to be able to detect and draw a square around some circles. These circles are taken with a camera so depending of the angle of view and the distance, the radius vary and they can be deformed.Here are two examples: First example and Second example.

The last thing I have tried is using the CircularHough_Grd function from Tao Peng but it finds circles that are tangent of the sought circles: Result with CircularHough_Grd. And I am not sure how resistant this function is to deformation.

Any suggestion would be welcome as I am running a bit out of ideas at the moment.

Cheers.

2 commentaires

Image Analyst
Image Analyst le 23 Jan 2014
Can you attach them here using the image icon? My company policy has banned dropbox.
Carine
Carine le 23 Jan 2014
Modifié(e) : Carine le 23 Jan 2014

Above there is one and here is the second one

Connectez-vous pour commenter.

 Réponse acceptée

Image Analyst
Image Analyst le 23 Jan 2014

0 votes

10 commentaires

Carine
Carine le 23 Jan 2014
I have tried it with the first image and it did work but I am afraid for less round image (as in the second example) it does not work. Moreover, I would like to find a way not to have to define so precisely the radius as it can vary a lot in my examples.
Image Analyst
Image Analyst le 23 Jan 2014
Modifié(e) : Image Analyst le 24 Jan 2014
Very easy. Basically 3 steps: threshold, regionprops, and filter to retain circular blobs. If you need a full demo, let me know. (Only doing it because it's really trivial and quick to do and it's just reapplication of boilerplate code).
Image Analyst
Image Analyst le 24 Jan 2014
Modifié(e) : Image Analyst le 24 Jan 2014
Alright, I'll do it. See attached code (below, in blue text) to produce the image below.
It also gives you the diameter, centroid, area, and perimeter.
Image Analyst
Image Analyst le 26 Jan 2014
Carine: Are you still alive? What did you think about the application I spent time writing for you? Do you like it? Does it do the job? Will we become rich and famous because of this?
Carine
Carine le 28 Jan 2014
Sorry, I have just seen your answer now. I thought I would be advised when receiving a new one but not. So thank you very much. I am going to start to study it right now and let you know when I have something new. The only problem I can foresee is I need to detect both circles (inner and outer ones). I have tried Tao Peng's code for that but it seems to have a bug.
I wish we would become rich and famous but I have something even better: satisfied to have made some advance in science :-)
Carine: You can get the coordinates of both sides of the ring by inverting the binary image and calling bwboundaries:
boundaries = bwboundaries(~binaryImage);
If that's the final things, then can you mark the Answer as "Accepted".
If you aren't getting notices of updates to your post, send an email to files@mathworks.com and let them know you think there's a bug in the Answers forum.
Hey Image Analyst, That is almost perfect except that when I try to compute the boundaries with:
[B,L,N,A] = bwboundaries(~binaryImage);
and I plot it on top of the original image with
for k=1:length(B),
if(~sum(A(k,:)))
boundary = B{k};
plot(boundary(:,2),...
boundary(:,1),'r','LineWidth',2);
for l=find(A(:,k))'
boundary = B{l};
plot(boundary(:,2),...
boundary(:,1),'g','LineWidth',2);
end
end
end
Then it turns out that it does not find the right boundaries. See this plot
I am thinking of alternative but I don't have the idea yet.
Thank you for your help!
Image Analyst
Image Analyst le 28 Jan 2014
The problem with this particular image is that the black ring is touching the edge of the image. So you're going to have to think up a way to get a "C" shape (a partial ring) as well as a ring. It would take some thought. Otherwise, just expand the one ring you do find. Of course there is the problem that even the central disk could be cropped, so it looks like a "D". All of these pathological cases make the algorithm a lot more complicated. It would help if you could define the parameters of your experiment, like make sure the black ring never touches the edge of the image. Otherwise, let me review your algorithm to get "C" shapes. I probably won't have time to develop an algorithm for you today, but since it's your project you can probably spend all day on it.
Carine
Carine le 28 Jan 2014
Hi again, I am of course spending the day on it... But the day is ending her in Europe. I have tried the another example but the result is rather worse. Your code give this plot:
More tomorrow.
I really appreciate your help! Cheers-
Hello, I have finally something quite satisfying (history will see if fame is approaching dear Image Analyst ;-)):
nomFile = 'Piscine80b.JPG';
rgbImage = imread(nomFile);
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows, columns, numberOfColorBands] = size(rgbImage);
redChannel = rgbImage(:, :, 1);
level = graythresh(rgbImage);
binaryImage = im2bw(redChannel,level);
binaryImage = bwareaopen(binaryImage, 20000);
binaryImage = ~bwareaopen(~binaryImage, 20000);
[labeledImage, numberOfBlobs] = bwlabel(binaryImage, 8);
% Label each blob so we can make measurements of it
fprintf('Found %d blobs.\n', numberOfBlobs);
coloredLabels = label2rgb (labeledImage, 'hsv', 'k', 'shuffle');
% pseudo random color labels
% Measure the regions
measurements = regionprops(labeledImage, 'Perimeter', 'Area');
% Select certain blobs based using the ismember function.
% Let's say that we wanted to find only those blobs
% with a circularity more than 5 or so.
allBlobPerimeters = [measurements.Perimeter];
allBlobAreas = [measurements.Area];
allCircularities = allBlobPerimeters .^ 2 ./ (4*pi*allBlobAreas)
% Get a list of the blobs that meet our criteria and we need to keep.
% keeperIndexes = find(allCircularities < 1.5)
[~,keeperIndexes] = min(allCircularities)
% Extract only those blobs that meet our criteria, and
% eliminate those blobs that don't meet our criteria.
% Note how we use ismember() to do this.
keeperBlobsImage = ismember(labeledImage, keeperIndexes);
% Measure the regions, this time getting equivalent circular diameter and centroid.
measurements = regionprops(logical(keeperBlobsImage), ...
'Perimeter', 'Area', 'EquivDiameter', 'Centroid','BoundingBox');
ecd = measurements.EquivDiameter
equivDiameter(k,lettre) = ecd;
c = measurements.Centroid;
centroid(k,lettre,:) = c;
BoundingBox = [measurements.BoundingBox]
% Create a square mask including the circle
x0 = BoundingBox(1); y0 = BoundingBox(2); % Upper left corner
w = BoundingBox(3); h = BoundingBox(4); % Width and heigth
dw = 0.1*w; dh = 0.1*h; % To let some margin
mask = zeros(rows,columns);
mask(max(1,ceil(y0-dh)):min(rows,ceil(y0+h+dh)), ...
max(1,ceil(x0-dw)):min(columns,ceil(x0+w+dw))) = 1;
mask = logical(mask);
Imask = rgbImage;
Imask(~mask) = 255;
IbinMask = ~(~binaryImage.*mask);
close
togglefig(nomFile)
imshow(rgbImage)
pause
imshow(IbinMask)
hold on
plot(c(1), c(2), 'r+', 'MarkerSize', 20, 'LineWidth', 3);
plot(c(1)-ceil(ecd/2):c(1)+ceil(ecd/2),c(2),'r','LineWidth', 3);
hold off
pause
end
end
Using that, I can define the box around my "nearly circle" and select it, draw the equivalent diameter and the centre. Thank you again for you help!

Connectez-vous pour commenter.

Plus de réponses (7)

Carine
Carine le 24 Mar 2014
Hello,
I would like to reopen this question as, dealing with a noiser picture, it does not work anymore. For example, if I take a picture which I process and transform to black and white. I get this one:
Now, when I try to find regions with regionprops, it just finds one in red. Whereas I need the system to dectect my black circle.
</matlabcentral/answers/uploaded_files/10333/region.jpg> To get it, following the previous idea of this thread I do:
[labeledImage, numberOfBlobs] = bwlabel(binaryImage, 8);
coloredLabels = label2rgb (labeledImage, 'hsv', 'k', 'shuffle');
imshow(coloredLabels)
Any idea on how I could detect the circle?
Cheers.
Carine
Carine le 26 Mar 2014
Modifié(e) : Carine le 26 Mar 2014
OK, here is a full example: I have this picture:
</matlabcentral/answers/uploaded_files/10400/Turbio10b.JPG> or link here. I process it using adapthisteq with Rayleigh distribution and clip of 1 and get:
Now I transform it to black and white and use bwareaopen to clean the image a bit:
Then if I try to find the blobs with
[labeledImage, numberOfBlobs] = bwlabel(binaryImage, 8);
I get this, link here or in fig . I find it very surprising as in very similar example, it works and detect both circles.
Cheers,
Carine.
P.S. I put hyperlink as it seems the direct links to the images don't work. I don't know why as when I download them, I am able visualize them but then it stop working.

3 commentaires

Image Analyst
Image Analyst le 26 Mar 2014
So you got it working?
And to insert images, did you use the image icon? Did you pick an image on the web or one from your hard drive?
Carine
Carine le 27 Mar 2014
No, if you can see my images, you will see that one of the circles is not detected. Yes I did use the image icon, choosing an image from my hard drive.
Image Analyst
Image Analyst le 27 Mar 2014
Modifié(e) : Image Analyst le 27 Mar 2014

Your links are broken. Let me see if I can upload one from my hard drive from the image icon and see if the link it inserts is broken.

It seems I can insert one. Please try again.

Connectez-vous pour commenter.

Carine
Carine le 27 Mar 2014

0 votes

Using adapthisteq with Rayleigh distribution
on red channel
Carine
Carine le 27 Mar 2014

0 votes

Now I transform it to black and white and use bwareaopen to clean the image a bit:
Carine
Carine le 27 Mar 2014
Then if I try to find the blobs with
[labeledImage, numberOfBlobs] = bwlabel(binaryImage, 8);
I get this
Carine
Carine le 27 Mar 2014
Modifié(e) : Carine le 27 Mar 2014

0 votes

I find it very surprising as in very similar example, it works and detect both circles.
I have split the text to have only one figure in each answer and see if it works better.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by