Convert variations in 2 D boundary to 1 D

#1

My goal here is to get the variations in the boundary (see the image) and plot in 1D with respect to a constant axis (either x-axis or y-axis).

Note: The yellow colored boundary is what I am concerned with.

Drawing a circle around a point
Measuring wall thickness of plastic extruded sample
#2

Good day!

[â€¦] variations in the boundary [â€¦]

with respect to what, a circle?

Clueless,

Herbie

PS:
Here is a polar plot that shows the deviation of the contour from a circle around the â€ścenter of massâ€ť of the contour:

`mean = 35.63 Â±6.94 pixel`

You may also have a look at this thread:

#3

Other ways of doing what you want are:

• elliptic Fourier descriptors
• curvature /scale space analysis
• fractal dimension (although the contour you showed does not look fractal)

#4

@Herbie

Yes, I need the variations with respect to the bounding circle. The image which you have put up is exactly what I am looking for. How did you come up with the Polar Plot?

Regards,
kbimagej

#5

@gabriel

Does ImageJ have any plugins which includes your method? Also, what do you mean by Fractal dimension?

Regards,
kbimagej

#6

Good day!

Here you can get the ImageJ-plugin for the polar transformation:
https://imagej.nih.gov/ij/plugins/polar-transformer.html

For me two ways of defining the crucial center for the transformation appear easily feasible:

1. Center of mass (see â€śSet Measurementsâ€¦â€ť)
2. Center of the fitting circle (see â€śEdit >> Selection >> Fit Circleâ€ť)

Please note that both approaches lead to slightly different results. You must decideâ€¦

Regards

Herbie

#7

An implementation for the elliptic fourier analysis:
http://imagejdocu.tudor.lu/doku.php?id=plugin:analysis:fourier_shape_analysis:start

I do not remember an existing plugin for the curvature analysis, but there are plenty of references on how to do it.

#8

Hi Herbie,

I got the centers for the ROI in the image posted. I understand the intuition that it has to do something with the variations in radius from the fitting circleâ€™s radius and we have to iterate through varying angles i.e. theta to get the graph. How do I reciprocate this idea so that I get a similar graph as the one you posted using Polar Transformer plugin?

Regards,
kbimagej

#9

Good day,

do you have the the imageJ plugin â€śPolar_Transformer.classâ€ť installed?

1. Then you have to have an image with the binary contour of your image open in ImageJ:

2. Start the plugin and uncheck all of the three check boxes in the appearing dialog. Then click OK.

3. A new dialog appears and for the time being leave it with the given entry of 360. Then click OK.

4. A new dialog appears in which you are to enter the center coordinates. Then click OK.

Youâ€™re done.

Regards

Herbie

#10

Hi Herbie,

Thanks for quick reply. I tried your method but I get a vertical image totally black. To get the binary contour, I saved the ROI from the ROI Manager and applied it on a new black image created through MS Paint. Is the process okay?

Many Thanks,
kbimagej

#11

Please use the binary contour Iâ€™ve provided and try with it.

Regards

Hebrie

#12

I got the graph with your image. But I am getting a black vertical image when I use my binary contour. Is there a problem with the way I have generated the binary contour?

Many Thanks,
kbimagej

#13

In this contribution
http://forum.imagej.net/t/convert-variations-in-2-d-boundary-to-1-d/9829/9?u=herbie
Iâ€™ve provided the binary contour image from which I get the polar transform shown earlier.

binary contour image.

Regards

Herbie

#14

with the selection is open in ImageJ.

In this case you can run the following macro to get the binary contour image:

``````orig = getImageID;
setForegroundColor( 255, 255, 255 );
newImage( "BinaryContour", "8-bit black", getWidth(), getHeight(), 1 );
run( "Restore Selection" );
run( "Draw", "slice" );
run( "Select None" );
selectImage( orig );
close();
``````

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

HTH

Herbie

Getting co-ordinates of ROI
#15

@Herbie

Works like a charm. One last question though. I would like to find the number variations i.e. no. of local maximas and minimas. Any idea on this? I tried using Analyze Line Graph (Analyze -> Tools ->Analyze Line Graph). But it didnâ€™t give me any result.

Many Thanks,
kbimagej

#16

I would like to find the number variations i.e. no. of local maximas and minimas.

This depends on what you regard as relative extrema. A tolerance value must be defined to give you these numbers. Have a look at
https://imagej.nih.gov/ij/developer/macro/functions.html
and especially:

``````Array.findMaxima(array, tolerance);
Array.findMinima(array, tolerance);
``````

Now itâ€™s time to learn macro coding â€¦
https://imagej.nih.gov/ij/developer/macro/macros.html

Regards

Herbie

#17

just an add to the suggestion of @Herbie to use the macro and findMaxima method, you can also take a look to this FindPeaks tool (https://imagej.net/Find_Peaks) in the BAR (https://imagej.net/BAR) plugins collection

#18

Finally here is an ImageJ macro that gives you all of the desired values of a closed contour image and saves the polar transform data to disk:

``````// imagej-macro "maximum height" (Herbie G., 15. March 2018)
requires( "1.51w" );
nme = "Polar_Transformer.class";
if ( !File.exists( getDirectory( "plugins" ) + nme ) ) exit( "Macro requires PlugIn \"" + nme + "\" !" );
if ( nImages != 1 )  exit( "A single contour image must be open!" );
run( "8-bit" );
run( "Make Binary" );
orig = getImageID();
nme = split( getTitle(), "." );
tol = 18;
a = newArray( "Center of Mass", "Center of fitting Circle" );
Dialog.create( "Polar Transformation" );
Dialog.addNumber( "Tolerance", tol, 0, 2, "" );
Dialog.show();
method = Dialog.getChoice();
tol = 10 * round( Dialog.getNumber() );
if ( method == a[0] ) {
List.setMeasurements;
x = List.getValue( "XM" );
y = List.getValue( "YM" );
nme = nme[0] + "_CoM.csv";
} else {
selectLine();
run( "Fit Circle" );
getSelectionBounds( x, y, w, h );
x += w * 0.5;
y += h * 0.5;
run( "Select None" );
nme = nme[0] + "_CoC.csv";
}
path = getDirectory( "Where to save the results?" ) + nme;
setBatchMode( true );
getRawStatistics( n, mn );
n *= mn / 255;
run( "Polar Transformer", "method=Polar degrees=360 number=[n] center_x=[x] center_y=[y]" );
run( "Make Binary" );
run( "Skeletonize" );
selectLine();
run( "Save XY Coordinates...", "save=[" + path + "]" );
open( path );
a = newArray( nResults );
selectWindow( "Results" );
for ( i=0; i < nResults; i++ ) a[i] = getResult( "X", i );
run( "Close" );
Array.getStatistics( a, mi, mx, mn, std );
print( method + ":  x = " + d2s( x, 2 ) + "; y = " + d2s( y, 2 ) + ";" );
print( "Mean radius = " + d2s( mn, 2 ) + fromCharCode( 177 ) + d2s( std, 2 ) + " pixel;" );
print( "( min = " + mi + "; max = " + mx + "; )" );
tol = round( tol / ( mx - mi ) );
relMx = Array.findMaxima( a, tol );
print( "Tolerance = " +  tol + ":  relMin = " + (relMx.length-1) + "; relMax = " + relMx.length + ";"  );
selectImage( orig );
run("Revert");
setBatchMode( false );
exit();
function selectLine() {
yPos = getHeight() * 0.5;
makeRectangle( 0, yPos, getWidth(), 1 );
p = getProfile();
p = Array.findMaxima( p, 0 );
Array.reverse( p );
doWand( p[0], yPos );
}
// imagej-macro "maximum height" (Herbie G., 15. March 2018)
``````

HTH

Herbie