Normalizing brightness across a image stack

Hello all,

I’m doing analysis on a micro-CT image stack, but due to a problem with the X-ray source the images loose brightness overtime. When I analysed the mean values of the samples they drop in a linear fashion and I would like to adjust them so the mean would stay the same.

This should be just a simple question of increasing brightness of the images so they each have the same mean. I do also have to exclude the air from the sample as that stays at the max saturation and doesn’t get dimmer with the rest of the sample.
Unfortunately I have no programming skill and can’t seem to be able to get this to work.

Any help would be greatly appreciated.

1 Like

Hello there,
Do you think the normalize option under the Process>>Enhance Contrast tab would help your cause?

Unfortunately its not much help as the values for air don’t change so I would have to somehow exclude it. Also because the sample is not exactly stable and moves in the frame so I couldn’t figure out how to only apply it to the sample. I was able to get a selection of the sample in each slice but i’m not sure if I can apply enhance contrast to the selections in ROI manager.

Do you think it would be possible to upload a small sample of the stack which you are having trouble with? This would make things it easier for the audience here to help you with suggestions.


It is possible to enhance the contrast of an entire image/stack based on an ROI

Hello all,

We recently had someone with a similar problem, an unstable brightfield timelapse, where the bulb was a bit too slow to light up before the camera started acquiring, which resulted in flickering.

We implemented a tool based on the great Correct Bleach plugin’s histogram2.HistogramMatcher class.

Basically it takes the first slice of the first image in a folder as a reference, then applies Histogram matching to all the other slices in all the other stacks.

We included a basic normalization step in case the user wants to ensure all values are within a certain range.

I_{norm} = \frac{I_{ori} - I_{min}}{I_{max}-I_{min}} \times usr_{max} + usr_{min}

where I_{min} and I_{max} are the minimum and maximum values found in the first slice of the first image and usr_{min} and usr_{max} are the new min and max values set by the user.

The script currently will create a new image that is 16-bit but as it is the case for your images, I opted to provide it as-is.

I tested it on some of your images (No need to crop the saturated pixels or anything) and it seems to do a good job.
Top is your images before applying the script
Middle is after
Bottom is the ratio of the two images

The scale was exaggerated to show the differences.

If you notice, on the 7th image, there is a bit of an issue (a few pixels were basically set to 0). That is because of the black line atop some of your images.
My suggestion is to open all your images as a stack, crop it out to make sure you don’t get artifacts like those black lines, then save it as a tif stack in a folder. You can then run the script and it should give you a nice result, so long as there is roughly the same information on each slice

You can download it from this Gist. Feedback is always welcome


Here is how I solved my issue.
I wrote a macro that I could use to alter the brightness based on a 4th order polynomial function I got from doing some measurement and analysing the trendline in excel.

for (i=1; i<= nSlices; i++) {
showProgress(i, nSlices);
//var a to d are the multipliers for the polynomial function
var a=0.000003;
var b=-0.0017;
var c=0.3026;
var d=-42.744;
var x=-(a*(pow(getSliceNumber(),4))+(b*(pow(getSliceNumber(),3)))+(c*(pow(getSliceNumber(),2)))+(d*getSliceNumber()));
setMinAndMax(-(x), 65535-(x));
run(“Apply LUT”, “slice”);
run(“Next Slice [>]”);

It seems to work great :slight_smile: