Measuring wall thickness of plastic extruded sample



Hi there,
I work for a manufacturing industry producing cables. During the extrusion process of plastic material, we need to check if the product has the characteristics requested by the client. One of the most important parameter is the wall thickness. To check it, we bought a digital microscope to capture a snapshot of a product sample. The first image attached is the raw snapshot, the second one is the image after the threshold has been adjusted. What I need to measure is:

  • The maximum wall thickness;
  • The minimum wall thickness;
  • The mean wall thickness (as per international norms of the sector, the mean is calculated using 4 random wall thickness values, excluding the maximum and the minimum, but also a generic average value is ok).

In the future the above measurements should be automated as possible through a macro, because they should be done by an operator during the extrusion process.

I am very new to ImageJ and I am baffled with the amount of documentation and I am a bit lost, I would appreciate if someone could give me some hints on how to implement the above measurements; also some references to specific piece of documentation to read would be very helpful.

Thanks in advance,

Determine average width of irregular line
What is the "origin" of the polar transformation?
Cleaning an image from "noise"
Measure the thickness of an Irregular ring
Vertical Caliper Distance?

Hey @gio

Take a look at this older Forum thread:

I think the info to get the measurements you want will be in there - so you can use MorpholibJ’s Geodesic Distance Transform functionality.

Give it a go… and let us know if you have more specific questions. :slight_smile:



Good day Gio,

you may consider using the polar transformation.

See these threads:

Here is a first attempt:

From the transformed image you may easily get the measures, e.g. by evaluation of the horizontal profiles of the transformed image.

Finally please don’t use JPG-compressed images. Lossy compression introduces artifacts!

Good luck


Hi @etarena,
thank you for your reply.

I tried to use the Morpholibj plugin to get those distances, this is what I achieved.

  • I skeletonized the thresholded image.
  • I applied the Geodesic Distance Map function (MorphoLibJ -> Binary Images -> Geodesic Distance Map), using the skeleton as the marker and the thresholded image as the mask.
  • The result is the LUT image attached; please note that I had to convert the image to jpeg, because for some reason I can not upload the LUT image as generated by ImageJ.
  • I exported the LUT in a readable format i.e. a table listing for each index the value of red, green and blue (Image -> Color -> Show LUT and then click on List…)
  • The list is attached

I have a couple of questions I hope you can help me out with.

  • The table exported from the LUT image has 256 lines: they seem to me a very few number; maybe ImageJ exports just a little part of the data?
  • How can I read the results? For example, at the index 111 I have the following values: red = 215, green=32, blue = 38; how can I get a distance from those numbers?
  • How can I understand what point of the circle a certain index refers to? Actually, this is not really important, because I have to find the maximum, minimum and mean value, not in what point they are, but maybe in the future I will have to find also this datum.

Many thanks for your help,
gio (1.4 KB)


Hi @Herbie,
thank you for your reply.

This is what I get so far using the polar transformation.

  • First of all, I measured the center of mass of the image (Analyze -> Set measurements… and then Analyze -> Measure).
  • Then I applied the Polar Transformer with the following parameters:
    • Method: Polar
    • Degrees used for polar space: 360
    • Default center for cartesian space: not ticked (when asked for the center, I used the center of mass measured earlier)
    • For polar transforms, use one line per angle: not ticked (when asked for the number of lines in angle dimension I put 730)
  • I inverted the the image I obtained (Edit -> Invert)
  • The result (very similar to what you posted) is attached: please note that I had to convert the image to png because for some reason I am not able to upload images as saved by ImageJ.

Now I am stuck to the part of evaluating the horizontal profiles of the transformed image.

  • I selected all
  • I drew the plot profile (Analyze -> Plot profile…)
  • I get the graph attached
  • I exported the data in the attached excel file (999 Bytes)

How can I read the data I got in order to calculate minimum, maximum and mean thickness?



Good day Gio,

as always in the end things aren’t as easy as they might appear at the beginning …

  1. The center of mass is only one of possible centers for the polar transformation, fitting circle is another. You may even consider the latter as a mean of the fitted inner and outer contour. You must decide …

  2. You may transform either the halftone or the binarized image. In both cases you should binarize the transformed image. The decision is yours …

  3. For the profile, draw a horizontal line selection at the vertical position you want to measure. The profile values are either 0 or 255 and you get the width from the distance between the jumps.

  4. You have to decide whether the binarized images give sufficient precision of the measurements.

You can automate all processing steps by using a macro. The macro recoder may help to get the code for the processing steps.
Furthermore, have a look at the documentations:





Start reading the thread at this response:

@iarganda explains step-by-step how to extract the data you want… as far as the # of measures… that is most likely based on the length of your longest-shortest-path length. Each measure comes from a point/pixel along that line…



Hi @Herbie
as far as regards the center for the polar transforms and the accuracy, this is not a real issue for me: this will be an in line check (so the operator is aware if the extrusion process is proceeding correctly or something is going really wrong), the real test will be made in the laboratory by a technician with a much more precise instrumentation.

As far as regards the macro, thank you for the link: I am experimenting. For future reference of other users interested in the topic, here is the core of my macro: it scans all the lines of the image, and give the minimum, maximum and average value (please note that results are in pixel, but to get the real values is just a matter of a division):

var on = 0;
var measures = 0;
var max = 0;
var min = 0;
var total = 0;
var avg = 0;

for(i=0; i<730; i++) {
	run("Clear Results");
	makeLine(0, i, 419, i);
	profile = getProfile();
	for (j=0; j<profile.length; j++)
		if (profile[j] > 0) on++;
	if(min == 0) min = on;
  if(on < min) min = on;
  if(on > max) max = on;
  if(on > 0) measures++;
  total += on; 
	on = 0;

avg = total / measures;

print("Minimum: " + min);
print("Maximum: " + max);
print("Average: " + avg);



nice to see you’ve found a solution for the width measurement from the polar transform of your images!

Here is an ImageJ-macro that does the whole processing from the original gray-level image:

// imagej-macro "pipe wall thickness" (Herbie G., 14. March 2018)
requires( "1.51v" );
nme = "Polar_Transformer.class";
if ( !File.exists( getDirectory( "plugins" ) + nme ) ) exit( "Macro requires PlugIn \"" + nme + "\" !" );
if ( nImages != 1 ) exit( "A single image must be open!" );
a = newArray( "Center of Mass", "Center of fitting Circles" );
Dialog.create( "Polar Transformation" );
	Dialog.addChoice( "Method", a, a[0] );;
method = Dialog.getChoice();
run( "8-bit" );
setAutoThreshold( "Default dark" );
setOption( "BlackBackground", false );
run( "Convert to Mask" );
doWand( 0, getHeight() * 0.5 );
x = List.getValue( "XM" );
y = List.getValue( "YM" );
n = round( List.getValue( "Perim." ) );
run( "Select None" );
if ( method == a[1] ) {
	outer = newArray( 0, y );
	inner = newArray( x, y );
	fitCircle( outer );
	fitCircle( inner );
	run( "Select None" );
	x = ( outer[0] + inner[0] ) * 0.5;
	y = ( outer[1] + inner[1] ) * 0.5;
	method =  "CoC-"; 
} else { method =  "CoM-"; }
setBatchMode( true );
run( "Polar Transformer", "method=Polar degrees=360 number=[n] center_x=[x] center_y=[y]" );
run( "Make Binary" );
wMax = 0;
wMin = getWidth();
wMean = 0;
for ( i=0; i<n; i++ ) {
	w = calcWidth( i );
	wMean += w;
	if ( w > wMax ) wMax = w;
	if ( w < wMin ) wMin = w;
wMean /= n;
print( method + "Minimum: "+ wMin + " pixel" );
print( method + "Maximum: "+ wMax + " pixel" );
print( method + "Mean: "+ d2s( wMean, 2 ) + " pixel" );
setBatchMode( false );
function fitCircle( a ) {
	doWand( a[0], a[1] );
	run ("Fit Circle" );
	getSelectionBounds( x, y, w, h );
	a[0] = x + w * 0.5;
	a[1] = y + h * 0.5;
function calcWidth( idx ) {
	makeRectangle( 0, idx, getWidth(), 1 );
	p = getProfile();
	s = 0;
	for ( i=0; i<p.length; i++ ) { if ( p[i] > 0 ) s++; }
	return s;
// imagej-macro "pipe wall thickness" (Herbie G., 14. March 2018)



Thank you for that, very helpful and instructive!


Hello @gio

The LUT is just a color mapping between pixels values and their corresponding color representation. In ImageJ LUTs contain 256 colors, so that’s why.

The distance is not stored there but in the result distance image. Each pixel has a value which is the distance to the closest border.