NA-MIC National Alliance for Medical Image Computing ITK Workshop October 5-8, 2005 Software Design.

Post on 27-Mar-2015

214 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

Transcript

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

top related