Colour Deconvolution
The colour deconvolution plugin (java and class files) implements stain
separation using Ruifrok and Johnston's method described
in [1].
The code is based on a NIH Image macro kindly provided by A.C. Ruifrok.
The plugin assumes images generated by color subtraction (i.e. light-absorbing dyes
such as those used in bright field histology or ink on printed paper). However, the dyes
should not be neutral grey (most histological stains are not so).
If you intend to work with this plugin, it is important to read the original paper
to understand how to determine new vectors and how the whole procedure works.
The plugin works correctly when the background is neutral (white to grey),
so background subtraction with colour correction
must be applied to the images before processing.
The plugin provides a number of "built in" stain vectors some of which were determined
experimentally in our lab (marked in the source
with GL), but you may have to determine your own vectors to
provide a more accurate stain separation, depending on the stains and methods you use. See note below.
The built-in vectors are :
- Haematoxylin and Eosin (H&E)
- Haematoxylin and DAB (H DAB)
- Fast Red, Fast Blue and DAB
- Methyl green and DAB
- Haematoxylin, Eosin and DAB (H&E DAB)
- Haematoxylin and AEC (H AEC)
- Azan-Mallory
- Alcian blue & Haematoxylin
- Haematoxylin and Periodic Acid of Schiff (PAS)
- RGB subtractive
- CMY subtractive
- User values entered by hand
- Values interactively determined from rectangular ROIs
Note: A very frequently asked question posted to the ImageJ list relates to quantification of immunostain intensity (for example DAB intensity) to evaluate antigen expression. However, please consider 2 main issues that prevent doing this in a quantitative manner:
- Antigen-antibody reactions are not stoichiometric, so "darkness of stain" does not mean "amount of reaction products". In fact most histological stains are not stoichiometric (an exception is Feulgen stain which is commonly used for DNA cytometry).
- In particular DAB does not follow Beer-Lambert law. See for example CM van der Loos paper:
"The brown DAB reaction product is not a true absorber of light,
but a scatterer of light, and has a very broad, featureless spectrum.
This means that DAB does not follow the Beer-Lambert law, which describes
the linear relationship between the concentration of a compound and
its absorbance, or optical density. As a consequence,darkly stained
DAB has a different spectral shape than lightly stained DAB."
Further details are mentioned in this informative message posted by Al Floyd to the ImageJ mailing list.
In consequence, while colour deconvolution might be useful in segmentation of immunostained structures or image enahancement for colour blind observers, attempting to quantify DAB intensity using the above plugin is not a good idea.
Ideally, new vector determination should be done on slides stained with only
one colour at a time (using the "From ROI" interactive option).
The plugin takes an RGB image and returns three 8-bit images. If the
specimen is stained with a 2 colour scheme (such as H&E) the 3rd image represents the
complementary of the first two colours (i.e. green). Ideally the 3rd image should
be completely white. If not, then either the colour vectors
or the background colour correction have not been correctly determined.
Read the paper!
New in version 1.2: Dennis Chao has kindly provided the following modifications to the code, 1) the plugin works with stacks, 2) the user-defined vectors can now also be recorded by the macro recorder, 3) the result images keep the original image name plus " (Colour[n])" in the name (note the leading space). Example: "test.tif" will produce images named "test.tif (Colour[1])", "test.tif (Colour[2])" and "test.tif (Colour[3])".
New in version 1.3: disable popup menu when using ROIs.
Examples
Haematoxylin and Eosin separation (using the built-in vectors).
From left to right: original, Haematoxylin, Eosin, virtually empty 3rd (complementary) component (showing that the vectors match the image quite well).
Haematoxylin and DAB separation (using the built-in vectors).
From left to right: original, Haematoxylin, DAB, 3rd component (the vectors did not perfectly matched the stains in this image, so they should be determined again from single-stained samples).
Ink/pigment separation (using ROI defined vectors).
This example shows stain separation in an old manuscript using regions of interest defined by the user (where stains were applied uniquely).
The top part of the image was pasted from the same manuscript page to allow sampling the ink alone within the same image. (Image of MS408, folio 2 recto courtesy of the Beinecke Rare Book and Manuscript Library, Yale University).

Top row: original, green pigment.
Bottom row: brown ink, 3rd component.
Vector values for this example:
Colour[1] (green pigment):
R1: 0.592132
G1: 0.4580393
B1: 0.6630081
Colour[2] (brown ink):
R2: 0.39982012
G2: 0.55231196
B2: 0.7315021
Colour[3] (3rd component):
R3: 0.69965965
G3: 0.6965282
B3: 0.15913807
Ink/pigment separation (using ROI defined vectors and image ratios).
Sometimes, the pigments are not easily separated. In such case the pigment that
is best separated can be filtered out using image ratio (a division of the original rgb planes by the pigment rgb planes followed by a multiplication of each plane by 255)
The example below uses ratio of the original image to the blue pigment image.
(Image of MS408, folio 9 verso courtesy of the Beinecke Rare Book and Manuscript Library, Yale University).
Left: original, right: ratio of the original and the blue pigment image.
Here is an ImageJ macro to perform this task (requires Colour_decovolution plugin and assumes that the 1st. colour in the deconvolved images is the one to filter out ).
Determining new vectors
Grab images with single stains (e.g. if one wants to determine the vectors of H and DAB, grab one image with only DAB and one stained only with Haematoxylin) and correct the background so it appears white or bright neutral grey. See this document for step by step instructions on background correction. If no background correction is applied, the colours in the image will depend on the colour/temperature of the light source.
Stitch or paste these 2 or 3 images together into a test image (so singly-stained areas exist in the same image)
Run the Colour Deconvolution plugin and select the From ROI option to let you define the stained areas and check the Show matrices box to display the vectors in the log window so they can be copied and pasted to the plugin source code later. Press OK.
Now the plugin will ask you to make selections. Select small ROIs areas which are all intensely stained with only one of the dyes. Select fully stained areas (i.e. without empty background). Repeat this for each dye.
If you are using 2 colours instead of 3, for the 3rd selection just right-click and the vector will be defined automatically as the complementary of the other 2 colours.
After this, the deconvolution of the test image will take place so you can evaluate the stain separation and a log window will show you something like this (the values will be different, of course):
------------------------------------------------------------
From ROI Vector Matrix ---
Colour[1]:
R1: 59.86929
G1: 65.04342
B1: 27.730581
Colour[2]:
R2: 23.209948
G2: 47.378456
B2: 51.81141
Colour[3]:
R3: 0.0
G3: 0.0
B3: 0.0
From ROI Translation Matrix ---
Colour[1]:
R1: 0.6461899
G1: 0.7020361
B1: 0.29930574
Colour[2]:
R2: 0.3138818
G2: 0.64072686
B2: 0.70067626
Colour[3]:
R3: 0.6956413
G3: 0.31082857
B3: 0.6476641
--------------------------------------------------------------------
These are the vectors for the dyes selected but bear in mind that one may have to repeat the procedure a few times to make sure the separation is optimal.
Now look for the 3 sets of vectors under the title:
"From ROI Translation Matrix ---"
and copy the values to the plugin java source code, where it says (for example if this is H DAB):
if (myStain.equals("H DAB")){
// 3,3-diamino-benzidine tetrahydrochloride
// Haem matrix
MODx[0]= 0.650;
MODy[0]= 0.704;
MODz[0]= 0.286;
// DAB matrix
MODx[1]= 0.268;
MODy[1]= 0.570;
MODz[1]= 0.776;
// Zero matrix
MODx[2]= 0.0;
MODy[2]= 0.0;
MODz[2]= 0.0;
}
That means that the 3 values in the log window:
R1: 0.6461899
G1: 0.7020361
B1: 0.29930574
need to replace the values already in the plugin, so:
MODx[0]= 0.650;
MODy[0]= 0.704;
MODz[0]= 0.286;
becomes:
MODx[0]= 0.6461899;
MODy[0]= 0.7020361;
MODz[0]= 0.29930574;
and so on for the other two colours.
If the 3rd colour was not defined (i.e. staining method consists of only 2 dyes), just insert the values as 0.0 and they will be recalculated by the plugin at run time.
Recompile the plugin from the menu entry Plugins>Compile and Run...
Restart IJ so the new class becomes active.
References
[1] Ruifrok AC, Johnston DA. Quantification of histochemical staining by color deconvolution. Anal Quant Cytol Histol 23: 291-299, 2001.
[2] A free plugin for Photoshop-compatible hosts to do colour separation is available from www.4n6site.com
[3] Tom Macura has ported the code of this plugin to MATLAB MEX c code, and it is available at the Open Microscopy Environment Repository.
Copyright G. Landini, 2004-2009 (except where indicated).
Last updated on 19/July/2009.
Back