[ITK] templating typdef question

Dr Bernhard Schaffer bschaffer at superstem.org
Mon Nov 3 03:51:11 EST 2014


Hi Matt,

I´m afraid I still don't quite get it.

I think I've understood the concept of the template and the switch-cases from the example you've given [1],

but that example code does not seem to 'return' the final image in any way, and that's where I'm stuck at the moment.

 

Leaving different types aside and just looking into dimensionality, I now basically have the following working:

 

The (dimension) template class wrapping around my own image object MyIMG and one of the functions I want to use the wrapper in:

( Methods are static methods of my class. My own stuff is marked in orange below. (Do emails in this list preserve formatting?) )

 

void MyITKWrapper::SomeCoolITKMethod( MyIMG img )

{

       switch ( img.GetDimensionality() )

       {

              case( 2 ):    MyITKWrapper::WrapScalarImage < 2 >( img );     break;

              case( 3 ):    MyITKWrapper::WrapScalarImage < 3 >( img );     break;

       }

}

 

template< unsigned int VDimension >

void MyITKWrapper::WrapScalarImage( MyIMG img )

{

       typedef itk::ImportImageFilter<float,VDimension> ImportFilterType;

       ImportFilterType::Pointer importFilter = ImportFilterType::New();

       

       ImportFilterType::SizeType  size;

       ImportFilterType::IndexType start;

       itk::SpacePrecisionType origin[VDimension];

       itk::SpacePrecisionType spacing[VDimension];

       long nPixels=1;

       for ( int dim = 0; dim<VDimension; dim++ )

       {

              size[dim] = img.GetSizeAlongDimension(dim);

              nPixels *= size[dim];

              start[dim] = 0;

              origin[dim] = 0.0;

              spacing[dim] = 1.0;

       }

 

       ImportFilterType::RegionType region;

       region.SetIndex( start );

       region.SetSize(  size  );

       importFilter->SetRegion( region );

       importFilter->SetOrigin( origin );

       importFilter->SetSpacing( spacing );

 

       float *localBuffer = (float *) img.GetArrayPointer(); 

       const bool importImageFilterWillOwnTheBuffer = false;  

       importFilter->SetImportPointer( localBuffer, nPixels, importImageFilterWillOwnTheBuffer );

       return;

}

 

 

This compiles and is fine. The problem, of course, is, that I now want to use the “importFilter” in my “SomeCoolITKMethod” method, so that I can go on like:

 

 

void MyITKWrapper::SomeCoolITKMethod( MyIMG img )

{

       switch ( img.GetDimensionality() )

       {

              case( 2 ):    importFilter = MyITKWrapper::WrapDMScalarImage < 2 >( img );  break;

              case( 3 ):    importFilter = MyITKWrapper::WrapDMScalarImage < 3 >( img );  break;

       }

 

       otherCoolITKFilter->SetInput( importFilter->GetOutput() );

       […]

a lot more stuff

[…]

}

 

…but I don’t know how I can “define” importFilter generically in this method, and I also can’t make 

 

itk::ImportImageFilter<float,VDimension>

 

the return-type of my templated wrapper method.

Do I have to make “SomeCoolITKMethod” a template function itself and have the switch-case in the method calling SomeCoolITKMethod ? Or is there a better way?

 

Thanks,

  Bernhard

 

 

 

 

 

[1] http://itk.org/ITKExamples/src/IO/ImageBase/ReadUnknownImageType/Documentation.html

 

-----Original Message-----
From: Matt McCormick [mailto:matt.mccormick at kitware.com] 
Sent: 29 October 2014 22:28
To: Dr Bernhard Schaffer
Cc: community at itk.org
Subject: Re: [ITK] templating typdef question

 

Hi Bernhard,

 

Welcome to ITK!

 

The basic strategy is to put all the templated code in a template function or class.  This prevents duplicated code (the root of almost all evil).  Then, use a switch statement and call the appropriate templates.  An example is here [1], which is long because it switches over both a number of pixel types and dimensions, but it demonstrates the idea.

 

Inside the templated code, use for loops instead explicit assignment to set each dimension value.  Also, use code like

 

  Image::SpacingType spacing;

  spacing.Fill( 1.0 );

 

instead of

 

  itk::SpacePrecisionType spacing[2];

  spacing[0] = 1.0;

  spacing[1] = 1.0;

 

Hope this helps,

Matt

 

 

[1]  <http://itk.org/ITKExamples/src/IO/ImageBase/ReadUnknownImageType/Documentation.html> http://itk.org/ITKExamples/src/IO/ImageBase/ReadUnknownImageType/Documentation.html

 

On Wed, Oct 29, 2014 at 5:03 PM, Dr Bernhard Schaffer < <mailto:bschaffer at superstem.org> bschaffer at superstem.org> wrote:

> Hi,

> 

> This is my second email to this list. I’m still not so familiar with 

> typedefs in coding, and I’ve the current problem:

> 

> 

> 

> I have my own “image” objects which can be 2D or 3D and of different 

> number type.  If I assume they are only 2D and float I can do something like this:

> 

> (The cyan lines show methods of  ‘my’ object.)

> 

> 

> 

> 

> 

> const unsigned int DIMENSION = 2;

> 

> 

> 

>           typedef itk::ImportImageFilter<float, DIMENSION > 

> ImportFilterType;

> 

> ImportFilterType::Pointer importFilter = ImportFilterType::New();

> 

> 

> 

> ImportFilterType::SizeType  size;

> 

>           size[0]  = MYIMAGE.GetXSIZE();

> 

> size[1]  = MYIMAGE.GetYSIZE();

> 

> 

> 

>           ImportFilterType::IndexType start;

> 

>           start.Fill( 0 );

> 

> 

> 

>           ImportFilterType::RegionType region;

> 

>           region.SetIndex( start );

> 

>           region.SetSize(  size  );

> 

> importFilter->SetRegion( region );

> 

> 

> 

> const itk::SpacePrecisionType origin[ DIMENSION ] = { 0.0, 0.0 };

> 

>           importFilter->SetOrigin( origin );

> 

> 

> 

>           const itk::SpacePrecisionType  spacing[ DIMENSION ] =  { 

> 1.0, 1.0 };

> 

> importFilter->SetSpacing( spacing );

> 

> 

> 

>           const bool importImageFilterWillOwnTheBuffer = false;

> 

> 

> 

>           float *localBuffer = MYIMAGE.GETPOINTER();

> 

>           importFilter->SetImportPointer( localBuffer, 

> size[0]*size[1], importImageFilterWillOwnTheBuffer );

> 

> 

> 

>           typedef itk::Image< float,DIMENSION >   InputImageType;

> 

>           typedef itk::Image< float,DIMENSION >   OutputImageType;

> 

> 

> 

>           typedef itk::CurvatureFlowImageFilter< InputImageType, 

> OutputImageType >  FilterType;

> 

>           FilterType::Pointer filter = FilterType::New();

> 

> 

> 

>           filter->SetInput( importFilter->GetOutput() );

> 

>           filter->SetTimeStep( timeStep );

> 

>           filter->SetNumberOfIterations( iterations );

> 

>           filter->Update();

> 

>           typedef itk::ImageRegionIterator< OutputImageType > 

> IteratorType;

> 

>           OutputImageType::Pointer filtered = filter->GetOutput();

> 

>           […]

> 

> 

> 

> If my image is 3D I can do accordingly: (Yellow is the difference to 

> above)

> 

> 

> 

> const unsigned int DIMENSION = 3;

> 

> 

> 

>           typedef itk::ImportImageFilter<float, DIMENSION > 

> ImportFilterType;

> 

> ImportFilterType::Pointer importFilter = ImportFilterType::New();

> 

> 

> 

> ImportFilterType::SizeType  size;

> 

>           size[0]  = MYIMAGE.GetXSIZE();

> 

> size[1]  = MYIMAGE.GetYSIZE();

> 

> size[2]  = MYIMAGE.GetZSIZE();

> 

> 

> 

> 

> 

>           ImportFilterType::IndexType start;

> 

>           start.Fill( 0 );

> 

> 

> 

>           ImportFilterType::RegionType region;

> 

>           region.SetIndex( start );

> 

>           region.SetSize(  size  );

> 

> importFilter->SetRegion( region );

> 

> 

> 

> const itk::SpacePrecisionType origin[ DIMENSION ] = { 0.0, 0.0, 0.0 };

> 

>           importFilter->SetOrigin( origin );

> 

> 

> 

>           const itk::SpacePrecisionType  spacing[ DIMENSION ] =  { 

> 1.0, 1.0,

> 1.0 };

> 

> importFilter->SetSpacing( spacing );

> 

> 

> 

>           const bool importImageFilterWillOwnTheBuffer = false;

> 

> float *localBuffer = MYIMAGE.GETPOINTER();

> 

>           importFilter->SetImportPointer( localBuffer, 

> size[0]*size[1]*size[2], importImageFilterWillOwnTheBuffer );

> 

> 

> 

>           typedef itk::Image< float,DIMENSION >   InputImageType;

> 

>           typedef itk::Image< float,DIMENSION >   OutputImageType;

> 

> 

> 

>           typedef itk::CurvatureFlowImageFilter< InputImageType, 

> OutputImageType >  FilterType;

> 

>           FilterType::Pointer filter = FilterType::New();

> 

> 

> 

>           filter->SetInput( importFilter->GetOutput() );

> 

>           filter->SetTimeStep( timeStep );

> 

>           filter->SetNumberOfIterations( iterations );

> 

>           filter->Update();

> 

>           typedef itk::ImageRegionIterator< OutputImageType > 

> IteratorType;

> 

>           OutputImageType::Pointer filtered = filter->GetOutput();

> 

>           […]

> 

> 

> 

> The problem I have is the following. I can query my object about its 

> dimensionality, but I can’t do the following:

> 

> 

> 

> const unsigned int DIMENSION = MYIMAGE.GETDIMENSIONALITY();

> 

> 

> 

> because the typedefs are evaluated on compilation not on runtime.   So my

> way around this is, to actually duplicate  all the code and have both 

> my examples in a switch-case:

> 

> 

> 

>           switch(MYIMAGE.GETDIMENSIONALITY())

> 

>           {

> 

>           case(2):

> 

>                     {

> 

> … EXAMPLE 2D as above

> 

> }

> 

>                    break;

> 

>           case(3):

> 

>                     {

> 

> … EXAMPLE 3D as above

> 

> }

> 

>                    break;

> 

> }

> 

> 

> 

> Which is rather obvious code duplication. Is there a better way to do this?

> (there has to!)  The problem branches out, if I also allow the type 

> float to be specified by my object as in

> 

>           switch(MYIMAGE.GETDATATYPE())

> 

>           {

> 

>           case(1):…float…;

> 

>           case(2):…double…;

> 

>           case(3):…

> 

>
> 

> }

> 

> 

> 

> 

> 

> I would very much appreciate a few lines of (pseudo-) code showing me 

> how I can do this better.

> 

> 

> 

> Thank you very much,

> 

>    Best regards,

> 

>    Bernhard

> 

> 

> 

> 

> _______________________________________________

> Community mailing list

>  <mailto:Community at itk.org> Community at itk.org

>  <http://public.kitware.com/mailman/listinfo/community> http://public.kitware.com/mailman/listinfo/community

> 

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/community/attachments/20141103/b3742269/attachment-0001.html>


More information about the Community mailing list