[Insight-users] 3D Affine transformation

Petter Risholm risholm at stud . ntnu . no
Fri, 14 Nov 2003 09:09:14 +0100 (CET)


hi,

I'm trying to do a 3D affine transformation on a 3D volume but am having
huge difficulties getting a resonable result.

When I run my program without doing any transformations (no rotation and
no translation), the first slice of the output volume looks exactly like
the input volume. However, the rest of the slices have no information
except for the DefaultPixelValue.

Is there something wrong with the resampling I'm doing?

This program is just an extension to 3D of the ResampleImageFilter4 found
in the examples.

Next follows the metaheader for the volume, next is the code for my
program.

regards Petter Risholm

 NDims = 3 DimSize = 128 128 20
ElementSpacing = 1 1 1
Position = 0 0 0
ElementByteOrderMSB = False
ElementType = MET_USHORT
HeaderSize = -1
ElementDataFile = LIST 2
Image_ref.raw

int main( int argc, char * argv[] )
{
  if( argc < 5 )
    {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << "  inputImageFile  outputImageFile  degrees
x-trans y-trans z-trans" << std::endl;
    return 1;
    }

  const     unsigned int   Dimension = 3;
  typedef   unsigned short  InputPixelType;
  typedef   unsigned short  OutputPixelType;

  typedef itk::Image< InputPixelType,  Dimension >   InputImageType;
  typedef itk::Image< OutputPixelType, Dimension >   OutputImageType;

  typedef itk::ImageFileReader< InputImageType  >  ReaderType;
  typedef itk::ImageFileWriter< OutputImageType >  WriterType;
 reader->SetFileName( argv[1] );
  writer->SetFileName( argv[2] );

  const double angleInDegrees = atof( argv[3] );
  const int xtrans = atoi( argv[4] );
  const int ytrans = atoi( argv[5] );
  const int ztrans = atoi( argv[6] );

  typedef itk::ResampleImageFilter<
                  InputImageType, OutputImageType >  FilterType;

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

  typedef itk::AffineTransform< double, Dimension >  TransformType;
  TransformType::Pointer transform = TransformType::New();

  typedef itk::BSplineInterpolateImageFunction<
                       InputImageType, double >  InterpolatorType;
  InterpolatorType::Pointer interpolator = InterpolatorType::New();

  filter->SetInterpolator( interpolator );

  filter->SetDefaultPixelValue( 13 );

  reader->Update();
  const double * spacing = reader->GetOutput()->GetSpacing();
  const double * origin  = reader->GetOutput()->GetOrigin();
  InputImageType::SizeType size =
      reader->GetOutput()->GetLargestPossibleRegion().GetSize();
  std::cout << "size: " <<  size << "\n";
  filter->SetOutputOrigin( origin );
  filter->SetOutputSpacing( spacing );
  filter->SetSize( size );


  filter->SetInput( reader->GetOutput() );
  writer->SetInput( filter->GetOutput() );

  TransformType::OutputVectorType translation1;

  const double imageCenterX = origin[0] + spacing[0] * size[0] / 2.0;
  const double imageCenterY = origin[1] + spacing[1] * size[1] / 2.0;
  const double imageCenterZ = origin[2] + spacing[2] * size[2] / 2.0;

  translation1[0] =   -imageCenterX;
  translation1[1] =   -imageCenterY;
  translation1[2] =   -imageCenterZ;

   transform->Translate( translation1 );

  std::cout << "imageCenterX = " << imageCenterX << std::endl;
  std::cout << "imageCenterY = " << imageCenterY << std::endl;
  std::cout << "imageCenterZ = " << imageCenterZ << std::endl;
TransformType::OutputVectorType axis;
  axis[0] = 0;
  axis[1] = 0;
  axis[2] = 1;

  const double degreesToRadians = atan(1.0) / 45.0;
  const double angle = angleInDegrees * degreesToRadians;
  transform->Rotate3D(axis, angle, false );

  TransformType::OutputVectorType translation2;
  translation2[0] =   imageCenterX + xtrans;
  translation2[1] =   imageCenterY + ytrans;
  translation2[2] =   imageCenterZ + ztrans;
  transform->Translate( translation2, false );

  filter->SetTransform( transform );

  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & excep )
    {
    std::cerr << "Exception catched !" << std::endl;
    std::cerr << excep << std::endl;
    }
  // Software Guide : EndCodeSnippet
return 0;
}