[Insight-users] Question regarding centered versor transform
Dan Mueller
dan.muel at gmail.com
Tue Oct 28 10:18:47 EDT 2008
Hi Insight Users,
I am experiencing a problem with setting parameters for centered
versor transforms.
Some background: I ultimately want to perform registration considering
only (centered) rotation. From my understanding the VersorTransform
compactly represents a centered rotation in 3D space (three rotation
parameters, no translation parameters optimized). However, when the
VersorTransformOptimizer optimizes the metric I seem to be noticing
"translation". I think this "translation" is occurring because the
center of rotation/translation/offset ? is not being set correctly
when setting the versor parameters.
To further investigate the issue I have simplified the problem,
totally removing the registration component, only considering image
resampling with a VersorTransform. The source code attached below does
the following:
1. Read the fixed image
2. Read the moving image
3. Create and setup the transform
4. Create interpolator
5. Resample moving image using the transform
6. Write resampled image
What I am observing is the following:
a. If I set the rotation via Versor.SetRotation(.) everything behaves
as I expect (i.e. the image is rotated around the center).
b. If I set the rotation via Transform.SetParameters(.) (which is what
the optimizer does) the rotation is NOT around the (desired) center.
I have made screen shots showing the results of (a) and (b) above,
only changing the #define SETBYPARAMETERS.
https://fileshare.qut.edu.au/public/muellerd/resampled_direct.png
https://fileshare.qut.edu.au/public/muellerd/resampled_param.png
The problem described in (b) seems to be what I am noticing with my
registration (i.e. a rotation around the wrong center, introducing
"translation").
What am I doing wrong? Have I misunderstood something? Is this a bug
with VersorTransform?
Thanks for any advice!
Regards, Dan
=== CMake ===
PROJECT(VersorTest)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
FIND_PACKAGE(ITK REQUIRED)
INCLUDE(${ITK_USE_FILE})
ADD_EXECUTABLE(VersorTest main.cxx)
TARGET_LINK_LIBRARIES(VersorTest ITKCommon ITKIO)
=== Source Code (main.cxx) ===
#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkVersorTransform.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkResampleImageFilter.h"
#define SETBYPARAMETERS 0
int main(int argc, char* argv[]) {
try {
// Typedefs
const unsigned int Dimension = 3;
typedef float PixelType;
typedef double CoordRepType;
typedef itk::Image< PixelType, Dimension > ImageType;
typedef ImageType::PointType PointType;
typedef itk::Vector< CoordRepType, Dimension > VectorType;
// 1. Read fixed image
std::cout << "Reading fixed image..." << std::endl;
typedef itk::ImageFileReader< ImageType > ReaderType;
ReaderType::Pointer readerFixed = ReaderType::New( );
readerFixed->SetFileName( "D:/Temp/fixed.mhd" );
readerFixed->Update( );
ImageType::Pointer imageFixed = readerFixed->GetOutput();
imageFixed->DisconnectPipeline( );
// 2. Read moving image
std::cout << "Reading moving image..." << std::endl;
ReaderType::Pointer readerMoving = ReaderType::New( );
readerMoving->SetFileName( "D:/Temp/moving.mhd" );
readerMoving->Update( );
ImageType::Pointer imageMoving = readerMoving->GetOutput();
imageMoving->DisconnectPipeline( );
// 3. Create and setup transform
// NOTE: This basically does the same as CenteredTransformInitializer
// with geometry on
std::cout << "Creating transform..." << std::endl;
typedef itk::VersorTransform< CoordRepType > TransformType;
TransformType::Pointer transform = TransformType::New();
PointType centerFixed;
for (int i=0; i<Dimension; i++) {
centerFixed[i] =
imageFixed->GetOrigin()[i] +
imageFixed->GetLargestPossibleRegion().GetSize()[0] *
imageFixed->GetSpacing()[0] / 2.0;
}
PointType centerMoving;
for (int i=0; i<Dimension; i++) {
centerMoving[i] =
imageMoving->GetOrigin()[i] +
imageMoving->GetLargestPossibleRegion().GetSize()[0] *
imageMoving->GetSpacing()[0] / 2.0;
}
VectorType translation = centerFixed - centerMoving;
TransformType::VersorType versor;
versor.Set( 0.0, 0.0, 0.9, 0.43589 );
transform->SetCenter( centerFixed );
transform->SetTranslation( translation );
TransformType::ParametersType param( Dimension );
for (int i=0; i<Dimension; i++) {
param[i] = versor.GetRight()[i];
}
#if SETBYPARAMETERS
std::cout << "Setting rotation using parameters..." << param
<< std::endl;
transform->SetParameters( param );
#else
std::cout << "Setting rotation directly..." << versor << std::endl;
transform->SetRotation( versor );
#endif
// 4. Create interpolator
typedef itk::LinearInterpolateImageFunction< ImageType,
CoordRepType > InterpolatorType;
InterpolatorType::Pointer interpolator = InterpolatorType::New();
// 5. Resample
std::cout << "Resampling moving image..." << std::endl;
typedef itk::ResampleImageFilter< ImageType, ImageType> ResampleType;
ResampleType::Pointer resample = ResampleType::New();
resample->SetInput( imageMoving );
resample->SetOutputParametersFromImage( imageFixed );
resample->SetInterpolator( interpolator );
resample->SetTransform( transform );
resample->Update( );
// 6. Write resample image
std::cout << "Writing resampled image..." << std::endl;
typedef itk::ImageFileWriter< ImageType > WriterType;
WriterType::Pointer writer = WriterType::New( );
writer->SetFileName( "D:/Temp/resampled.mhd" );
writer->SetInput( resample->GetOutput() );
writer->Update( );
return EXIT_SUCCESS;
}
catch( itk::ExceptionObject& err ) {
std::cout << err << std::endl;
return EXIT_FAILURE;
}
}
=== Information ===
ITK 3.8
CMake 2.6.0
Windows XP 64-bit SP2
Visual Studio 8.0.50727.762
More information about the Insight-users
mailing list