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

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.