Vertical Caliper Distance?

Hello all,
Does anyone know how to automatically measure the largest vertical distance within an object?

For example, in the image below I know all 4 objects have the same max vertical distance from the bottom to the top. If these were irregular objects with parts protruding vertically at different distances up and down, is there a way to measure the longest distance (height)?

Thanks for your insights in advance!
Matt

Good day Matt,

If the objects are nicely aligned and the background is zero, such as in your sample images, then do a horizontal projection and determine the width of the projection signal that is greater than zero.

Projection (Profile of an area): https://imagej.nih.gov/ij/docs/guide/146-30.html#toc-Subsection-30.11

Regards

Herbie

@Matt_RTHA

You can also take a look at MorphoLibJ’s Geodesic Distance Map plugin.

Here are some other Forum posts that describe how to apply it to images, etc.


If you have more questions - just ask - we are here to help!

eta

Thank you @anon96376101 and @etadobson,

I’ve been playing with both suggested methods. I think my original image example is a bit misleading as to what I really want.

I would like something like calculating local thickness (which I can do, but I don’t see how to get maximum vertical length values from), but more along the lines of the the image below:

As seen above:
I am working with these very irregular shapes, and I would like to avoid manually searching for the greatest distance between the top and bottom of this shape.

I tried understanding plot profile to perhaps do this, but I’m still a bit confused as how it measures distance.

Thanks,
Matt

Good day Matt!

I think my original image example is a bit misleading as to what I really want.

More than a bit (sorry!) …

The projection approach won’t work for your new sample image because it would give the following maximum distance (red):

But there is help and if you could post the new sample image without the drawn lines, we could try to give you further advice.

Regards

Herbie

Just a lesson I needed to learn (Always post an image of what you are actually looking at).

Here are some unedited images of what I am working with:

1 Like

Matt,

I shall report later today about a possible approach.

Regards

Herbie

Matt,

the following ImageJ macro does what you wish (Edit: slightly optimized):

// imagej-macro "maximum height" (Herbie G., 14./15. March 2018)
requires( "1.51w" );
if ( nImages != 1 ) exit( "A single binary image must be open!" );
setBatchMode( true );
w = getWidth();
h = getHeight();
maxHeight = 0;
for ( i=0; i<w; i++ ) {
	makeRectangle( i, 0, 1, h );
	setKeyDown( "alt" );
	p = getProfile();
	setKeyDown( "none" );
	top = 0;
	while ( p[top] == 0 && top < h-1 ) { top++; }
	bot = 0;
	if ( top < h-1 ) {
		Array.reverse( p );
		while ( p[bot] == 0 && bot < h-1 ) { bot++; }
	} else { bot++; }
	height = h - bot - top;
	if ( height > maxHeight ) maxHeight = height;
}
print( maxHeight );
setBatchMode( true );
exit();
// imagej-macro "maximum height" (Herbie G., 14./15. March 2018)

Paste the above macro code to an empty macro window (Plugins >> New >> Macro) and run it.

HTH

Herbie

2 Likes

Thank you very much for this script @anon96376101!
This is perfect!

Thank you, @anon96376101, for demonstrating the power of the macro language!


Still, I was intrigued by your initial suggestion to use a projection to solve the issue, and I believe you can still do this on the given sample image by:

  1. projecting along y with a Sum projection, then
  2. projecting along x with a Maximum projection.

The result should be a single sample value that contains the maximum vertical caliper found at any given position in x (when taking into account that the sum of pixels needs to be divided by 255 to account to the 8-bit nature of binary images in ImageJ).

So I couldn’t resist and wrote this little Groovy script using ImageJ Ops to replicate the analysis of your macro (you can run it from the script editor after choosing Language > Groovy):

#@ Dataset input
#@ OpService ops

sumOp = ops.op("sum", input)
maxOp = ops.op("max", input)

// Create SUM projection along Y axis
sumProjection = ops.run("img", [input.dimension(0)])
ops.run("project", sumProjection, input, sumOp, 1)

// Add new dimension to allow second projection
sumProjection = ops.run("addDimensionView", sumProjection, 0, 0)

// Create MAX projection along X axis
maxProjection = ops.run("img", [1])
ops.run("project", maxProjection, sumProjection, maxOp, 0)

// Get value (divide by 255 to account for 8-bit binary image)
println maxProjection.firstElement().get() / 255

(A nice side effect of this is that you can also calculate the mean vertical caliper or its standard deviation by changing to a different op for the second projection step.)


EDIT: But coming back to the original question: @Matt_RTHA depending on your task, you might also want consider measuring Feret’s (min and max) diameter on your irregular objects, except if you have reasons to have the strictly vertical orientation as a constraint.

No maximum projection here for the macro language but perhaps I’m missing something.

I must admit that I don’t understand this ops business and the code does’t look transparent to me.

The IJ-macro language has many advantages and in the very few cases where it is too limited or too slow, Java-plugins are the way to go for me. Javascript to me is one of the worst inventions and other scripting languages I don’t speak.

For someone who is not from engineering/informatics/physics and who needs to use ImageJ, the macro language is by far the easiest way to automate image processing. Thanks Wayne who, in the first place, cares for the user not for innovations per se.

Just my 5 Euro-cents

Herbie

This is some cool code @imagejan.

I thought about using Feret’s diameter, but only the vertical thickness is useful for my particular problem.