Clear outside of 3D porous object but keep stuffs in pores

Hi everyone,

I’m new in ImageJ. I’m trying to analyse a 3D porous sample. The sample is in water and there are water and air phases in the pores and want to clear the outside of the 3D object but keep the phases in the pores. This means I can’t just use the grey level threshold to select the object. And it is not a standard cylinder in the Z direction so I can’t just create a shape from one slice and cut through. Any tool or plugin in ImageJ can do this?

Thanks

Jerry Wang

@Jerry_Wang

Welcome to the Forum Jerry!

So… I am sorry, but I did not quite follow exactly what you need/want to segment. I do not know your science - so got lost in the jargon a bit (what’s are ‘phases in the pores’?)… And why can’t you use grey levels to segment? (Too - I can only see the top image - the second image did not work when I tried opening it. ??)

But anywho… I assumed you want to segment the light-grey blobs within the circle? So I tried two ways just quickly without much refining… so methods can be improved…

1) Auto-Thresholding using Otsu method (this was without any pre-processing):

2) Using Trainable Weka Segmentation plugin (also works in 3D) …

Perhaps you can clarify things a bit - but hope this helps get you started at least…

Here are some other Segmentation links for ImageJ you might find helpful:

eta :slight_smile:

1 Like

Hi Ellen,

Thank you very much for your help! Sorry if I didn’t explain clearly. What I want is to fit the sample with a circle or ellipse, I want to keep everything inside the circle and clear outside. It is a 3D object but the edge of the object is not always the same in the Z direction. So I can’t cut through with the same shape on each slice. Any way to do this automatically on each slice?

Thanks

@Jerry_Wang

Do you want to measure the area of this circle? What is the ultimate goal in doing this?

I think we can figure something out and then you can definitely apply those same steps - once we figure out the best method - per slice … using Built-In Macro Functions and for loop.

eta

I’m not measuring the area. I just want to leave the area within the circle for further analysis. I’m not interested in the part outside. But I want to keep everything inside the circle. I’m thinking about how to have the best-fitted circle and how to do it on all slices automatically. Thank you very much for the hints.

Good day Jerry,

here is a macro that may get you started, will say, it works for your example image:

run(“Duplicate…”, " ");
setAutoThreshold(“Default”);
run(“Convert to Mask”);
run(“Open”);
doWand(0, 750);
run(“Convex Hull”);
close();
run(“Restore Selection”);
setBackgroundColor(0, 0, 0);
run(“Clear Outside”);
run(“Select None”);

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

I hope it doesn’t matter that the final selection isn’t a perfect circle or ellipse.

HTH

Herbie

@Jerry_Wang

I wrote up a quick macro that fits a circle to each slice in your stack… you might have to alter the dilate/erode/fillholes steps as you see fit… but this seems to work… you get a ROI created for each slice in the image:

image = getTitle();

getDimensions(w, h, channels, slices, frames);

setAutoThreshold("Otsu dark");
//run("Threshold...");

for (i=1; i<slices+1; i++) {
	Stack.setFrame(i);
	run("Create Mask");
	run("Dilate");
	run("Dilate");
	run("Erode");
	run("Erode");
	run("Fill Holes");
	run("Analyze Particles...", "add");
	roiManager("Select", i-1);
	run("Fit Circle");
	roiManager("Add");
	roiManager("Select", i-1);
	roiManager("Delete");
	selectWindow(image);
    }

let me know if it works for you.

eta :slight_smile:

Thank you Herbie! I will try this and also the macro given by Ellen.

Thank you Ellen! This is what I want!

1 Like

Jerry,

did you compare the results from both approaches for your example image?

“Fit Circle” and even “Fit Ellipse” cut off quite a portion of your sample, “Convex Hull” of course does not.

Regards

Herbie

Thanks Herbie! Yes, you are right. ‘Convex Hull’ is a better way. Thank you a lot. This helped me a lot!

Best regards

Jerry

Dear Jerry,

and here is an attempt to apply my approach to a stack of images:

requires( "1.51p" );
setBatchMode( true );
setBackgroundColor( 0, 0, 0 );
halfHeight = getHeight() / 2;
for ( i=0; i<nSlices; i++ ) {
  setSlice( i+1 );
  run( "Duplicate...", "use" );
  setAutoThreshold( "Default" );
  run( "Convert to Mask" );
  run( "Open" );
  doWand( 0, halfHeight  );
  run( "Convex Hull" );
  close();
  run( "Restore Selection" );
  run( "Clear Outside", "slice" );
  run( "Select None" );
}
setSlice( 1 );
setBatchMode( false );

HTH

Herbie

1 Like

Thank you Herbie! I use the following Macro and it totally sovled my problem!

requires( "1.50p" );
setBatchMode( true );
setBackgroundColor( 0, 0, 0 );
halfHeight = getHeight() / 2;
for ( i=0; i<nSlices; i++ ) {
  setSlice( i+1 );
  run( "Duplicate...", "use" );
  setAutoThreshold();
  setThreshold( 40694, 65535 );
  run( "Convert to Mask" );
  run( "Open" );
  run("Dilate");
  run("Dilate");
  run("Dilate");
  run("Dilate");
  run("Dilate");
  run("Dilate");
  run("Dilate");
  run("Dilate");
  doWand(0, 750);
  run( "Convex Hull" );
  run("Enlarge...", "enlarge=-6");
  close();
  run( "Restore Selection" );
  run( "Clear Outside", "slice" );
  run( "Select None" );
}
setSlice( 1 );
setBatchMode( false );
1 Like

Jerry,

that’s interesting because it shows that your original images are 16bit images.

Apart from that, I don’t think it’s a good idea to use a fixed thresholds because with other stacks the macro may not give comparable results.

Do you really need the “Dilate”-operations and why do you have to shrink the selection by 6 pixel. I think it should work without both, if you use a suitable automatic threshold method.

In any case, you should change

doWand( 0, 750 );

to

doWand( 0, halfHeight );

Presently, I can’t test your macro because I don’t have your test image as 16 bit.

Regards

Herbie