Correcting brightfield illumination artifacts



Hi All,

@Alex_H @haesleinhuepf @imagejan

I was wondering whether there is an ImageJ workflow already for correcting brightfield illumination?
I just tried an own attempt (median filter based) and I guess that would be OK but I also do not want to reinvent the wheel…

Input image

Gradient (Computed from downsampled and median-filtered)

Subtract gradient and then also divide by gradient


Good day,

are you sure the microscope was set-up correctly?




Hi Tischi,

there are a few documented methods.
From these, I found the FFT bandpass filter to work nice and fast, but the result using your image posted above is not necessarily of better quality compared to what you already have.


Good question :slight_smile:
It is low mag high throughput multi-well imaging, the gradient comes because of the well shape.


Thanks for the tip! The FFT is much faster than subtracting the median. This might be helpful!


What magnification?
If overall magnification is small, a normal Microscope may be sub-optimum and special illumination may be needed.

Without seeing the multi-well objects and the whole optic set-up it’s difficult to tell what’s wrong.




the BioVoxxel Pseudoflatfield correction with a radius around 10 also doesn´t look too bad and it´s super easy to use. There are some artifacts in the lower left corner which I guess are due to the jpeg format of the sample image.


If you’re only after a band pass, you could also try Plugins > Integral Image Filters > Normalize Local Contrast which is even faster than the FFT bandpass. Try various block-sizes with preview checked

The integral filters are explained here:

If you have many images from the same microscope under similar settings, you can estimate the flatfield with CIDRE

If you have more images than CDRE can digest or you’re interested in 3D flatfields (I gues you’re not ;)), you can use our not yet published scale up of the CIDRE approach


In fact, I do have more images. My naive approach was just to compute a median projection, thereby ideally removing the objects and only being left with the flat-field. This of course does not work very robustly if there are many objects in every image. Thus, thanks for pointing out CIDRE I will check it out!


@axtimwalde @igorpisarev @Kevin_Smith

CIDRE works really well! However I would need to write an other UI that enables batch-processing of many experiments and also accepts Tiff stacks as input. I guess it would make to use your new code as a starting point, rather than the original one?

Your new code (right?):

Original code:


As an alternative to CIDRE there is also BaSiC.
There is an update site available for it and you can find a bit of demo/documentation here.
If I remember correctly it does work on stacks and was quite fast.


Results look good, works on stacks and is macro recordable => one can easily batch it!
Very nice!


Just for the record (maybe other people will find this post interesting):
CIDRE and BaSiC are giving very similar results for my data (just different treatment of the offset due to the particular CIDRE settings that I used):


Good day Christian,

unfortunately you didn’t use the provided sample image for your experiments. Furthermore, the provided sample image is JPG-compressed …

Here is what I get from your sample image (profile from left bottom to right top)



when using this little ImageJ-macro:

w = getWidth();
h = getHeight();
img = getImageID();
makeLine(0, h-1, w-1, 0);
run("Plot Profile");
run("Select None");
run("Bandpass Filter...", "filter_large=100 filter_small=0 suppress=None tolerance=0");
run("Restore Selection");
run("Plot Profile");




Hi Chistian,

to me it seems you need a flat-field correction.
This means, you should divide by the correction, not subtract it (also the Fourier filters do a subtraction, not a division). Otherwise the features in the dark (insufficiently illuminated) parts of the image get too weak.
You could try, e.g., the following macro:

run("Duplicate...", "title=flat");
run("Gaussian Blur...", "sigma=2");
run("Subtract Background...", "rolling=500 light create sliding");
imageCalculator("Divide create 32-bit", origID,flatID);

But there are some additional problems:

  • In the dark areas, the intensity is extremely low (pixel value only 3-4), so you won’t get a reasonable result there.
  • I have the impression that the image was taken with increased contrast, so zero intensity does not correspond to a gray level of zero. Maybe there was also some nonlinear transfer curve (e.g. Gamma,
  • The features look different near the center and where you have a large gradient of the intensity. Near the center, they are mainly dark; near the edge they are bright one one side.

So I think you should definitely improve the illumination and/or alignment!


Perfectly agreed, see here:

also the Fourier filters do a subtraction, not a division

In the case in question they zero out harmonic spatial waves of large periods. Division is the way to go but improved image acquisition is superior!



Here are again results obtained from the supplied sample image. Profiles are on the image diagonal from left bottom to right top.

  1. According to Michael’s ImageJ-macro:

  2. Bandpass-filtered logarithmically transformed image after exponential re-transformation:


Hi @Christian_Tischer,

did you by any chance already work on a script to batch-process your data?

I have now a similar dataset (a time-laps of 60 wells with 6x6 tiles per well in Brightfield) and it would be great if you would have code that I could use :slight_smile: Thanks!


I almost finished implementing the BaSiC approach…
I still have to test the batching though…


Please follow the progress in this thread: Automated batch processing


Could you please test it?
Update site: EMBL-CBA
And then at the very bottom of Plugins > Restoration > Illumination > BaSiC
(I am not sure it will work immediately because I had some strange dependency issues…)