<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-15">
  </head>
  <body bgcolor="#ffffff" text="#000000">
    <div class="moz-text-html" lang="x-western">
      <pre><i></i>&gt;<i> 
</i>&gt;<i> Hi there,
</i>&gt;<i> I am trying to register two 3-D images,
</i>&gt;<i> using the MattesMutualInformationMetric with the versor3Drigid transform and the 
VersorRigid3DTransformOptimizer optimizer .</i><i>
Actually after reading the images, I am using the normalizeImageFilter and the DiscreteGaussianImageFilter
to preprocess the images before registration.

But when I am calling the registration routine, I am getting errors. 
I guess there may be errors when I am calling the CenteredTransformInitializer, Could someone
check my code and help me?

Here is my code:

// imreg.cpp : Defines the entry point for the DLL application.
//

// imreg.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"

// Header files for ITK image registration
#include "itkImageRegistrationMethod.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkMattesMutualInformationImageToImageMetric.h"
#include "itkMutualInformationImageToImageMetric.h"
#include "itkMeanReciprocalSquareDifferenceImageToImageMetric.h"
#include "itkNormalizedCorrelationImageToImageMetric.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkImage.h"


#include "itkTimeProbesCollectorBase.h"

#ifdef ITK_USE_REVIEW
#include "itkMemoryProbesCollectorBase.h"
#define itkProbesCreate()  \
  itk::TimeProbesCollectorBase chronometer; \
  itk::MemoryProbesCollectorBase memorymeter
#define itkProbesStart( text ) memorymeter.Start( text ); chronometer.Start( text )
#define itkProbesStop( text )  chronometer.Stop( text ); memorymeter.Stop( text  )
#define itkProbesReport( stream )  chronometer.Report( stream ); memorymeter.Report( stream  )
#else
#define itkProbesCreate()  \
  itk::TimeProbesCollectorBase chronometer
#define itkProbesStart( text ) chronometer.Start( text )
#define itkProbesStop( text )  chronometer.Stop( text )
#define itkProbesReport( stream )  chronometer.Report( stream )
#endif

#include "itkBSplineDeformableTransform.h"
#include "itkLBFGSBOptimizer.h"
#include "itkVersorRigid3DTransform.h"
#include "itkCenteredTransformInitializer.h"
#include "itkVersorRigid3DTransformOptimizer.h"

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkResampleImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkSquaredDifferenceImageFilter.h"

#include "itkImportImageFilter.h"
#include "itkMultiThreader.h"

//  The following section of code implements a Command observer
//  that will monitor the evolution of the registration process.
//
#include "itkCommand.h"

#include "itkNormalizeImageFilter.h"
#include "itkDiscreteGaussianImageFilter.h"

#define WM_MESSAGE_STATUS WM_USER +13

class CommandIterationUpdate : public itk::Command 
{
public:
  typedef  CommandIterationUpdate   Self;
  typedef  itk::Command             Superclass;
  typedef itk::SmartPointer&lt;Self&gt;  Pointer;
  itkNewMacro( Self );
protected:
  CommandIterationUpdate() {};
public:
  typedef itk::VersorRigid3DTransformOptimizer     OptimizerType;
  typedef   const OptimizerType   *    OptimizerPointer;

  void Execute(itk::Object *caller, const itk::EventObject &amp; event)
    {
      Execute( (const itk::Object *)caller, event);
    }

  void Execute(const itk::Object * object, const itk::EventObject &amp; event)
    {
      OptimizerPointer optimizer = 
        dynamic_cast&lt; OptimizerPointer &gt;( object );
      if( ! itk::IterationEvent().CheckEvent( &amp;event ) )
        {
        return;
        }
      std::cout &lt;&lt; optimizer-&gt;GetCurrentIteration() &lt;&lt; "   ";
      std::cout &lt;&lt; optimizer-&gt;GetValue() &lt;&lt; "   ";
      std::cout &lt;&lt; optimizer-&gt;GetCurrentPosition() &lt;&lt; std::endl;
    }
};

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                                         )
{
    return TRUE;
}


__declspec(dllexport) int RegisterImage2to1(short *pixdata1, short *pixdata2, int xdim, int ydim, int zdim){
        // define image dimension and data type
        const unsigned int    ImageDimension = 3;
        typedef  float           PixelType;
        // define fixed and moving image
        typedef itk::Image&lt; PixelType, ImageDimension &gt;  FixedImageType;
        typedef itk::Image&lt; PixelType, ImageDimension &gt;  MovingImageType;

        typedef   float                                    InternalPixelType;
        typedef itk::Image&lt; InternalPixelType, ImageDimension &gt; InternalImageType;

        typedef itk::VersorRigid3DTransform&lt; double &gt; TransformType;

        const unsigned int SpaceDimension = ImageDimension;
        const unsigned int SplineOrder = 3;
        typedef double CoordinateRepType;

        typedef itk::VersorRigid3DTransformOptimizer           OptimizerType;

        /*typedef itk::NormalizedCorrelationImageToImageMetric&lt; 
                                    FixedImageType, 
                                    MovingImageType &gt;    MetricType;*/
        
        /*typedef itk::MeanReciprocalSquareDifferenceImageToImageMetric&lt; 
                                    FixedImageType, 
                                    MovingImageType &gt;    MetricType;*/

        /*typedef itk::MeanSquaresImageToImageMetric&lt; 
                                    FixedImageType, 
                                    MovingImageType &gt;    MetricType;

          typedef itk::MutualInformationImageToImageMetric&lt; 
                                          InternalImageType, 
                                          InternalImageType &gt;    MetricType;*/


        typedef itk::MattesMutualInformationImageToImageMetric&lt; 
                                    InternalImageType, 
                                    InternalImageType &gt;    MetricType;

        typedef itk:: LinearInterpolateImageFunction&lt; 
                                    InternalImageType,
                                    double          &gt;    InterpolatorType;

        typedef itk::ImageRegistrationMethod&lt; 
                                    InternalImageType, 
                                    InternalImageType &gt;    RegistrationType;

        MetricType::Pointer         metric        = MetricType::New();
        OptimizerType::Pointer      optimizer     = OptimizerType::New();
        InterpolatorType::Pointer   interpolator  = InterpolatorType::New();
        RegistrationType::Pointer   registration  = RegistrationType::New();
  
        registration-&gt;SetMetric(        metric        );
        registration-&gt;SetOptimizer(     optimizer     );
        registration-&gt;SetInterpolator(  interpolator  );


        TransformType::Pointer  transform = TransformType::New();
        registration-&gt;SetTransform( transform );

        /*metric-&gt;SetFixedImageStandardDeviation(  0.4 );
        metric-&gt;SetMovingImageStandardDeviation( 0.4 );*/

        // define import filter #1 and #2 for data import to itk
        typedef itk::ImportImageFilter&lt; PixelType, ImageDimension&gt; ImportFilterType;
        ImportFilterType::Pointer importFilter1 = ImportFilterType::New();
        ImportFilterType::Pointer importFilter2 = ImportFilterType::New();
        ImportFilterType::SizeType size;
        size[0] = xdim;
        size[1] = ydim;
        size[2] = zdim;
        ImportFilterType::IndexType start;
        start.Fill( 0 );
        ImportFilterType::RegionType region;
        region.SetIndex( start );
        region.SetSize( size );
        importFilter1-&gt;SetRegion( region );
        importFilter2-&gt;SetRegion( region );
        double origin[ ImageDimension ];
        origin[0] = 0.0;
        origin[1] = 0.0;
        origin[2] = 0.0;
        importFilter1-&gt;SetOrigin( origin );
        importFilter2-&gt;SetOrigin( origin );
        double spacing[ ImageDimension ];
        spacing[0] = 1.0;
        spacing[1] = 1.0;
        spacing[2] = 1.0;
        importFilter1-&gt;SetSpacing( spacing);
        importFilter2-&gt;SetSpacing( spacing);
        // create buffers for images
        const unsigned int numberOfPixels = size[0]*size[1]*size[2];
        PixelType * localBuffer1 = new PixelType[ numberOfPixels ];
        PixelType * it1 = localBuffer1;
        PixelType * localBuffer2 = new PixelType[ numberOfPixels ];
        PixelType * it2 = localBuffer2;
        // set pixels into image #1: fixed image
        for(unsigned int i=0;i&lt;size[0]*size[1]*size[2];i++){
                *it1++ = (float) pixdata1[i];
                // uncomment following lines for thresholding before registration
                /*if(pixdata1[i] &gt; 16)
                        *it1++ = (float) pixdata1[i];
                else
                        *it1++ = 0;*/
        }
        importFilter1-&gt;SetImportPointer( localBuffer1, numberOfPixels, true);
        //registration-&gt;SetFixedImage( importFilter1-&gt;GetOutput() );
        importFilter1-&gt;Update();
        typedef FixedImageType::SpacingType    SpacingType;
        typedef FixedImageType::PointType      OriginType;
        typedef FixedImageType::RegionType     RegionType;
        typedef FixedImageType::SizeType       SizeType;
        FixedImageType::Pointer fixedImage = importFilter1-&gt;GetOutput();
        const SpacingType fixedSpacing = fixedImage-&gt;GetSpacing();
        const OriginType  fixedOrigin  = fixedImage-&gt;GetOrigin();
        const RegionType  fixedRegion  = fixedImage-&gt;GetLargestPossibleRegion(); 
        const SizeType    fixedSize    = fixedRegion.GetSize(); 
        TransformType::InputPointType centerFixed;          
        centerFixed[0] = fixedOrigin[0] + fixedSpacing[0] * fixedSize[0] / 2.0;
        centerFixed[1] = fixedOrigin[1] + fixedSpacing[1] * fixedSize[1] / 2.0;
        centerFixed[2] = fixedOrigin[2] + fixedSpacing[2] * fixedSize[2] / 2.0;
        // set pixels into image #2 moving image
        for(unsigned int i=0;i&lt;size[0]*size[1]*size[2];i++){
                *it2++ = (float) pixdata2[i];
                // uncomment following lines for thresholding before registration
                /*if(pixdata2[i] &gt; 16)
                        *it2++ = (float) pixdata2[i];
                else
                        *it2++ = 0;*/
        }
        importFilter2-&gt;SetImportPointer( localBuffer2, numberOfPixels, true);
        //registration-&gt;SetMovingImage( importFilter2-&gt;GetOutput() );
        importFilter2-&gt;Update();
        MovingImageType::Pointer movingImage = importFilter2-&gt;GetOutput();
        // set center of image
        const SpacingType movingSpacing = movingImage-&gt;GetSpacing();
        const OriginType  movingOrigin  = movingImage-&gt;GetOrigin();
        const RegionType  movingRegion  = movingImage-&gt;GetLargestPossibleRegion();
        const SizeType    movingSize    = movingRegion.GetSize();
        TransformType::InputPointType centerMoving;
        centerMoving[0] = movingOrigin[0] + movingSpacing[0] * movingSize[0] / 2.0;
        centerMoving[1] = movingOrigin[1] + movingSpacing[1] * movingSize[1] / 2.0;
        centerMoving[2] = movingOrigin[2] + movingSpacing[2] * movingSize[2] / 2.0;
        //FixedImageType::RegionType fixedRegion = fixedImage-&gt;GetBufferedRegion();
          registration-&gt;SetFixedImageRegion( fixedRegion );
        
        /*typedef TransformType::RegionType RegionType;
        RegionType bsplineRegion;
        RegionType::SizeType   gridSizeOnImage;
        RegionType::SizeType   gridBorderSize;
        RegionType::SizeType   totalGridSize;

        gridSizeOnImage.Fill( 5 );        // 12 ?
        gridBorderSize.Fill( 3 );    // Border for spline order = 3 ( 1 lower, 2 upper )
        totalGridSize = gridSizeOnImage + gridBorderSize;

        bsplineRegion.SetSize( totalGridSize );

        //typedef TransformType::SpacingType SpacingType;
        //SpacingType spacing = fixedImage-&gt;GetSpacing();
        //typedef TransformType::OriginType OriginType;
        //OriginType origin = fixedImage-&gt;GetOrigin();;

        FixedImageType::SizeType fixedImageSize = fixedRegion.GetSize();

        for(unsigned int r=0; r&lt;ImageDimension; r++)
                {
                spacing[r] *= static_cast&lt;double&gt;(fixedImageSize[r] - 1)  / 
                                        static_cast&lt;double&gt;(gridSizeOnImage[r] - 1);
                origin[r]  -=  spacing[r]; 
                }

        transform-&gt;SetGridSpacing( spacing );
        transform-&gt;SetGridOrigin( origin );
        transform-&gt;SetGridRegion( bsplineRegion );
        transform-&gt;SetGridDirection( fixedImage-&gt;GetDirection() );*/
        
        typedef itk::NormalizeImageFilter&lt; 
                                                        FixedImageType, 
                                                        InternalImageType 
                                                                        &gt; FixedNormalizeFilterType;
        typedef itk::NormalizeImageFilter&lt; 
                                                        MovingImageType, 
                                                        InternalImageType 
                                                                                  &gt; MovingNormalizeFilterType;

        FixedNormalizeFilterType::Pointer fixedNormalizer = 
                                                                                FixedNormalizeFilterType::New();

        MovingNormalizeFilterType::Pointer movingNormalizer =
                                                                                MovingNormalizeFilterType::New();


        typedef itk::DiscreteGaussianImageFilter&lt;
                                                                  InternalImageType, 
                                                                  InternalImageType
                                                                                                &gt; GaussianFilterType;

        GaussianFilterType::Pointer fixedSmoother  = GaussianFilterType::New();
        GaussianFilterType::Pointer movingSmoother = GaussianFilterType::New();

        fixedSmoother-&gt;SetVariance( 2.0 );
        movingSmoother-&gt;SetVariance( 2.0 );

        fixedNormalizer-&gt;SetInput(  importFilter1-&gt;GetOutput() );
        movingNormalizer-&gt;SetInput( importFilter2-&gt;GetOutput() );

        fixedSmoother-&gt;SetInput( fixedNormalizer-&gt;GetOutput() );
        movingSmoother-&gt;SetInput( movingNormalizer-&gt;GetOutput() );

        registration-&gt;SetFixedImage( fixedSmoother-&gt;GetOutput() );
        registration-&gt;SetMovingImage( movingSmoother-&gt;GetOutput() );

        fixedNormalizer-&gt;Update();
        FixedImageType::RegionType fixedImageRegion =
       fixedNormalizer-&gt;GetOutput()-&gt;GetBufferedRegion();
        registration-&gt;SetFixedImageRegion( fixedImageRegion );

        typedef itk::CenteredTransformInitializer&lt; TransformType, 
                                             FixedImageType, 
                                             MovingImageType 
                                                 &gt;  TransformInitializerType;

    TransformInitializerType::Pointer initializer = 
                                          TransformInitializerType::New();

        initializer-&gt;SetTransform(   transform );
    initializer-&gt;SetFixedImage(  importFilter1-&gt;GetOutput() );
    initializer-&gt;SetMovingImage( importFilter2-&gt;GetOutput() );
        initializer-&gt;MomentsOn();
        initializer-&gt;InitializeTransform();
        typedef TransformType::VersorType  VersorType;
        typedef VersorType::VectorType     VectorType;

        VersorType     rotation;
        VectorType     axis;
          
        axis[0] = 0.0;
        axis[1] = 0.0;
        axis[2] = 1.0;

        const double angle = 0.0;

        rotation.Set(  axis, angle  );

        transform-&gt;SetRotation( rotation );
        registration-&gt;SetInitialTransformParameters( transform-&gt;GetParameters() );
        typedef OptimizerType::ScalesType       OptimizerScalesType;
        OptimizerScalesType optimizerScales( transform-&gt;GetNumberOfParameters() );
        const double translationScale = 1.0 / 1000.0;

        optimizerScales[0] = 1.0;
        optimizerScales[1] = 1.0;
        optimizerScales[2] = 1.0;
        optimizerScales[3] = translationScale;
        optimizerScales[4] = translationScale;
        optimizerScales[5] = translationScale;

        optimizer-&gt;SetScales( optimizerScales );

        optimizer-&gt;SetMaximumStepLength( 0.2000  ); 
        optimizer-&gt;SetMinimumStepLength( 0.0001 );

        optimizer-&gt;SetNumberOfIterations( 200 );

        CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
        optimizer-&gt;AddObserver( itk::IterationEvent(), observer );

        try 
                { 
                registration-&gt;StartRegistration(); 
                } 
        catch( itk::ExceptionObject &amp; err ) 
                { 
                std::cerr &lt;&lt; "ExceptionObject caught !" &lt;&lt; std::endl; 
                std::cerr &lt;&lt; err &lt;&lt; std::endl; 
                return EXIT_FAILURE;
                } 
          
        OptimizerType::ParametersType finalParameters = 
                                                registration-&gt;GetLastTransformParameters();

        const double versorX              = finalParameters[0];
        const double versorY              = finalParameters[1];
        const double versorZ              = finalParameters[2];
        const double finalTranslationX    = finalParameters[3];
        const double finalTranslationY    = finalParameters[4];
        const double finalTranslationZ    = finalParameters[5];

        const unsigned int numberOfIterations = optimizer-&gt;GetCurrentIteration();

        const double bestValue = optimizer-&gt;GetValue();

        transform-&gt;SetParameters( finalParameters );

        TransformType::MatrixType matrix = transform-&gt;GetRotationMatrix();
        TransformType::OffsetType offset = transform-&gt;GetOffset();

        typedef itk::ResampleImageFilter&lt; 
                                                                MovingImageType, 
                                                                FixedImageType &gt;    ResampleFilterType;

        TransformType::Pointer finalTransform = TransformType::New();

        finalTransform-&gt;SetCenter( transform-&gt;GetCenter() );

        finalTransform-&gt;SetParameters( finalParameters );

        ResampleFilterType::Pointer resampler = ResampleFilterType::New();

        resampler-&gt;SetTransform( finalTransform );
        resampler-&gt;SetInput( movingImage );

        

        resampler-&gt;SetSize(    fixedImage-&gt;GetLargestPossibleRegion().GetSize() );
        resampler-&gt;SetOutputOrigin(  fixedImage-&gt;GetOrigin() );
        resampler-&gt;SetOutputSpacing( fixedImage-&gt;GetSpacing() );
        resampler-&gt;SetOutputDirection( fixedImage-&gt;GetDirection() );
        resampler-&gt;SetDefaultPixelValue( 0 );
        //resampler-&gt;SetDefaultPixelValue( 100 );
        
        movingImage = resampler-&gt;GetOutput();
        resampler-&gt;Update();

        // give back the registered image
        typedef itk::ImageRegionConstIterator&lt; MovingImageType &gt; IteratorType;
        IteratorType it( movingImage, region );
        it.GoToBegin();
        int k=0;
        while(! it.IsAtEnd()){
                pixdata2[k] = (short) it.Get();
                k++;
                ++it;
        }

        return EXIT_SUCCESS;
        return 0;
};


</i>&gt;<i> Thanks in advance for your help
Gael</i><i>
</i>&gt;<i> 
</i></pre>
      <br>
      <br>
      <pre class="moz-signature" cols="72">
<a class="moz-txt-link-abbreviated" href="mailto:gael.pentang@med.uni-duesseldorf.de"></a></pre>
    </div>
    <pre class="moz-signature" cols="72">-- 
M.Sc. Comp. Eng. Gael Pentang
Research Assistent
University  Dusseldorf
Medical Faculty
Department of Diagnostic and Interventional Radiology
Moorenstrasse 5
D-40225 Dusseldorf
Germany
Tel.: +49 211 8117430
Mail: <a class="moz-txt-link-abbreviated" href="mailto:gael.pentang@med.uni-duesseldorf.de">gael.pentang@med.uni-duesseldorf.de</a></pre>
  </body>
</html>