[Insight-users] itkVTKtoITKtoVTK modification
Luis Ibanez
luis.ibanez@kitware.com
Thu, 02 May 2002 20:39:12 -0400
Hi Mathieu,
I just reproduced the error that you reported.
Here is what is happening :
1) ITK uses exceptions for managing error conditions.
Your modifications are conceptually fine but they are
generating a pixel type conflict between VTK and ITK,
this results in an exception being thrown.
Iin general you may want to put ITK code inside
try/catch blocks. Specially the code that updates filters.
Typically this will look like:
try
{
myFilter->Update()
}
catch( itk::ExceptionObject & e )
{
std::cerr << "Exception catched " << e << std::endl;
}
(Note that the exception is catched by reference)
2) After adding this try/catch block,
here is the message that you can see for the thrown exception:
Exception catched !!
itk::ExceptionObject (0x84e60c0)
Location: "Unknown"
File: /home/ibanez/test/Insight/Code/BasicFilters/itkVTKImageImport.txx
Line: 203
Description: itk::ERROR: VTKImageImport(0x84d1368):
Input scalar type is unsigned short but should be float
The last line specifies that there is a conflict of types at
the input of the VTKImageImport...
VTK is templated over types internally while ITK templates are
exposed to the user. VTK makes decisions on types at run time
by using internal switch statements on the filters. ITK asks the
user to make those decisions at compile time.
When you replaced the Noise source image by a PNGReader you
implicitly replaced the type of the input image. PNG images are
typically (not always...) read as "unsigned short". Because VTK
made this decision at run time, your compilation passed Ok.
When you execute the pipeline, VTK reads the file and place the
data in an "unsigned short" image. Then it tries to pass it to the
Exporter but the exporter is templated over type and is already
expecting a "float" image. Not knowing what to do, it throws an
exception with the hope that the user will catch it in a try/catch
block and solve the problem somehow.
The solution is to change the type of the image pixel on line 127:
typedef itk::Image<float, 2> ImageType;
typedef itk::VTKImageImport<ImageType> ImageImportType;
replacing "float" by "unsigned short" will prevent the exception
from happening.
but....
at compile time you will find that the itk::CurvatureFlowImageFilter
actually expect the input image to be of pixel type float or double.
This fact will produce a large number of warnings related to
assignemes from 'double' to 'unsigned short'. They look like:
itkCurvatureFlowFunction.txx:101: warning: assignment
to `short unsigned int' from `double'
So now you will have to introduce a CastImageFilter in between
the vtkImageLuminance filter and the VTKImageImport filter.
This Cast filter should convert the input image from "unsigned
short" pixels to "float" pixels.
Note that Cast is pretty naive in the sense that no effort is made
to adjust the intensity range of the images. It will just do a
pixel-wise cast on the image. If you want to adjust the intensity
range the itkShiftScaleImageFilter could do that for you.
Once you introduce this Cast filter the pipeline should
execute ok.
A modified version of itkVTKtoITKtoVTK.cxx has been
checked in. If you update your cvs checkout you will find
itkPNGVTKtoITKtoVTK.cxx
Which is based on the code that you posted to the list.
You will also see a modified CMakeList.txt (that defines an
executable for this example)
This executable is requiring two PNG files right now, so you
will have to change the filenames in lines : 121 and 223 in
order to set any of your PNG files.
=============
A Comment on Casting:
The use of CastFilters is a trade-off between speed and memory.
When you use a CastFilter you are paying for an extra copy of
the image on memory but the process should be quite fast.
If memory is a concern, you may use ImageAdaptors instead.
http://www.itk.org/Doxygen/html/classitk_1_1ImageAdaptor.html
ImageAdaptors allow to make an image of type TA look like
an image of type TB.
This is done by an internal conversion on the iterators that access
the pixels on the image. So each time that you read a pixel, the
iterator will do the cast for you. Using ImageAdaptors allow to
avoid the extra memory consumption of the copied image but
will be slower at computing time.
ImageAdaptors can also be used to compute pixel-wise functions
on images, see for example:
http://www.itk.org/Doxygen/html/classitk_1_1SinImageAdaptor.html
Now...
most ITK filters are templated over the input image type and the
output image type. So, most of them will do casting for you.
Whether this Casting is exactly what you wanted to do or not....
well, this is another question :-)
Please let us know if you encounter any other problem
with this code
Thanks
Luis