Initial Color Calibration Results

Thanks to Peter Haub’s comment on my previous post, I’ve begun to get color calibration of our RGB images working. As he suggested, I’ve been using ArgyllCMS, which does most of what I need using a command line interface. I acquire my images using illumination with red, green, and blue LEDs, using a monochrome camera. These are then flat-fielded using images acquired with no slide; this is done without normalizing the images so as to white balance at the same time (details in this previous post). As an aside, I’m not totally happy with this correction procedure and I hope to improve it soon.

As our camera is 16-bit, the first task is to convert our Micro-manager image stacks into 16-bit per channel RGB TIFFs (also known as 48-bit TIFFs) so that ArgyllCMS can read them. It turns out that ImageJ will save 48-bit RGB tiffs, but only if the first channel is named “Red”. This ImageJ macro will fix the naming (thanks to Wayne Rasband for telling me how to do this):

labels = newArray("Red", "Green", "Blue");
for (i=0; i<3; i++) {
   setMetadata("label", labels[i]);
saveAs("tif", "");

The first step in color calibrating an image is extracting the pixel values from the calibration slide I showed previously and comparing them to the expected values of the slide in a reference color space (CIEXYZ or CIELAB). These values are provided by the manufacturer of the slide. In ArgyllCMS, this is done with the scanin command:

scanin -v -dipn CalibrationSlide.tif C:\Argyll_V1.6.3\ref\It8.cht ..\N140131.txt

It8.cht is the file that defines the chart layout, and N140131.txt is the file documenting the XYZ values of the chart provided by the manufacturer.

This produces CalibrationSlide.ti3, which is just a text file listing all of the color patches in the chart with their XYZ values (from the manufacturer) and the RGB values (measured from our image). The RGB values are expressed in percent of full scale. Next, we need to turn these values into an ICC device profile to transform our measured data (from the .ti3 file) into one of the reference (or device independent) color spaces. The ArgyllCMS command colprof does this:

colprof -v -D"HSS" -qm -am CalibrationSlide

This produces an ICC profile in the file CalibrationSlide.icm. The -D flag lets you provide a name for your profile, and the -am flag tells it to calculate a single matrix that transforms from RGB to the reference color space. There are many ways of doing this transformation, but the single matrix is in some sense the most conservative, and is appropriate if your camera has a linear response, which it probably does. For my system, this results in the matrix:

 0.589552 0.502653 0.138266
 0.282719 1.007607 0.031246
-0.005334 -0.068406 1.045615

I believe that this matrix transforms RGB to XYZ, i.e. XYZ = matrix * RGB, but I haven’t confirmed this.

With this ICC profile in hand you are essentially done. You can load this profile into a program that knows about color management (like Photoshop) and then assign this profile to your microscope images when you load them, and Photoshop will handle the rest. You can then save your images into a standard color space (like sRGB), and in principle, other people will know how to interpret the RGB values. If you want to simplify your workflow and avoid going through Photoshop, you can link the device profile created above to a profile defining a standard color space (e.g. sRGB) and convert from the device color space to sRGB in a single step. The command collink does this:

collink CalibrationSlide.icm c:\Argyll_V1.6.3\ref\sRGB.icm HSS2sRGB.icm

I can then use the command cctiff to convert a TIFF measured on our microscope to the sRGB color space in a single step:

cctiff -ip HSS2sRGB.icm HE9.tif HE9sRGB.tif

Finally, here are some results. These are single images of various H&E stained tissues from Carolina Biological Supply. The top row (if your browser window is wide enough) is the raw images from the microscope; the bottom row is the same images converted to the sRGB color space; you can click on the images to see the full resolution 4 megapixel images.


The single biggest difference you can see is that the sRGB images are much brighter. I believe that’s because of the gamma correction of roughly 2.2 that sRGB provides. I’m still not sure if this is a good thing, if we should be working in a linear color space, or if I’ve done something wrong in this process. The colors are definitely brighter and better looking in the corrected images, but they look washed out to me. Applying a gamma correction of about 2 makes these images look better, but I don’t think I should have to do that.  Expect more posts as I learn more about how to do this correctly.

5 thoughts on “Initial Color Calibration Results

    • How do you know it’s not a transformation from RGB to XYZ? I too am unclear about how to deal with the reference white.

      Unfortunately I’m busy with other things now, and there doesn’t seem to be much interest in RGB LED imaging and color calibration, so I don’t know when I will return to working on this.

      • 1) colprof creates ICC profiles for transforming RGB to RGB’ and not RGB to XYZ. Used with the -am option you get a simplified ICC profile in form of a matrix. Your profile mentioned above is your final correction profile.
        2) The RGB->XYZ matrix is well defined and can be found either in the argyll source code or on the web page I have mentioned, see table row
        sRGB D65 RGB->XYZ:
        0.4124564 0.3575761 0.1804375
        0.2126729 0.7151522 0.0721750
        0.0193339 0.1191920 0.9503041
        (! Do not miss the note that the RGB values have to be linear)
        A nice and helpful introduction can be found in [1] : Burger W. and Burge M., Digital Image Processing – An Algorithmic Introduction using Java
        3) Colorimetric color spaces are defined always in relation to a white point (such as standard illuminants D50 or D65). In case of transformations between color spaces with different reference white points a chromatic adaptation has to be performed.
        Since your LED illumination has most probably not a standard white point you have to measure the LEDs white point and adapt it to the necessary standard illumination (see 12.3.5 Chromatic Adaptation in [1])
        Hope this helps

  1. Sorry, I have to correct my statement 1):
    I fact, your matrix is a transformation from an RGB space into the XYZ space. It includes the color correction and therefore it is not equal to the standard (default) RGB->XYZ matrix.
    I have tested this be multiplying an color image with your matrix and a transforming it back to RGB with the XYZ->RGB matrix. In this way the color correction can be visualized and applied to images without changing the gamma value.
    The back transformation works nicely by multiplication with the inverted version of your matrix plus XYZ->RGB transformation.
    Sorry for the confusion – peter

    • Hi Peter –
      Thanks for the clarification. That makes a lot of sense, and in fact, maybe all I want to do is apply the color correction. I really need to think more about this….

Comments are closed.