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