How to fit an ellipse to an image in matlab.

diskimage1.jpgI have a image like this and I want to fit an ellipse around this disk image and get the info about the ellipse like its axis, center point, etc. I am unsure how to use the image proccessing toolbox to draw an ellipse to it and get info about the ellipse.

 Risposta accettata

How about the following?
% Read image
I = imread('diskimage1.jpeg');
% Binarize
Igray = rgb2gray(I);
BW = imbinarize(Igray);
% Extract the maximum area
BW = imclearborder(BW);
BW = bwareafilt(BW,1);
% Calculate centroid, orientation and major/minor axis length of the ellipse
s = regionprops(BW,{'Centroid','Orientation','MajorAxisLength','MinorAxisLength'});
% Calculate the ellipse line
theta = linspace(0,2*pi);
col = (s.MajorAxisLength/2)*cos(theta);
row = (s.MinorAxisLength/2)*sin(theta);
M = makehgtform('translate',[s.Centroid, 0],'zrotate',deg2rad(-1*s.Orientation));
D = M*[col;row;zeros(1,numel(row));ones(1,numel(row))];
% Visualize the result
figure
imshow(Igray)
hold on
plot(D(1,:),D(2,:),'r','LineWidth',2)
untitled.png

11 Commenti

This is amazing! What if the image is poor in quality like the one below. There is still clearly a disk but how would you get rid of all the background stuff around it? disk3.jpg
Thank you Image Analyst-san for introducing many sophisticated algorithms!
These well-designed algorithms must be robust for many images. But, as far as this image, I think small modification for my previous code would be OK.
Please change the first half of my previous code as follows:
% Read image
I = imread('disk3.jpeg');
% Binarize
Igray = rgb2gray(I);
BW = Igray > 10; % <- Changed this line for this new image
% Extract the maximum area
BW = imclearborder(BW);
BW = bwareafilt(BW,1);
BW = imfill(BW,'holes'); % <- Added this line to fill holes
The remaining part is the same as previous one. If you run the code, the result will be like this:
untitled2.png
Thank you so much for your help!
Hi Akira,
Thank you very much for your code, I have found it to be very helpful!
can I ask you a follow up question?
I used your cade to fit an ellipse to my CT scan and I works really well but there is one more thing I'd like to do: find goodness of fit to my image. as you can see in the attached file the bottom of the image doesn't fit so well. what can I do to quantify how well the ellipse fits my image?
thank you very much
You can get the boundary of your binary image with bwboundaries. Then use sqrt() to find the distance of every actual boundary point to the closest fit point. Find the closest one with min. Then take the mean or sum of those closest distances.
boundaries = bwboundaries(mask);
boundaries = boundaries{1}; % Extract from cell
xb = boundaries(:, 2);
yb = boundaries(:, 1);
closestDistances = zeros(1, length(xb));
for k = 1 : length(xb)
% Get distance of each actual boundary point to all points in your ellipse fit vectors.
distances = sqrt((xFit - xb(k)) .^ 2 + (yFit - yb(k)) .^ 2); % A vector of distances
closestDistances(k) = min(distances); % A single distance.
end
closenessOfFitMetric = mean(closestDistances)
Hello Mr. @Akira Agata,
I looked into your code and would like to use it for my analysis of the area of certain objects in pictures - quite similar to Hardit Singh's case.
I have trouble understanding your code to its full core so I'd like to ask you wether your code takes into cosideration wether the ellipse is tilted or not? With my knowledge it would mean that if the ellipse is tilted by an angle φ, the points to use as Major- and MinorAxisLength are also tilted by φ.
If you'd like I asked this question about your code here, maybe it could help you understand my question a bit more: https://de.mathworks.com/matlabcentral/answers/1662750-getting-area-of-tilted-ellipse-with-regionprops?s_tid=prof_contriblnk, 08.03.2022, 3:16 pm.
Thank you for your time.
You can get the angle of the tile in degrees by calling regionprops.
props = regionprops(BW, 'Orientation', 'MajorAxisLength', 'MinorAxisLength');
allAngles = [props.Orientation]
Of course the axis lengths do NOT depend on the angle. They are what they are, regardless of angle.
Hi, I'm trying to use your method to solve my own ellipse fitting problem, i have detected the edge of my shape in the image included and want to fit an ellipse to this to generate a function that i can use to perform the diff() function and get the tangent of the ellipse at the bottoms of the edge detected in the image.
I am having some trouble improving the fit of the ellipse here, this is my best attempt so far, any advice would be greatly appreciated:
@Connor that is not a blob. Well it is but it's a very snake-like, line-like blob. So the fit is accurate. But I suspect what you want is to fit the (x,y) coordinates of the blob to an ellipse. So you need to get x and y from the binary image like this:
[y, x] = find(binaryImage);
Thanks!

Accedi per commentare.

Più risposte (2)

Matt J
Matt J il 10 Nov 2023
Modificato: Matt J il 10 Nov 2023
You can use ellipticalFit from this FEX download
processImage('Connors_image.png')
ans =
ellipticalFit with properties: center: [196.4747 218.0069] a: 130.0274 b: 119.1008 angle: 3.0398
processImage('Hardits_image.png')
ans =
ellipticalFit with properties: center: [171.3735 173.6428] a: 112.7502 b: 104.1636 angle: 47.0771
function e=processImage(filename)
I = imread(filename);
% Binarize
I = bwareafilt(imclearborder(imbinarize(rgb2gray(I))),1);
b = bwboundaries(I);
e=ellipticalFit(flipud(b{1}'));
imshow(I,[]); hold on
showfit(e,'LineWidth',1,'Color','r','LineStyle','--'); hold off
end

Prodotti

Release

R2016b

Community Treasure Hunt

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

Start Hunting!

Translated by