Maximum Feret diameter of irregular 3D shape

Does anyone knows a nice plugin to analyze 3D particle (binary stack) with iregular shape and have the major feret diamater (sometimes called caliper diamater too) and its orientation as output?

I checked BoneJ’s particle analyzer, but this does not give the results I look for, see test macro below.
Also the axis in the result are slightly tilted.

// lets assume a prism of 10 x 20 x 30 pixel
w = 10; h = 20; l = 30;
newImage("Test", "8-bit black",40, 40, 40);
makeRectangle(10, 10, w, h);
setColor("white");
for (i = 6; i < 6+l; i++) {
    setSlice(i);
    run("Fill", "slice");
};

// Lets get the output from the boneJ particle analyser
run("Particle Analyser", "feret min=0.000 max=Infinity"+
	" surface_resampling=2 show_centroids show_axes show_ellipsoids"+
	" show_stack draw_ellipsoids split=0.000"+
	" volume_resampling=2");

// what I expect is the diagonal of the prism
maxfer = sqrt( w*w + h*h + l*l);
print("max. feret = "+maxfer);

So, any idea how I can get the max. length of a 3D particle and its orientation?

Cheers,
Jürgen

1 Like

Hi @Jurgen_Gluch,

interesting question! I just tried the 3D Manager. It doesn’t have a max-Feret but it fits an ellipse and I could imagine that you can derive the elongation in voxels from its measurements:

I also tried MorphoLibJ, which has a dedicated Plugins > MorpolibJ > Analyse > Max Feret menu
image
I’m just confused by the result. Maybe @dlegland can help us here? We’re expecting for a value around 35, not 22, right :wink:

Alternatively, if the objects are not too large(precisely: Less than about 3000 edge voxels) , I can offer you a brute-force option using a graphics card and CLIJ2 #clij :

Starting from your binary image (I had to adapt the code a bit, because it wasn’t setting voxels to any value on my machine) we get all edge voxels. Afterwards, we determine the distance between all edge voxels (to each other) and take the maximum from these values:

w = 10; h = 20; l = 30;
newImage("Test", "8-bit black",40, 40, 40);
makeRectangle(10, 10, w, h);
setColor("white");
for (i = 6; i < 6+l; i++) {
    setSlice(i);
	run("Add...", "value=1");
};


// init GPU
run("CLIJ2 Macro Extensions", "cl_device=");
Ext.CLIJ2_clear();

// push data to GPU memory
input = getTitle();
Ext.CLIJ_push(input);

// detect edges
edges = "edges";
Ext.CLIJ2_binaryEdgeDetection(input, edges);

// label all white voxels with individual numbers
Ext.CLIJ2_labelSpots(edges, labelled);

// get the coordinates of all edge voxels
Ext.CLIJ2_labelledSpotsToPointList(labelled, pointlist);

// generate a distance matrix from all voxels to all voxels
Ext.CLIJ2_generateDistanceMatrix(pointlist, pointlist, distance_matrix);

// determine maximum
Ext.CLIJ2_getMaximumOfAllPixels(distance_matrix, max_distance);

print("Maximum distance: " + max_distance);

Resulting in:
image

Which is pretty close to the correct solution assuming that 10 pixels in one line are 9 pixels long (measured from center to center of first/last pixel):
print(sqrt(9 * 9 + 19 * 19 + 29 * 29));

image

I actually hope we find a less complicated solution!

Cheers,
Robert

1 Like

Hi,

The Implementation of Max Feret diameter in MorphoLibJ currently does not support 3D images… I suppose the result was computed on a single slice, resulting in a diameter lower than actual 3D value.

I have an implementation skeleton somewhere for long, so 3D version could be incorporated later in MorphoLibJ!

2 Likes

Thank you both for the answers.
@haesleinhuepf, you are completely correct that the length is pixel center to center :smiley:

The mentioned 3D Manager made me remember the 3D image suite from @ThomasBoudier. It contains a 3D ellipsoid fitting that also gives the maximum feret (with coordinates of the two pole points) :partying_face:

1 Like

Hi all @Jurgen_Gluch, @dlegland, @haesleinhuepf

The Max Feret is available in 3DManager, you need to activate the measurement in 3DManager Options (or the config icon).

The measurement is not activated by default because, as mentioned, it may take some time to compute especially for large objects.

Best,

Thomas

1 Like

Do you mean the orientation of the line that joins the two extreme points that contribute to the Feret diameter?

BoneJ’s Particle Analyser gives the orientation based on the inertia tensor and the best fit ellipsoid. It could give this Feret orientation as well, which is a very simple calculation (just the unit vector joining two points that are already known).

1 Like

I made PR that reports the points from with the direction can be calculated:

Would it help also to display the Feret axis in the 3D Viewer?

1 Like

@Jurgen_Gluch I’ve made some improvements to BoneJ’s Particle Analyser, including the ability to report and display the Feret points and axes, which are the green points and lines:

.
These should be available via the updater later this week.

2 Likes

Wow, this sounds great. I’ll test it out :star_struck:
That visualization will be helpful to get the impression and the feeling for the numbers. Thank you.

Cool - keep an eye on your updater.

Bear in mind that the max Feret algorithm is brute force and very slow on large particles. If it seems to have hanged and your CPU is running with one hot thread (shows as 100% in top or 100/nThreads % in other views) then it’s probably due to one huge particle taking ages to finish. You can speed it up by asking for for more surface mesh averaging in the setup dialog, but in that case you will lose fine features and small particles.

1 Like