Fwd: [Insight-users] NiftiImageIO intensity rescaling bug

Tom Vercauteren tom.vercauteren at gmail.com
Thu Mar 8 06:34:40 EST 2007


Forward without attachments

---------- Forwarded message ----------
From: Tom Vercauteren <tom.vercauteren at m4x.org>
Date: Mar 8, 2007 12:31 PM
Subject: Re: [Insight-users] NiftiImageIO intensity rescaling bug
To: "Hans J. Johnson" <hans-johnson at uiowa.edu>
Cc: insight-users <insight-users at itk.org>, Luis Ibanez <luis.ibanez at kitware.com>


Hi Hans,

After some more thought, I think that my previous solution needed more
work. I found that I needed to modify both the NiftiImageIO and the
ConvertPixelBuffer classes.

This seems a little involved by I didn't find any better solution.
Please tell  me I am fooling myself.


1) What I did to modify NiftiImageIO
==========================
Here is what I understand it from the NIFTI documentation:
http://nifti.nimh.nih.gov/nifti-1/documentation/nifti1fields/nifti1fields_pages/scl_slopeinter.html

We need to rescale the data if scl_slope!=0 or (scl_slope!=1 and
scl_inter!=0). If we need to rescale the data, then the pixel type
should be promoted to a floating point data type. It should be "float"
if the written pixel type is not a floating point data type. Otherwise
it can be left unchanged.

In case we need to rescale, we should thus:
- determine the pixel type based on the written pixel type
- read the data into a written pixel type buffer
- rescale the written pixel to the final pixel type buffer

I have attached my modified NIFTIImageIO class. It is not completely
finished yet as I always use floats if a rescaling is needed but it
gives an idea of how this can be done. I hope this helps.


1) What I did to modify ConvertPixelBuffer
==============================
But If I only do that I am still stuck with the roundoff error problem
I mentioned. The ImageIO class now provides floating point data. If I
ask the ImageFileReader to read a integer image, it is up to the
ConvertGrayToGray function in itkConvertPixelBuffer.txx to do the
conversion job. Here is the problem:
- it uses a static_cast to convert the pixel type provided by the
ImageIO to the pixel type asked by the ImageFileReader
- If the ImageIO pixel type is a floating point type and the
ImageFileReader pixel type is an integer type, then this leads to
round-off errors. These errors can be really problematic when one
reads segmentation images for example
- the solution I found was to use a rounding operation before the
cast. See below for the ConvertGrayToGray function I use.
template < typename InputPixelType,
           typename OutputPixelType,
           class OutputConvertTraits
           >
void
ConvertPixelBuffer<InputPixelType, OutputPixelType, OutputConvertTraits>
::ConvertGrayToGray(InputPixelType* inputData,
                    OutputPixelType* outputData , int size)
{
   InputPixelType* endInput = inputData + size;

  if ( NumericTraits<OutputComponentType>::is_integer )
  {
     while(inputData != endInput)
     {
        OutputConvertTraits
           ::SetNthComponent(0, *outputData++,
                             static_cast<OutputComponentType>
                             (vnl_math_rnd(static_cast<double>(*inputData))));
        inputData++;
     }
  }
  else
  {
     while(inputData != endInput)
     {
        OutputConvertTraits
           ::SetNthComponent(0, *outputData++,
                             static_cast<OutputComponentType>
                             (*inputData));
        inputData++;
     }
  }
}


Best,
Tom


More information about the Insight-users mailing list