[Insight-users] Application walk through

Luis Ibanez luis.ibanez@kitware.com
Wed, 08 Jan 2003 02:45:25 -0500


Hi Neil


Please see comments interlaced below.


------------------------------------------------
Neil Killeen wrote:

> 
> 
> 1) I have created the Image typedef
> 
>   typedef itk::Image<float, 2>                  ImageType;
> 
>   I had to specify the dimensionality of the image (2) at this point.
> 
>   Is this really necessary ? In my opinion, it is very inflexible to have to
>   specify it here.  A generic display tool for example should be able
>   to read and display an image of arbitrary dimensionality.
> 




Totally agree with you,
A general display tool should deal with arbitrary dimensionality.
However, Visualization is out of the scope of ITK.

The objective of the Insight toolkit is to perform Medical
Image Registration and Segmentation. Defining the dimension
as a template parameter results in code that runs faster.

For visualization purposes you may want to use VTK.


> 
> 2) I have used the class itk::ImageFileReader to read the image,.
> 
>   This class appears to have the smarts to handle various different
>   file formats.  It can handle at least dicom and meta images - great.
> 
>   However, I would *never* have found this class if it wasn't used
>   in the example code.    The (module) 'Groups' class listing
>   is the one that I find the most useful.  However, this class does
>   not appear to exist in that structure.  If I was to expect to find it anywhere,
>   it would be under
> 
>    Groups
>      Data Processing Objects
>        Input and Output Filters
> 



Thanks for pointing this out.
The ImageFileReader has been now classified on this group.


>
> 
> 
>       - there is no ImageFileReader.  I see RawImageIO there, I would have expected a similar
>         class for all of the supported file formats, e.g. MetaImageIO etc.   Where is ImageFileReader
>         to be found ?
>



Thanks again,
the ImageIO classes have also been added now to the IOFilters
group in oxygen


 
>       - I see the class VTKImageExport  (and *Import) which says it is for use at the end of the ITK
>         pipeline chain to allow you to convert to VTK format.   Question, what is the
>         relationship of this class to class   ImageToVTKImageFilter  which does exactly
>        that too (used in application below and subject of our discussion last week) ?
> 





They are closely related.
The ImageToVTKImageFilter has a VTKImageExport inside   :-)
The filter is just a convinience class that connect all the
elements of the VTK and ITK pipelines.
The final purpose is to be able to seamlessly connect an image
from an ITK pipeline as input to a VTK pipeline. and viceversa.





>       - The only place I could find ImageFileReader was in the alphabetical list.
> 
>         The class documentation gives no clue as to what file format types are supported.
> 




That's exactly how it should be
The Image File Reader is intended to be a transparent
interface for IO totally independent of file format.
The list of file formats supported is defined by the
set of ImageIO objects in the directory

     Insight/Code/IO



>         This class is templated according to
> 
>         template <class TOutputImage, class ConvertPixelTraits=DefaultConvertPixelTraits<ITK_TYPENAME TOutputImage::PixelType> >
> 
> 
>        where the TOutputImage is the *output* Image type of the filter.  The ConvertPixelTraits
>        is used to convert between the file pixel type and this output type.
> 
>        I couldn't find any class ConvertPixelTraits in the alphabetical list although
>        DefaulConvertPixelTraits is there.  As far as I can tell this is nothing to do
>        with file formats (e.g. meta/dicom etc) but purely pixel type (float, int etc).
> 





This is one of the classes that are mostly intended to
provide internal support in the toolkit. It is not really
one of the first classes you may want to play with.




>        I assume that DefaultConvertPixelTraits<ITK_TYPENAME TOutputImage::PixelType> >
>        works out to be the same pixel type as TOutputImage, which in my case was Float ?
> 
> 
> 
> 3) The DiscreteGaussianImageFilter class does separable Gaussian convolution.
> It's interface should be simple and clear.  However, virtally every method
> doc. says  'Standard Get/Set' macros for filter parameters.
> 
> I find that pretty frustrating, especially as nowhere can I find the
> documentation for these 'Standard Get/Set' methods  !    I think that
> anything that says this should include a link to their location.
> 
> As a general statement about the class documentation, I am finding it
> relatively poor.
> 




Please refer to the software guide. This document is under:

       InsightDocuments/Web/HTML/SoftwareGuide.pdf

The chapter on Smoothing describes the gaussian filters in detail



 >

>
> The module, class and class member descriptions are often so poor as to
> be useless.  IMO, the module docs.  are the most important as they give
> you some high-level context about what does what and where it is.
> 




Yeap,
some reorganization and clean up maybe needed
in the classification of doxygen groups.
Sounds like spring-clean-up task !



 >

>
> As another trivial example, ImageFileReader::GenerateData describes its
> functionality as 'Does the real work' which is singularly unhelpful !
> 

 >



Well, you may have to accept that some comments
on the documentation fall in the range of excerting
the programmer's right of "free speech".

In particular when they are working late at night.  :-)

Now that....
It is actually very true that the "GenerateData()"
method of all the filters is where the real work is done.

I hope you will not look too close to some of the comments
we write on CVS   :-)



>
> Also the heavy typedef-ing and templating makes it very hard to figure
> out just what the arguments in the interface are.  I seem to spend a lot
> of time going back to the Alphabetical class list becaus the DOxygen
> docs.  don't hyperlink me anywhere useful a lot of the time (because of
> typedefs I think).
> 

 >


Welcome to Generic Programming !

With enough coffee you will get use to it and probably
will end up liking the way the code looks.

Actually I have to confess that now I find difficult
to read code that doesn't have typedefs nor templates.


 >

>
> Clearly, your goal with a toolkit is to reuse code.  This means
> the documentation *must* be good enough to allow this easily.
> 
> It's always a problem to get people to write good documentation...
> 




That's certainly the case.

As we speak, we are working hard in getting the SoftwareGuide ready.
The document will be in the order of 200 pages, on 48 hours from now.
We expect it to continue growing upto about 400. This document
describes the main features of the toolkit.



> 
> 
> 4) The basic approach is that of a pipeline, and I like the clarity that
> this has, with common methods always being available for the pipeline
> (e.g. SetInput, GetOutput)
> 
>      smoother->SetInput(reader->GetOutput());
>      converter->SetInput(smoother->GetOutput());
>      viewer->SetInput(converter->GetOutput());
> 



You got this right,


> The GetOutput functions return pointers to the basic class Image of the
> appropriate type that you are dealing with.  However, these do not appear
> to be Smart pointers, but raw pointers.
> 
> E.g.
> 
> template<class TOutputImage>  OutputImageType* itk::ImageSource< TOutputImage >::GetOutput (void)
> 



Well, this is a long story.

but here are the main episodes:

1) SmartPointers update a reference count in the
    object they are pointing to
2) We want ITK to be thread safe
3) Several SmartPointers in different thread may
    try to update the reference count
4) To prevent catastrophic events Mutual exclusion
    should be used when updating the reference count
5) Mutex lock are slow.... very slow ... very slow
6) We want the toolkit to be fast

Ergo sum:

SmartPointer should only be passed around when they
are really necessary and in the case of SetInput()
GetOutput() they are not really necessary since
there are few reasons to expect that you plan to
destroy a filter that you just plug into another.
So, passing raw pointers is the best approach when
returning images that are own by the object in
question.


 >

>
> So I am a bit confused about whose responsibility it is to manage these
> pointers.  In the example code nothing deletes them.  Who owns these
> pointers - are they all clones of the same image ? I.e.  it being a
> pipeline, all I need is one Image which is continually updated.
> 




Ouput image are owned by the filter.
The filter holds a container of SmartPointes to
the output images it is responsible for.
The SmartPointer + reference counting mechanism
take care of destroying the images when appropriate.

You don't have to call "Delete()" in any object
managed by SmartPointers.




>
> I am assuming that what happens is that the data is read into an Image
> class object (by ImageFileReader) which exists purely in memory (perhaps
> you can get away with this because Medical imaging images are not very
> big).  This object is updated by each filter and responsibility for it
> is transferred somehow to each successive filter.  Does it get deleted
> at the end when the last filter is destroyed ? Perhaps you could clarify
> this for me ?
> 
> 



Image are not actually passed from one filter to another.

in

A  --->  B ---- > C

the output image of filter A stays with A.
B "read" this image and use the data to compute
the values it puts in its own output image.
B's output image is an entity completly independent
of A's output image.  Then C reads B's output image
and use the data to compute the values of C's
outtput image.


> 
> 
> 5) I don't know much about VTK yet, so perhaps I will allow myself just
> one question. IN getting the example code running I had to use the class
> vtkImageViewer2 rather than the given  vtkImageViewer.  I don't know what
> the difference is.
> 

 >

> The example code did
> 
>   vtkImageViewer2* viewer = vtkImageViewer2::New();
> 
> which is just a raw pointer.  Nothing deletes it.  However if I try to
> delete them the compiler complains.  Should they be deleted (somehow)
> or not ?
> 
> 



Could you please post the error message
produced by the compiler ?

normaly you should invoke "Delete()" on VTK object.



> 
> 
> 
> that's all for now
> 
> many thanks (again)
> Neil
> 
> 
> 
> 
> 
>