NA-MIC National Alliance for Medical Image Computing ITK Workshop October 5-8, 2005 Software...
-
Upload
sarah-barrett -
Category
Documents
-
view
220 -
download
0
Transcript of NA-MIC National Alliance for Medical Image Computing ITK Workshop October 5-8, 2005 Software...
NA-MICNational Alliance for Medical Image Computing http://na-mic.org
ITK Workshop
October 5-8, 2005
Software Design
National Alliance for Medical Image Computing http://na-mic.org
ITK Workshop – Open Source Viewers
• Design Patterns– Pipeline– Decorators– Iterators– Adaptors– Accessors– Functors– Factories– Traits
National Alliance for Medical Image Computing http://na-mic.org
The Data Pipeline
Insight Toolkit - Advanced Course
National Alliance for Medical Image Computing http://na-mic.org
The Data Pipeline
DataObject
ProcessObject
DataObject
ProcessObject
DataObject
National Alliance for Medical Image Computing http://na-mic.org
Who owns the Output ?
DataObject
DataObject
DataObject
ProcessObject
ProcessObject
The ProcessObject allocates and owns its output
Therefore the output is const
National Alliance for Medical Image Computing http://na-mic.org
• Instantiate the filters types
• Construct the filters with New()
• Connect SetInput() GetOutput()
• Set filter Parameters
• Invoke Update() in the last filter
How to use the Pipeline ?
National Alliance for Medical Image Computing http://na-mic.org
• Modify the filter parameters
• Invoke Update() in the last filter
The Pipeline is intended to be Re-Executed
Only the filters that need to re-compute their output will be re-executed
National Alliance for Medical Image Computing http://na-mic.org
Updating the Pipeline
ImageReader
FilterA
FilterB
FilterC
FilterD
ImageWriter
National Alliance for Medical Image Computing http://na-mic.org
Updating the Pipeline
ImageReader
FilterA
FilterB
FilterC
FilterD
ImageWriter
Execute
Execute Execute
Execute
Update()
National Alliance for Medical Image Computing http://na-mic.org
Updating the Pipeline
ImageReader
FilterA
FilterB
FilterC
FilterD
ImageWriter
ExecuteExecute Execute Execute
Update()
National Alliance for Medical Image Computing http://na-mic.org
Updating the Pipeline
ImageReader
FilterA
FilterB
FilterC
FilterD
ImageWriter
Execute Execute
Update()SetParameter
I’m OK I’m OK
National Alliance for Medical Image Computing http://na-mic.org
• itk::Object has a TimeStamp
• Invoking Modified() updates the stamp
• SetParameter() methods calls Modified()
• Most Set() methods use itkSetMacro()
• If you write your own SetParameter() you must remember to invoke Modified()
How it works internally
National Alliance for Medical Image Computing http://na-mic.org
What will go wrong with your filter if you create a SetParameter() method and forget to invoke Modified() from it ?
How it works internally
Quiz !
It will run fine the first time but if you call SetParameter() and then call Update() the filter will not re-execute.
National Alliance for Medical Image Computing http://na-mic.org
Open the itkMacro.h file in
Insight/Code/Common
How it works internally
Exercise
Find the itkSetMacro() and identify the line where Modified() is invoked
National Alliance for Medical Image Computing http://na-mic.org
Pervasive Pipelining
Insight Toolkit - Advanced Course
(or the Ode to Intelligent Design)
National Alliance for Medical Image Computing http://na-mic.org
In the Beginning… there was the itk::DataObject
Insight Toolkit - Advanced Course
The itk::DataObject originated the itk::Image and the itk::Mesh
National Alliance for Medical Image Computing http://na-mic.org
Only the the itk::DataObject and his sons were admited in the Pipeline garden
Insight Toolkit - Advanced Course
The float, ints, Transforms and Pointsgrew jealous of the DataObject
Since they could not promenade in the Pipeline Garden
National Alliance for Medical Image Computing http://na-mic.org
So in chorus they asked to change the ways of the Pipeline garden
Insight Toolkit - Advanced Course
And from the darkness of the abyss the itk::DataObjectDecorator was born.
National Alliance for Medical Image Computing http://na-mic.org
Insight Toolkit - Advanced Course
With it,the float, ints, Transforms and Points became as DataObjects and walked at their will in the Pipeline Garden.
National Alliance for Medical Image Computing http://na-mic.org
#include “itkDataObject.h”
template<class T>class SimpleDataObjectDecorator : public DataObject{public: typedef SimpleDataObjectDecorator Self; typedef DataObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer;
itkNewMacro( Self );
itkTypeMacro( SimpleDataObjectDecorator, DataObject );
private: T m_Component;
The SimpleDataObjectDecorator
National Alliance for Medical Image Computing http://na-mic.org
public: virtual void Set( const T & value ) { if( m_Component != value ) { m_Component = value; this->Modified(); } }
virtual const T & Get() const { return m_Component }
The SimpleDataObjectDecorator
National Alliance for Medical Image Computing http://na-mic.org
#include “itkDataObject.h”
template<class T>class DataObjectDecorator : public DataObject{public: typedef DataObjectDecorator Self; typedef DataObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer;
itkNewMacro( Self );
itkTypeMacro(DataObjectDecorator, DataObject );
private: typename T::Pointer m_Component;
The DataObjectDecorator
National Alliance for Medical Image Computing http://na-mic.org
public: virtual void Set( const T * value ) { if( m_Component != value ) { m_Component = value; this->Modified(); } }
virtual const T * Get() const { return m_Component }
The DataObjectDecorator
National Alliance for Medical Image Computing http://na-mic.org
Iterators
Insight Toolkit - Advanced Course
National Alliance for Medical Image Computing http://na-mic.org
• STL Iterators
• Image Iterators– Region– Linear– Slice
• Mesh Iterators– VectorContainer– MapContainer
Iterators
National Alliance for Medical Image Computing http://na-mic.org
#include <vector>
typedef std::vector< float > VectorType;
VectorType myVector;
myVector.push_back( 4 );myVector.push_back( 7 );myVector.push_back( 19 );
VectorType::const_iterator itr = myVector.begin();
while( itr != myVector.end() ) { std::cout << *itr << std::endl; ++itr; }
STL Iterators
National Alliance for Medical Image Computing http://na-mic.org
for( unsigned int z = 0; z < Nz; z++ ) { for( unsigned int y = 0; y < Ny; y++ ) { for( unsigned int x = 0; x < Nx; x++ ) {
image[z][y][x] = … // pixel access
} }}
Image Iterators
The Evil nested loop and the Dimensional Trap
How to generalize this code to 2D, 3D, 4D …?
National Alliance for Medical Image Computing http://na-mic.org
#include “itkImage.h”#include “itkImageRegionIterator.h”
typedef itk::Image< float, 3 > ImageType;typedef itk::ImageRegionConstIterator< ImageType > IteratorType;
ImageType::ConstPointer image = GetConstImageSomeHow();
ImageType::RegionType region = image->GetLargestPossibleRegion();
IteratorType itr( image, region );itr.GoToBegin();
while( ! itr.IsAtEnd() ) { std::cout << itr.Get() << std::endl; ++itr; }
Image Iterators (const)
National Alliance for Medical Image Computing http://na-mic.org
#include “itkImage.h”#include “itkImageRegionIterator.h”
typedef itk::Image< float, 3 > ImageType;typedef itk::ImageRegionIterator< ImageType > IteratorType;
ImageType::Pointer image = GetNonConstImageSomeHow();
ImageType::RegionType region = image->GetLargestPossibleRegion();
IteratorType itr( image, region );itr.GoToBegin();
while( ! itr.IsAtEnd() ) { itr.Set( 0 ); ++itr; }
Image Iterators (non-const)
National Alliance for Medical Image Computing http://na-mic.org
#include “itkImage.h”#include “itkImageLinearIteratorWithIndex.h”
typedef itk::Image< float, 3 > ImageType;typedef itk::ImageLinearConstIteratorWithIndex< ImageType > IteratorType;
ImageType::ConstPointer image = GetConstImageSomeHow();ImageType::RegionType region = GetImageRegionSomeHow();IteratorType itr( image, region );
for( itr.GoToBegin(); !itr.IsAtEnd(); itr.NextLine() ) { while( ! itr.IsAtEndOfLine() ) { std::cout << itr.Get() << “:“ << itr.GetIndex() << std::endl; ++itr; } }
Image Linear Iterator (const)
National Alliance for Medical Image Computing http://na-mic.org
#include “itkImageSliceIteratorWithIndex.h”
typedef itk::ImageSliceConstIteratorWithIndex<ImageType> IteratorType;
ImageType::ConstPointer image = GetConstImageSomeHow();ImageType::RegionType region = GetImageRegionSomeHow();IteratorType itr( image, region );
for( itr.GoToBegin(); !itr.IsAtEnd(); itr.NextSlice() ) { for( ; ! itr.IsAtEndOfSlice(); itr.NextLine() ) { for( ; ! itr.IsAtEndOfLine(); ++itr ) { std::cout << itr.Get() << “:“ << itr.GetIndex() << std::endl; } } }
Image Slice Iterator (const)
National Alliance for Medical Image Computing http://na-mic.org
Using the ImageLinearIterator
Exercise 28
Use two ImageLinearIterators in order to flip and image across its diagonal
National Alliance for Medical Image Computing http://na-mic.org
• Reflective Image Iterator
• Neighborhood Iterator
• Shaped Neighborhood Iterator
• Image Random Iterator
• Image Random Non Repeating Iterator
• Flood Filled Function Conditional Iterator
• Path Iterator
Other Image Iterators
National Alliance for Medical Image Computing http://na-mic.org
• Iterators absorb a large portion of the complexity in an Image Filter
• Iterators made possible to generalize ITK to N-Dimensional images
• Iterators allows to have fast access to pixel data
• Iterators made ImageAdaptors possible (see later)
Importance of Image Iterators
National Alliance for Medical Image Computing http://na-mic.org
#include “itkMesh.h”
typedef itk::Mesh< float, 3 > MeshType;
MeshType::ConstPointer mesh = GetConstMeshSomeHow();
typedef MeshType::PointsContainer PointsContainer;typedef PointsContainer::ConstIterator PointsIterator;
PointsContainer points = mesh->GetPoints();PointsIterator pointItr = points->Begin();
while( pointItr != points->End() ) { MeshType::PointsType point = pointItr.Value(); std::cout << “point “ << point << std::endl; ++pointItr; }
Mesh Iterators (const)
National Alliance for Medical Image Computing http://na-mic.org
Image Adaptors
Insight Toolkit - Advanced Course
(Things are not always what they seem)
National Alliance for Medical Image Computing http://na-mic.org
Some operations are too simple for a filter
Image ImageProcessObject
Image Filter
ImageFake
ImageImage
Adaptor
Image Adaptor
National Alliance for Medical Image Computing http://na-mic.org
Pixel Accessor
ImageFake
ImageImage
Adaptor
Image Adaptors = Image Iterators + Pixel Accessors
Pixel Accessor Pixel Accessor
Where the transformation is done
National Alliance for Medical Image Computing http://na-mic.org
Pixel Accessor and Image Iterators
Image Image Iterator
National Alliance for Medical Image Computing http://na-mic.org
Pixel Accessor and Image Iterators
Image Image Iterator
itr.Get()
m_PixelAccessorFunctor.Get( *( m_Buffer + m_Offset ));
National Alliance for Medical Image Computing http://na-mic.org
namespace Accessor {
class RedChannel { public: typedef itk::RGBPixel<float> InternalType; typedef float ExternalType; static ExternalType Get()( const InternalType & A ) { return static_cast< ExternalType >( A.GetRed() ); } };
} // end of Accessor namespace
Pixel Accessor : Red Channel from RGB Image
National Alliance for Medical Image Computing http://na-mic.org
int main() {typedef Accessor::RedChannel::InternalType InternalPixelType;
typedef itk::Image< InternalPixelType, 2 > AdaptedImageType;
typedef itk::ImageAdaptor< AdaptedImageType, Accessor::RedChannel >ImageAdaptorType; ImageAdaptorType::Pointer adaptor = ImageAdaptorType::New();
typedef itk::ImageFilterReader< AdaptedImageType > ReaderType; ReaderType::Pointer reader = ReaderType::New();
adaptor->SetImage( reader->GetOutput() );
Using the Pixel Accessor in the Image Adaptor
National Alliance for Medical Image Computing http://na-mic.org
• Image Adaptors are like Images
• Image Adaptors are not Filters
• Image Adaptors do not have Buffers
• Not all Iterators support Image Adaptors
• Not all Filters support Image Adaptors
Image Adaptors
National Alliance for Medical Image Computing http://na-mic.org
typedef itk::Image< unsigned char, 2 > OutputImageType;
typedef itk::RescaleIntensityImageFilter< ImageAdaptorType, OutputImageType > FilterType; FilterType::Pointer filter = FilterType::New();
filter->SetInput( adaptor ); // Adaptors are like Images !!
writer->SetInput( filter->GetOutput() );
writer->Update(); }
Using the Pixel Accessor in the Image Adaptor
National Alliance for Medical Image Computing http://na-mic.org
Image Adaptors
Pierce the Illusion…
to see the Void.
National Alliance for Medical Image Computing http://na-mic.org
• Writers access Image’s buffer directly,They are not fooled by Image Adaptors.
• Neigborhood Iterators do not call theGet() method…They are not fooled by Image Adaptors.
Image Adaptors
National Alliance for Medical Image Computing http://na-mic.org
Image Adaptors
Exercise 27
Write a Pixel Accessor that will invert the intensities in an image.
Instantiate its corresponding Image Adaptor
National Alliance for Medical Image Computing http://na-mic.org
namespace Accessor {
class Inversor { public: typedef unsigned char InternalType; typedef unsigned char ExternalType; static ExternalType Get()( const InternalType & A ) { return static_cast< ExternalType >( 255 - A ); } };
} // end of Accessor namespace
Pixel Accessor : Invert 8-bits intensities.
National Alliance for Medical Image Computing http://na-mic.org
Functors
Insight Toolkit - Advanced Course
The Way takes no action, but leaves nothing undone
National Alliance for Medical Image Computing http://na-mic.org
namespace Functor {
template< class TInput, class TOutput> class Doubler { public: Doubler() {}; ~Doubler() {}; inline TOutput operator()( const TInput & A ) { return static_cast<TOutput>( 2.0 * A ); } };
} // end of Functor namespace
Functors
A Functor is a class that looks like a Function
National Alliance for Medical Image Computing http://na-mic.org
typedef Functor::Doubler< int, int > FunctorType;
FunctorType iDouble;
int input = 197.0;
int result = iDouble( input );
Functors
Functors are used as functions
National Alliance for Medical Image Computing http://na-mic.org
Functors are used by
Insight Toolkit - Advanced Course
• UnaryFuncturImageFilter<>• BinaryFunctorImageFilter<>• TernaryFunctorImageFilter<>
Functors make possible to factorize all other operations of an image filter
National Alliance for Medical Image Computing http://na-mic.org
Factories
Insight Toolkit - Advanced Course
The origin of the world is its mother;Understand the mother, and you understand the child
Tao Te Ching
National Alliance for Medical Image Computing http://na-mic.org
The Class Hierarchy of Factories
itk::ObjectFactoryBaseitk::DataObject
itk::Object
itk::ObjectFactory
itk::LightObject
itk::ProcessObject
National Alliance for Medical Image Computing http://na-mic.org
What happens when we invoke ::New() ?
itk::LightObject
New()
itk::ObjectFactory<T>
Create()
CreateInstance( typeid(T) )
itk::ObjectFactoryBase
Iterate over Registered Factories
CreateObject( classname)return pointer, or NULL
if NULL call “new”
National Alliance for Medical Image Computing http://na-mic.org
Factories
itk::ObjectFactoryBase
RegisteredFactories std::list< ObjectFactoryBase *>static
static void RegisteredFactory( ObjectFactoryBase *)
ObjectFactory X
ObjectFactory Y
ObjectFactory Z
ObjectFactory W
National Alliance for Medical Image Computing http://na-mic.org
Factories can be loaded as Dynamic Libraries
itk::ObjectFactoryBase
LoadLibrariesInPath( char * path )static
itk::DynamicLoader
From pathget all filenamesthat are shared libraries
GetSymbolAddress()
OpenLibrary( fname)
RegisterFactory( ObjectFactoryBase* )static
National Alliance for Medical Image Computing http://na-mic.org
Loading Dynamic Factories
• Set environment variable ITK_AUTOLOAD_PATH
• In the Shared library create an itkLoad() functionthat returns an itk::ObjectFactoryBase *
• Compile the shared library using CMake commandADD_LIBRARY( Name SHARED …sources…)
• Copy the shared library in one of the directories in ITK_AUTOLOAD_PATH
National Alliance for Medical Image Computing http://na-mic.org
Image Adaptors
Exercise 29
Create a simple Factory
Use the same structure for replacingan existing ITK class
National Alliance for Medical Image Computing http://na-mic.org
Creating my own Factory
itk::ObjectFactoryBase
itk::MyOwnFactory
• static itkLoad();• FactoryLessNewMacro();• FactoryNew();• GetITKSourceVersion();• GetDescription();• RegisterOneFactory();• MyOwnFactory(); // constructor• ~MyOwnFactory(); // destructor
National Alliance for Medical Image Computing http://na-mic.org
Traits
Insight Toolkit - Advanced Course
Knowing others is Wisdom
Knowing the Self is Enlightenment
Tao Te Ching
National Alliance for Medical Image Computing http://na-mic.org
Traits
Traits
• Types declared inside another Type
• Fundamental for enforcing consitency
National Alliance for Medical Image Computing http://na-mic.org
#include “itkImageBase.h”
template<class TPixel, unsigned int VDimension>class Image : public ImageBase< VDimension >{public: typedef Image Self; typedef ImageBase< VDimension > Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer;
itkNewMacro( Self ); itkTypeMacro(Image, ImageBase );
typedef TPixel PixelType;
itkStaticConstMacro(ImageDimension, unsigned int, VDimension);
Traits Examples
National Alliance for Medical Image Computing http://na-mic.org
#include “itkImage.h”
int main( int, char * argv []) {typedef itk::Image< unsigned char, 2 > ImageType;
typedef itk::ImageFilterReader< ImageType > ReaderType; ReaderType::Pointer reader = ReaderType::New();reader->SetFileName( argv[1] );
ImageType::ConstPointer image = reader->GetOutput();
ImageType::IndexType index;index.Fill(0);
ImageType::PixelType pixel = reader->GetPixel( index );
Use Traits instead of redundant declarations !
National Alliance for Medical Image Computing http://na-mic.org
template <class TImage>class ImageFilter {public: typedef TImage ImageType; const ImageType * GetImage() const;private: typename ImageType::ConstPointer m_Image;};
template <class TImage>const typename ImageFilter<TImage>::ImageType *ImageFilter<TImage>::GetImage() const{ return m_Image;}
Very Important in Return Types…
National Alliance for Medical Image Computing http://na-mic.org
template <class TImage>class ImageFilter { typename TImage::ConstPointer m_Image;};
Note the use of typename
You need typename if all the following applies
• You are in a templated class• You are accessing a trait from a class that
depends on the template arguments of your current class.
National Alliance for Medical Image Computing http://na-mic.org
Compilers and typename
The keyword typename is supported differenty by different compilers
• Totally ignored by Visual Studio 6.0• Supported in Visual Studio 7.0 and 7.1• Required in gcc 3.2, gcc 3.3• Implicit typenames not supported in gcc 3.4
National Alliance for Medical Image Computing http://na-mic.org
END
Insight Toolkit - Advanced Course