Determining the average colour of all individual ROIs and the surrounding area

I need to accomplish two things for a bunch of images, using a macro:

  1. Determining the average CIELAB value for each individual particle, detected with the “Analyze Particle” tool
  2. Determine the average CIELAB value for surrounding area (i.e. the whole image except the are inside the ROIs determined)

While the second task should be fairly simple, the first requires a bit of knowledge on the scripting language, which I’m unfortunately missing.

Determining the average colour manually is very simple via the Average Color-Plugin (Image → Color → Average Color). Is there any way to get this value within a macro? The macro recorder only shows run("Average Color", "cielab");

Regarding the colour of each individual ROI:
I assume I would need to iterate through all the ROIs (similar to here: ROI Iterator Demo and ideally getting the average CIELAB-value of each ROI by the above mentioned Average Color-Plugin.
If this is the way to go, then I would try to put a macro together and maybe ask for correction/suggestions to get it finally running.

For the surrounding area I would make a selection from all ROIs using roiManager("Show All with labels"); and roiManager("Combine");, subsequently inverting it with run("Make Inverse"); and then determine the average color from the selection.

Thanks already for all suggestions!

Hi MijoDodo,
The Roi Iterator Demo is a plugin coded Java.
It could be modified to include the command < run("Average Color", "cielab");> for each Roi.

Unfortunately the Average Color-Plugin is part of FIJI and compiling Java files in FIJI can easily create a strong headache. So you either have to create your solution in an IDE or you should put out some Ibu :woozy_face:

In principle it should work.

The Rois have to be transferred from the Roi Manager to the image as Overlay before using the ‘Roi Iterator Demo’ plugin (IJ menu Image/Overlay/From Roi Manager).


Thank you for this information!

Well, I don’t necessarily have to use the Average Color-Plugin if things get too complicated. Initially I just thought it would be a nice way to access its functionality of calculating the CIELAB values.

I have come up with the following approach and it seems to work with the first example images I was testing it. I used the “RGB to CIELAB”-function and then determined the mean gray value within each ROI for each of the three slices, which should be the average L-, a-, and b-values.

//add procedure to detect particles here

run("RGB to CIELAB");

//calculate mean L-, a-, and b-values for individual ROIs
for (i=0; i<roiManager("count"); i++) {
roiManager("Select", i);
LValue = getValue("Mean");
setResult("LValue ", i, LValue);
aValue = getValue("Mean");
setResult("aValue ", i, aValue);
bValue = getValue("Mean");
setResult("bValue ", i, bValue);

//calculate mean L-, a-, and b-values for surrounding area
run("Make Inverse");
LValueSurrounding = getValue("Mean");
setResult("LValueSurrounding ", 0, LValueSurrounding);
aValueSurrounding = getValue("Mean");
setResult("aValueSurrounding ", 0, aValueSurrounding);
bValueSurrounding = getValue("Mean");
setResult("bValueSurrounding ", 0, bValueSurrounding);

saveAs("Measurements", output + savename + ".csv");

So my Question to those ImageJ users more experienced than me: Is the above described procedure correct in order to determine the average CIELAB values for each of the particles or am I missing something?
Code-wise it might not be the nicest macro, but it seems to do the job, so far.

Colors are represented by 3 values defining a point in a coordinate system.
Different coordinate systems can be used. They are defined by the ‘Color Space’.
Important color spaces are RGB, sRGB, CIE XYZ, CIE Lab, YUV, (HSB, HSL) etc.
Transformation between some color spaces are non-linear.
That means that 3 colors laying on a straight line in color space A do not lay on a straight line in color space B.

Since the mean (average) color of two colors is a point on the straight line between this two colors, the resulting average depends on the used color space.

Not diving to much into color theory and to make the story short:
Averaged color values calculated in RGB and Lab are (~linear) comparable.
They deviate from averaged values calculated in sRGB.

Your Lab conversions seems to be a good choice.
see Converting RGB to CIELAB and averaging

BUT … as you can find in
The RGB to XYZ conversion assumes sRGB as input …
The RGB to Lab* conversion assumes sRGB for conversion …”

That means that your RGB images should be in sRGB space.
Are you sure they are?
If they are not, then using the RGB_to_Lab conversion introduces an additional non-linearity instead of compensating the non-linearity of sRGB.
(I’m not sure if the function you are using is based on this color-space-converter.)

Its so cool to work with colors and so easy to err oneself.
Be careful.

To answer your question

Your procedure seems to be correct. (I haven’t checked the part of combining and inverting the Rois.)
You calculate average CIALAB values.

My recommendations:

  • Yes, you can (in principle) calculate average color values in the way defined by your macro (average color value = color value of averaged components).
  • Be careful with the averaged color values because those values can represent color which are not existing in your image.
  • Use your original RGB values to calculate the averaged color. Compare the final results of your experiment for values based on RGB averages and Lab averages.
  • Be aware of the complexity of the color spaces, their transformations etc., especially if you have to apply e.g. background correction or other processing.

Hope that helps

1 Like