Fitting ellipse from a set of point

Hello everyone,

I’m trying to fit an ellipse from a set of point like MATLAB do. I’m working with images of contact between en indentor and a transparent polymer.
Do someone know if there’s a macro who can do that like the run circle function of ImageJ.
The fit ellipse function DOESN’T DO what I need. I want to fit from point not from closed selection.
Here’s a image.

The points would be the inner line around the brightest region.

1 Like

Hi @Lionel_Limol,

it may sound a bit crazy, but: Could you imagine to draw a polygon along your points and filling the area with white while filling the area around it with black? You would then have a binary image, where you could apply the fit ellipse thingy…

Cheers,
Robert

Thanks Robert,
That’s a good idea to get some info at first sight like the area but I’m working with a lot of images so I made a tool image to treat 10 images stacks. I’m still approximate those area with circle :/. Hope that someone release a fit ellipse function as It exists in MATLAB ( https://fr.mathworks.com/matlabcentral/fileexchange/3215-fit-ellipse?requestedDomain=www.mathworks.com k

Welcome to the forum, @Lionel_Limol!

You could compute the convex hull of the points, and then fit the ellipse using the Fit Ellipse command, maybe?

Cool, I didn’t think of that… I’ll try it.
The right hand part is a circle while the left hand is an ellipse. Actually I fit the two part separatly and combine the two area selection with “AND”.
I’ve found this http://imagej.1557.x6.nabble.com/Ellipse-Fitting-td3689852.html on the forum but didn’t understand how to use it…

2 Likes

Ah, cool. That code is now part of BoneJ, a great project by @mdoube and @rimadoma. You can download it from the BoneJ web site.

There is no user-facing menu item for this class, which is used internally. There is a public method which can be called by other code, if you would like to write a script to do that.

1 Like

Hello,
In the othe forum, you wrote that you implement the “direct” fit; you mean the fit by Fitzgibbon-Pilu-Fisher ?
For th Taubin fit, you had some problems , right ?
I’m new in this ImageJ stuff but I’ll try to understand how to use the “public method by calling her with a script”.
Thanks a lot 4 your help.

Specifically, the code in question is:

I quickly tried the following Groovy script (after adding BoneJ_.jar to my Fiji installation):

import org.doube.geometry.FitEllipse

double[][] points = [[0,1],[1,0],[0,-1]]
parameters = FitEllipse.direct(points)

println(parameters)

which returned the following parameters for the resulting ellipse:

[-0.7559289460184545, 0.0, -0.37796447300922736, 0.3779644730092272, 0.0, 0.37796447300922736]

Hope that helps in getting you started.

2 Likes

Yes.

Yes, specifically that the particular form of eigendecomposition, eig(a,b), required by the Taubin fit was (is?) not available in the linear algebra library BoneJ uses (JAMA).

Please note that BoneJ’s ellipse-fitting code is a straight Java port from Nikolai Chernov’s MATLAB code, and I’ve applied little to no critical analysis or reworking to it.

2 Likes

Hello everybody,

Thanks to you and to Jerome Mutterer I succeed in using the public method (Jerome Mutterer give me the code):

  1. I save this javascript ( with the name “EllipseFit.js”) in the macro directory:
// javascript
importClass(Packages.org.doube.geometry.FitEllipse);
imp = IJ.getImage();
roi = imp.getRoi();
p = roi.getPolygon();
points = [[],[]];
for (i=0; i<p.npoints; i++) {  x = p.xpoints[i]; y = p.ypoints[i]; points[i] = [x,y];}
//@mdoube put a fonction to calculate the geometric parameters from the algebraic one
//so I apply varTo Dimensions to FitEllipse which contains the algebraic parameters
ellipse = FitEllipse.varToDimensions(FitEllipse.direct (points));
res  = '';for(i in ellipse) res+=ellipse[i]+";";
Prefs.set("ellipse.params",res);
// fin du javascript.

2.I run this macro code after doing a multi selection point on my image :

runMacro("EllipseFit.js");   
params = call('ij.Prefs.get','ellipse.params','n/a');
geometric = split (params,';');
x0=geometric[0];y0=geometric[1];
a=geometric[2];b=geometric[3];
phi=geometric[4];

//I finally get the point of the ellipse:
drawEllipse(x0,y0,a,b, phi);

I found an old post where Arttu Miettinen said that the dggev.f subroutine used in LAPACK could do that. Is that true ?

Cheers,
Lionel

Here are the images of the fit (in the draw Ellipse I make points only from PI/2 to 3*PI/2 which corresponds to the left part of my images):

I fit an ellipse from the left side of the vertical line, the right part is a perfect circle:

Taking some points:

After the macro runs:

Sometimes my Ellipse is rotate from the original points, I don’t know why yet, but going to figure it out :
I had more or less the same multipoint selection and the result:

Cheers,
Lionel

2 Likes

Maybe - you’re welcome to investigate, improve the code, and make pull requests at Github. I had a look at it long ago, and gave up once I had the direct fit working.

1 Like

Looks like the major and minor semiaxes are swapped - I wonder under what conditions that happens.

1 Like

Hello,

I found out why this happen : my angle was in degree in the draw function while my output angle from the fit was in radian.
Now It’s working fine as a charm…
Regarding the LAPACK subroutine, I’ll investigate and let you know if I find out something…

Cheers,
Lionel

2 Likes


Is this what you wanted? The reds are the fitted contour ellipses, the green is user-defined threshold isocurve, the white is user-defined ROI rectangle. It is processed by imagin.py (https://github.com/ASukhanov/Imagin).

FitEllipse was removed from BoneJ2 because no other code called it. Not sure if it was ever upstreamed:

The code still exists in BoneJ1 (no longer recommended due to installation difficulties), and on GitHub and could easily be reincarnated.