Discrepancies in Histogram after Reslice

Hi,

I have a stack of 150 slice in the plane XY of a composite material. I resliced the stack so that I get the YZ projection and then, I performed the same processes, in parallell with a macro, over the stack in the XY and YZ just to double check the results.

I applied to them a filter (3D-Mean: Radius 3) and then transformed them to 8-bit scale. I was expecting to get the same histogram for both stacks since their original histogram was the same and they contain the exact same information, BUT, a change in the histogram happened after the Filtering. See table below:

What could be the discrepancy between the histograms in the XY-stack and the re-sliced YZ-stack after filtering? Why the 3D-Mean Filter gives me a different result depending on wether it is applied to a XY stack or a YZ stack?

This thing is kind of driving me crazy!

Thank you!!

Hi @pedgalher,

Welcome to the forum.

That is really annoying.

Question - how is it possible to have a mean of >100k when 8 bit values only represent 0 - 255?

Short answer, conversion to 8-bit uses the min/max values of the brightness / contrast settings when quantizing, meaning that if the contrast settings were different between the two, then the conversion would be different - giving different results.

The reason for that is documented here (and a possible solution).

Converts to 8-bit grayscale. ImageJ converts 16-bit and 32-bit images to 8-bit by linearly scaling from min–max to 0–255, where min and max are the two values displayed in the Image▷Adjust▷Brightness/Contrast… [C]↓. Image▷Show Info… [i]↓ displays these two values as Display range . Note that this scaling is not done if Scale When Converting is not checked in Edit▷Options▷Conversions…↑ …)

John

1 Like

Commas indicate decimals here.

Thank you for your answer! Unfortunately, the contrast settings were the same for both cases (I have just checked it) :frowning:

Ha, of course. Thanks for clarifying.

Weird. If you could share a macro / script that reproduces this issue, it could help us get to the bottom of this.

John

1 Like

Sure! The code might not be the most optimised but it does the job.


//The code above was just the directories definition to load images and save the images...

//ANALYSIS

//Open .Vol data as Raw Data
run("Raw...", "open=[" + input_dir + "] image=[32-bit Real] width=2000 height=2000 number=475 little-endian");

// Rotate the image 39 degrees
run("Rotate... ", "angle=39 grid=1 interpolation=Bilinear stack");

//ROI --> setTool("rectangle");
makeRectangle(399, 621, 1296, 567);
run("Specify...", "width=1266 height=333 x=429 y=738 slice=189");
run("Duplicate...", "duplicate");
selectWindow("Test 2.vol");
selectWindow("Test 2-1.vol");
selectWindow("Test 2.vol");
close();
selectWindow("Test 2-1.vol"); // We work with this new stack

//Remove Slices so that we keep only the slices [120 - 270]
run("Slice Remover", "first=1 last=119 increment=1");
run("Slice Remover", "first=151 last=356 increment=1");
run("Image Sequence... ", "format=TIFF name=slice_ save=[" + output_dir_xy_orig + "\\slice_0000.tif" + "]"); //Save this first image
	
//Generate YZ-projection stack
run("Reslice [/]...", "output=1 start=Right avoid"); //We get a new stack in the plane YZ so that the slices are along the X-Axis//If we would have started in the left it would have been more straightforward
selectWindow("Reslice of Test");
run("Image Sequence... ", "format=TIFF name=slice_ save=[" + output_dir_yz_orig + "\\slice_0000.tif" + "]"); //Save this first image


//PROCESSING OF XY-PROJECTION
selectWindow("Test 2-1.vol")

//Filter: 3D-Mean
run("Mean 3D...", "x=3 y=3 z=3");
run("Image Sequence... ", "format=TIFF name=slice_ save=[" + output_dir_xy_filter + "\\slice_0000.tif" + "]"); //Save this filtered image
run("8-bit");

//Contrast modification
//run("Brightness/Contrast...") --> Contrast:[70-255]
setMinAndMax(70,255);
run("Apply LUT", "stack");
run("Image Sequence... ", "format=TIFF name=slice_ save=[" + output_dir_xy_contrast + "\\slice_0000.tif" + "]"); //Save this modified image

//Thresholded Image
setAutoThreshold("Default stack"); // Apply threshold to the whole stack
setThreshold(0, 110);
setOption("BlackBackground", false);
run("Convert to Mask", "method=Default background=Light");
run("Invert", "stack");
run("Image Sequence... ", "format=TIFF name=slice_ save=[" + output_dir_xy_binary + "\\slice_0000.tif" + "]"); //Save the thresholded image


//PROCESSING OF YZ-PROJECTION
selectWindow("Reslice of Test");

//Filter: 3D-Mean
run("Mean 3D...", "x=3 y=3 z=3");
run("Image Sequence... ", "format=TIFF name=slice_ save=[" + output_dir_yz_filter + "\\slice_0000.tif" + "]"); //Save this filtered image
run("8-bit");

//Contrast modification
//run("Brightness/Contrast...") --> Contrast:[70-255]
setMinAndMax(70,255);
run("Apply LUT", "stack");
run("Image Sequence... ", "format=TIFF name=slice_ save=[" + output_dir_yz_contrast + "\\slice_0000.tif" + "]"); //Save this modified image

//Thresholded Image
setAutoThreshold("Default stack"); // Apply threshold to the whole stack
setThreshold(0, 110);
setOption("BlackBackground", false);
run("Convert to Mask", "method=Default background=Light");
run("Invert", "stack");
run("Image Sequence... ", "format=TIFF name=slice_ save=[" + output_dir_yz_binary + "\\slice_0000.tif" + "]"); //Save the thresholded image


Thank you very much for your interest!

Pedro

1 Like

Not sure if this is it, but in this section:

//Filter: 3D-Mean
run("Mean 3D...", "x=3 y=3 z=3");
run("Image Sequence... ", "format=TIFF name=slice_ save=[" + output_dir_xy_filter + "\\slice_0000.tif" + "]"); //Save this filtered image
run("8-bit");

//Contrast modification
//run("Brightness/Contrast...") --> Contrast:[70-255]
setMinAndMax(70,255);
run("Apply LUT", "stack");
run("Image Sequence... ", "format=TIFF name=slice_ save=[" + output_dir_xy_contrast + "\\slice_0000.tif" + "]"); //Save this modified image

setMinAndMax is called after run("8-bit"). Perhaps try moving that function call to before you convert to 8-bit. I’d suggest changing the above to

//Filter: 3D-Mean
run("Mean 3D...", "x=3 y=3 z=3");
run("Image Sequence... ", "format=TIFF name=slice_ save=[" + output_dir_xy_filter + "\\slice_0000.tif" + "]"); //Save this filtered image
setMinAndMax(70,255); // will probably need to change the values here
run("Apply LUT", "stack");
run("8-bit");
...

John

1 Like

It works! Not exactly what you suggested but you gave an amazing idea, which is converting to 8-bit before doing all the stuff. Thank you soooo much! I hadn’t thought about putting the 8-bit conversion before the processing actually. I have just tested it and it works :slight_smile:

I converted the image stack into 8-bit (it was a 32-bit image stack initially) before the all the pre-processing (filtering, contrast adjustment…) and the histograms were the same in all the subsequent processes. However, the filtering gives me a slightly more diffused image but I suppose that’s because I’m only working now with 255 grayvalues instead of 2^32 values, but I still can accept it.

Thank you!!

1 Like