[Insight-users] Question regarding centered versor transform

Dan Mueller dan.muel at gmail.com
Thu Oct 30 05:44:45 EDT 2008


Is someone able to confirm if this is a bug with the code or with the user?

2008/10/28 Dan Mueller <dan.muel at gmail.com>:
> I've had a dig into the code and seem to have found an inconsistency...
>
> In itkVersorTransform.txx in SetRotation(.) the versor is set and then
> both ComputeMatrix(.) and ComputeOffset(.) are called.
>
> In itkVersorTransform.txx in SetParameters(.) the verser is set and
> then only ComputeMatrix(.) is called. If I add ComputeOffset(.) here,
> then my code works as expected.
>
> Should I file a bug, or have I misunderstood something?
>
> Regards, Dan
>
> 2008/10/28 Dan Mueller <dan.muel at gmail.com>:
>> 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