[Insight-users] Comparing AffineTransform and CenteredAffineTransform

Gavin Baker gavinb+xtk at cs . mu . OZ . AU
Mon, 13 Oct 2003 19:41:06 +1000


--HlL+5n6rz5pIUxbD
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline


Hello,

I have been working with the ResampleImageFilter, and got some unexpected
results with the transforms.  From reading the docs, it seems that
CenteredAffineTransform is simply an AffineTransform that rotates about the
specified center point.

So I wrote a test case (attached) to explore the difference between an
AffineTransform and a CenteredAffineTransform.  All it is supposed to do is
rotate the input data about the center of the image.

The AffineTransform does a:

  translate( -center )
  rotate( angle )
  translate( center )

While the CenteredAffineTransform does a:

  set center( center )
  rotate( angle )

I would have expected the output to be the same for both.  However the
output of the CenteredAffineTransform ends up translated off to the side,
when no translation has been specified (and is not merely size/2).

Have I missed something here?  Any insights appreciated...

Thanks,

  :: Gavin

-- 
Gavin Baker                                Computer Vision Lab (CVMIL)
http://www . cs . mu . oz . au/~gavinb                 University of Melbourne

--HlL+5n6rz5pIUxbD
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="test_centered.cxx"


#include <itkImage.h>
#include <itkCastImageFilter.h>
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include <itkExtractImageFilter.h>
#include <itkResampleImageFilter.h>
#include <itkAffineTransform.h>
#include <itkCenteredAffineTransform.h>

int main( int argc, char* argv[] )
{
    if ( argc < 4 )
    {
        std::cerr << "usage: test_centered <in> <out_a> <out_c>" << std::endl;
        return 1;
    }

    // Pixels ______________________________________________________________

    typedef unsigned short
        InputPixelType;

    typedef unsigned short
        InternalPixelType;

    typedef unsigned short
        OutputPixelType;    

    // Images ______________________________________________________________

    enum { Dimension = 3 };

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

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

    // Pipeline ____________________________________________________________

    typedef itk::ImageFileReader<
        InputImageType >                        ReaderType;

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

    typedef itk::AffineTransform<
        double,
        3>                                      AffineType;

    typedef itk::CenteredAffineTransform<
        double,
        3>                                      CenteredAffineType;

    typedef itk::ImageFileWriter<
        OutputImageType >                       WriterType;

    // Construct pipeline __________________________________________________

    ReaderType::Pointer         _reader     = ReaderType::New();
    ResampleType::Pointer       _resample_a = ResampleType::New();
    ResampleType::Pointer       _resample_c = ResampleType::New();
    AffineType::Pointer         _xform_a    = AffineType::New();
    CenteredAffineType::Pointer _xform_c    = CenteredAffineType::New();
    WriterType::Pointer         _writer_a   = WriterType::New();
    WriterType::Pointer         _writer_c   = WriterType::New();

    // Connect pipeline ____________________________________________________

    _reader->SetFileName( argv[1] );

    _resample_a->SetInput( _reader->GetOutput() );
    _resample_a->SetTransform( _xform_a );
    _writer_a->SetInput( _resample_a->GetOutput() );

    _resample_c->SetInput( _reader->GetOutput() );
    _resample_c->SetTransform( _xform_c );
    _writer_c->SetInput( _resample_c->GetOutput() );

    _writer_a->SetFileName( argv[2] );
    _writer_c->SetFileName( argv[3] );

    // Set parameters _______________________________________________________

    _reader->Update();

    ResampleType::SizeType in_size =
        _reader->GetOutput()->GetLargestPossibleRegion().GetSize();

    std::cout << "Input volume size: " << in_size << std::endl;

    float rot_angle = 0.7; // radians

    // Affine ______________________________________________________________

    AffineType::OutputVectorType center_a;
    center_a[0] = in_size[0]/2;
    center_a[1] = in_size[1]/2;
    center_a[2] = in_size[2]/2;

    _xform_a->Translate( -center_a );
    _xform_a->Rotate( 0, 1, rot_angle );
    _xform_a->Translate( center_a );

    _resample_a->SetDefaultPixelValue( 86 ); // Get Smart!
    _resample_a->SetSize(in_size);

    std::cout << "Center point: " << center_a << std::endl;

    _xform_a->Print(std::cout);

    // Centered ____________________________________________________________

    CenteredAffineType::InputPointType center_c;
    center_c[0] = center_a[0];
    center_c[1] = center_a[1];
    center_c[2] = center_a[2];

    _xform_c->SetCenter( center_c );
    _xform_c->Rotate( 0, 1, rot_angle );

    _resample_c->SetDefaultPixelValue( 86 );
    _resample_c->SetSize(in_size);

    _xform_c->Print(std::cout);

    // Save the output ______________________________________________________

    try
    {
        std::cout << "Saving AffineTransform result..." << std::endl;
        _writer_a->Update();

        std::cout << "Saving CenteredAffineTransform result..." << std::endl;
        _writer_c->Update();
    }
    catch( itk::ExceptionObject& excep )
    {
        std::cerr
            << "Exception caught !\n"
            << excep << std::endl
            ;
    }

    return 0;
}

--HlL+5n6rz5pIUxbD--