[Insight-developers] Improving support for color in ITK
Dan Mueller
dan.muel at gmail.com
Sun Jul 26 11:26:12 EDT 2009
Hi ITK developers,
There are segmentation tasks which require different image color
spaces. As I need to perform (supervised statistical) classification
on color images (digitized pathology images), I intend to improve
support for non-RGB color spaces in ITK. My ultimate goal is a
submission to the Insight Journal consisting of various
classes/filters for converting to/from various color spaces. However,
before I go too far, I would appreciate some thoughts/suggestions from
more experienced ITK developers.
I started my task by taking an inventory of current color
functionality within ITK:
RGBPixel
NumericTraitsRGBPixel
* Basic data container for (linear) RGB pixels
RedPixelAccessor
GreenPixelAccessor
BluePixelAccessor
NthElementImageAdaptor
VectorIndexSelectionCastImageFilter
* Provide access to individual (RGB) color components
RGBToVectorImageAdaptor
RGBToVectorPixelAccessor
* Provide access to RGB pixel as vector pixel
ConvertPixelBuffer
RGBToLuminanceImageFilter
* Provide conversions from (linear) RGB to luminance
Obviously there is a lack of support for other common color spaces
such as HSV, XYZ, Lab.
I also looked at VTK, which contains the following functions for color
space conversion (see Common/vtkMath.h):
RGBToHSV
HSVToRGB
LabToXYZ
XYZToLab
XYZToRGB
RGBToXYZ
RGBToLab
LabToRGB
I noticed vtkMath::RGBToXYZ(..) and vtkMath::XYZToRGB(..) have some
code regarding conversion from linear RGB to non-linear R'G'B' (ie.
sRGB). However this code is commented out, citing incompatible with
OpenGL.
I then read Charles Poynton's Color and Gamma FAQs which are
referenced in IO/itkConvertPixelBuffer.h:
http://www.poynton.com/PDFs/ColorFAQ.pdf
http://www.poynton.com/PDFs/GammaFAQ.pdf
<aside>The URLs in itkConvertPixelBuffer.h are outdated and broken.</aside>
I am still processing these documents, but the author seems to suggest
HSB (hue, saturation, brightness) and HLS (hue, lightness, saturation)
"are useless for conveyance of accurate color information" because the
"formulations are based on RGB components whose chromaticities and
white point are unspecified".
All this has left me somewhat confused. So I guess my big question is:
should I stay with the "simple" approach taken by VTK, which --
although not the whole truth -- seems adequate? Or should I aim for a
more "complete" solution, with support for non-linear color spaces
(eg. sRGB), white point specification, etc?
Brad: From a recent post to the users list, you seem knowledgeable on
this topic. Perhaps you have some advice?
http://www.itk.org/pipermail/insight-users/2009-July/031394.html
Without further advice I will implement the VTK color conversions in a
base filter which accepts VectorImage types. That is, rather than
create a new pixel container for each of the color spaces, the three
channels can simply reside in a vector. For example:
typedef unsigned char BasePixelType;
typedef itk::RGBPixel< BasePixelType > RgbPixelType;
typedef itk::Image< RgbPixelType, 2 > RgbImageType;
typedef itk::ImageFileReader< RgbImageType> RgbReaderType;
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName( "D:/Temp/color1.png" );
typedef itk::RGBToVectorImageAdaptor< BasePixelType > AdapterType;
AdapterType::Pointer imageRgb = AdapterType::New();
imageRgb->SetImage( reader->GetOutput() );
typedef itk::VectorImage< BasePixelType, 2 > VectorImageType;
typedef itk::ConvertColorSpaceImageFilter< BasePixelType, 2 > ConvertFilterType;
ConvertFilterType::Pointer converter = ConvertFilterType::New();
converter->SetInput( imageRgb );
converter->SetInputColorSpace( ColorSpace::RGB );
converter->SetOutputColorSpace( ColorSpace::CIELAB );
converter->Update( );
VectorImageType::Pointer imageCielab = converter->GetOutput( );
VectorImageType::IndexType index;
index.Fill( 10 );
BasePixelType lightness = imageCielab->GetPixel( index ).GetElement( 0 );
The advantage of using vectors to hold the color images is that no new
pixel types (or traits) need to be added/maintained. The disadvantage
is that the user now needs to be careful which color components are
currently held by the vector. For example pixel.GetElement( 0 ) may
return R(GB), L*(a*b*), X(YZ), or H(SV). Do you feel this is too
confusing?
Sorry for the long email. Thanks for any advice.
Regards, Dan
More information about the Insight-developers
mailing list