]> Creatis software - clitk.git/blob - registration/clitkAffineRegistrationGenericFilter.cxx
Remove ITK3 and ITK4.2 tests and dependencies
[clitk.git] / registration / clitkAffineRegistrationGenericFilter.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18
19 #ifndef CLITKAFFINEREGISTRATIONGENERICFILTER_CXX
20 #define CLITKAFFINEREGISTRATIONGENERICFILTER_CXX
21
22 #include "clitkAffineRegistrationGenericFilter.h"
23
24 namespace clitk
25 {
26 //==============================================================================
27 //Creating an observer class that allows us to monitor the registration
28 //================================================================================
29 class CommandIterationUpdate : public itk::Command
30 {
31 public:
32   typedef  CommandIterationUpdate   Self;
33   typedef  itk::Command             Superclass;
34   typedef  itk::SmartPointer<Self>  Pointer;
35   itkNewMacro( Self );
36 protected:
37   CommandIterationUpdate() {};
38 public:
39   typedef   clitk::GenericOptimizer<args_info_clitkAffineRegistration>     OptimizerType;
40   typedef   const OptimizerType   *           OptimizerPointer;
41
42   // Set the generic optimizer
43   void SetOptimizer(OptimizerPointer o) {
44     m_Optimizer=o;
45   }
46
47   // Execute
48   void Execute(itk::Object *caller, const itk::EventObject & event) {
49     Execute( (const itk::Object *)caller, event);
50   }
51
52   void Execute(const itk::Object * object, const itk::EventObject & event) {
53     if ( !(itk::IterationEvent().CheckEvent( &event )) ) {
54       return;
55     }
56
57     m_Optimizer->OutputIterationInfo();
58   }
59
60   OptimizerPointer m_Optimizer;
61 };
62 //==================================================================================================================================//
63 //Constructor
64 //===================================================================================================================================//
65
66 AffineRegistrationGenericFilter::AffineRegistrationGenericFilter():
67     ImageToImageGenericFilter<Self>("Register")
68
69 {
70   InitializeImageType<2>();
71   InitializeImageType<3>();
72   m_Verbose=true;
73 }
74 //==========================================================================================================//
75 //============================================================================================================//
76 //--------------------------------------------------------------------
77 template<unsigned int Dim>
78 void AffineRegistrationGenericFilter::InitializeImageType()
79 {
80   ADD_DEFAULT_IMAGE_TYPES(Dim);
81 }
82 //--------------------------------------------------------------------
83
84
85 //==============================================================================
86 //Creating an observer class that allows us to change parameters at subsequent levels
87 //==============================================================================
88 template <typename TRegistration>
89 class RegistrationInterfaceCommand : public itk::Command
90 {
91 public:
92   typedef  RegistrationInterfaceCommand   Self;
93   typedef  itk::Command             Superclass;
94   typedef itk::SmartPointer<Self>  Pointer;
95   itkNewMacro( Self );
96 protected:
97   RegistrationInterfaceCommand() {};
98 public:
99
100   // Registration
101   typedef   TRegistration                              RegistrationType;
102   typedef   RegistrationType *                         RegistrationPointer;
103
104   // Metric
105   typedef typename RegistrationType::FixedImageType    InternalImageType;
106   typedef clitk::GenericMetric<args_info_clitkAffineRegistration, InternalImageType, InternalImageType> GenericMetricType;
107
108   // Two arguments are passed to the Execute() method: the first
109   // is the pointer to the object which invoked the event and the
110   // second is the event that was invoked.
111   void Execute(itk::Object * object, const itk::EventObject & event) {
112     if ( !(itk::IterationEvent().CheckEvent( &event )) ) {
113       return;
114     }
115
116     // Get the levels
117     RegistrationPointer registration = dynamic_cast<RegistrationPointer>( object );
118     unsigned int numberOfLevels=registration->GetNumberOfLevels();
119     unsigned int currentLevel=registration->GetCurrentLevel()+1;
120
121     // Output the levels
122     std::cout<<std::endl;
123     std::cout<<"========================================"<<std::endl;
124     std::cout<<"Starting resolution level "<<currentLevel<<" of "<<numberOfLevels<<"..."<<std::endl;
125     std::cout<<"========================================"<<std::endl;
126     std::cout<<std::endl;
127
128     // Higher level?
129     if (currentLevel>1) {
130       // Reinitialize the metric (!= number of samples)
131       typename GenericMetricType::Pointer genericMetric= GenericMetricType::New();
132       genericMetric->SetArgsInfo(m_ArgsInfo);
133       genericMetric->SetFixedImage(registration->GetFixedImagePyramid()->GetOutput(registration->GetCurrentLevel()));
134       if (m_ArgsInfo.referenceMask_given)  genericMetric->SetFixedImageMask(registration->GetMetric()->GetFixedImageMask());
135       typedef itk::ImageToImageMetric< InternalImageType, InternalImageType >  MetricType;
136       typename  MetricType::Pointer metric=genericMetric->GetMetricPointer();
137       registration->SetMetric(metric);
138     }
139   }
140
141   void Execute(const itk::Object * , const itk::EventObject & ) {
142     return;
143   }
144
145  void SetArgsInfo(args_info_clitkAffineRegistration a) {
146     m_ArgsInfo=a;
147   }
148   args_info_clitkAffineRegistration m_ArgsInfo;
149 };
150
151 //==============================================================================================//
152 // ArgsInfo
153 //==============================================================================================//
154 void AffineRegistrationGenericFilter::SetArgsInfo(const args_info_clitkAffineRegistration & a)
155 {
156   m_ArgsInfo=a;
157   if (m_ArgsInfo.reference_given) AddInputFilename(m_ArgsInfo.reference_arg);
158
159   if (m_ArgsInfo.target_given) {
160     AddInputFilename(m_ArgsInfo.target_arg);
161   }
162
163   if (m_ArgsInfo.output_given) SetOutputFilename(m_ArgsInfo.output_arg);
164 }
165 //==============================================================================
166 // Update with the number of dimensions and pixeltype
167 //==============================================================================
168 template<class InputImageType>
169 void AffineRegistrationGenericFilter::UpdateWithInputImageType()
170 {
171   //=============================================================================
172   //Input
173   //=============================================================================
174
175   typedef typename  InputImageType::PixelType PixelType;
176 //typedef typename InputImageType::ImageDimension Dimension;
177
178   bool threadsGiven=m_ArgsInfo.threads_given;
179   int threads=m_ArgsInfo.threads_arg;
180
181   //Coordinate Representation
182   typedef double TCoordRep;
183
184
185   typename InputImageType::Pointer fixedImage = this->template GetInput<InputImageType>(0);
186
187   typename InputImageType::Pointer inputFixedImage = this->template GetInput<InputImageType>(0);
188
189   // typedef input2
190   typename InputImageType::Pointer movingImage = this->template GetInput<InputImageType>(1);
191
192   typename InputImageType::Pointer inputMovingImage = this->template GetInput<InputImageType>(1);
193
194
195
196   //The pixeltype of the fixed image will be used for output
197   typedef itk::Image< PixelType, InputImageType::ImageDimension > FixedImageType;
198
199   //Whatever the pixel type, internally we work with an image represented in float
200   typedef typename  InputImageType::PixelType  InternalPixelType;
201   typedef itk::Image< PixelType, InputImageType::ImageDimension > InternalImageType;
202
203
204   //Read in the reference/fixed image
205 //  typedef itk::ImageFileReader< InternalImageType > ReaderType;
206 //  typename ReaderType::Pointer  fixedImageReader  = ReaderType::New();
207 //  fixedImageReader->SetFileName( m_ArgsInfo.reference_arg);
208
209
210   //Read in the object/moving image
211 //  typename ReaderType::Pointer movingImageReader = ReaderType::New();
212 //  movingImageReader->SetFileName( m_ArgsInfo.target_arg );
213   if (m_Verbose) std::cout<<"Reading images..."<<std::endl;
214 //  fixedImageReader->Update();
215 //  movingImageReader->Update();
216
217   if (m_Verbose) std::cout  << "Reading images... " << std::endl;
218
219   //we connect pointers to these internal images
220  // typedef typename  fixedImageReader fixedImage;
221  // typedef typename  movingImageReader movingImage;
222
223   //We keep the images used for input for possible output
224 // typedef typename   fixedImageReader inputFixedImage;
225 // typedef typename  movingImageReader inputMovingImage;
226
227
228   //============================================================================
229   // Preprocessing
230   //============================================================================
231
232   //If given, the intensities of both images are first normalized to a zero mean and SD of 1
233   // (usefull for MI, not necessary for Mattes' MI but performed anyway for the ouput)
234   if ( m_ArgsInfo.normalize_flag ) {
235     typedef itk::NormalizeImageFilter< InternalImageType,InternalImageType >  NormalizeFilterType;
236
237     typename  NormalizeFilterType::Pointer  fixedNormalizeFilter = NormalizeFilterType::New();
238     typename  NormalizeFilterType::Pointer  movingNormalizeFilter = NormalizeFilterType::New();
239
240     fixedNormalizeFilter->SetInput( fixedImage );
241     movingNormalizeFilter->SetInput( movingImage );
242
243     fixedNormalizeFilter->Update();
244     movingNormalizeFilter->Update();
245
246     //We keep the images used for input for possible output
247     inputFixedImage= fixedNormalizeFilter->GetOutput();
248     inputMovingImage= movingNormalizeFilter->GetOutput();
249
250     //the pointers are reconnected for further output
251     fixedImage=fixedNormalizeFilter->GetOutput();
252     movingImage=movingNormalizeFilter->GetOutput();
253
254     if (m_Verbose)  std::cout <<  "Normalizing image intensities to zero mean and SD of 1..." << std::endl;
255   }
256
257
258   //If given, the images are blurred before processing
259   if ( m_ArgsInfo.blur_arg!= 0) {
260     typedef itk::DiscreteGaussianImageFilter<InternalImageType,InternalImageType> GaussianFilterType;
261     typename GaussianFilterType::Pointer fixedSmoother = GaussianFilterType::New();
262     typename GaussianFilterType::Pointer movingSmoother = GaussianFilterType::New();
263     fixedSmoother->SetVariance( m_ArgsInfo.blur_arg );
264     movingSmoother->SetVariance(m_ArgsInfo.blur_arg );
265
266     fixedSmoother->SetInput( fixedImage );
267     movingSmoother->SetInput( movingImage );
268
269     fixedSmoother->Update();
270     movingSmoother->Update();
271
272     fixedImage=fixedSmoother->GetOutput();
273     movingImage=movingSmoother->GetOutput();
274
275     if (m_Verbose)  std::cout <<  "Blurring images with a Gaussian with standard deviation of " << m_ArgsInfo.blur_arg <<"..." << std::endl;
276   }
277
278
279   //============================================================================
280   // Setting up the moving image in a reference system
281   //============================================================================
282   const itk::Vector<double, InputImageType::ImageDimension> movingResolution = movingImage->GetSpacing();
283   typename InternalImageType::RegionType movingRegion = movingImage->GetLargestPossibleRegion();
284   typename InternalImageType::RegionType::SizeType  movingSize = movingRegion.GetSize();
285
286   // Print the parameters of the moving image
287   if (m_Verbose) {
288     std::cout << "Object or Moving image:"<<std::endl;
289     std::cout << "Size: " << movingSize[0] << ", " << movingSize[1];
290     if (InputImageType::ImageDimension==3) std::cout<<", " << movingSize[2];
291     std::cout << std::endl;
292
293     std::cout<< "Resolution: "<< movingResolution[0] << ", " << movingResolution[1];
294     if (InputImageType::ImageDimension==3) std::cout<< ", " << movingResolution[2];
295     std::cout << std::endl;
296   }
297
298
299   //============================================================================
300   // Setting up the fixed image in a reference system
301   //============================================================================
302   const itk::Vector<double, InputImageType::ImageDimension> fixedResolution = fixedImage->GetSpacing();
303   typename InternalImageType::RegionType fixedRegion = fixedImage->GetLargestPossibleRegion();
304   typename InternalImageType::RegionType::SizeType fixedSize = fixedRegion.GetSize();
305
306   // Print the parameters of the moving image and the transform
307   if (m_Verbose) {
308     std::cout << "Target or Moving image:"<<std::endl;
309     std::cout << "Size: " << fixedSize[0] << ", " << fixedSize[1];
310     if (InputImageType::ImageDimension==3) std::cout<<", " << fixedSize[2];
311     std::cout << std::endl;
312
313     std::cout<< "Resolution: "<< fixedResolution[0] << ", " << fixedResolution[1];
314     if (InputImageType::ImageDimension==3) std::cout<< ", " << fixedResolution[2];
315     std::cout << std::endl;
316   }
317
318
319
320   //===========================================================================
321   // If given, we connect a mask to reference or target
322   //============================================================================
323   typedef itk::ImageMaskSpatialObject<  InputImageType::ImageDimension >   MaskType;
324   typename MaskType::Pointer  fixedMask=NULL;
325   if (m_ArgsInfo.referenceMask_given) {
326     fixedMask= MaskType::New();
327     typedef itk::Image< unsigned char, InputImageType::ImageDimension >   ImageMaskType;
328     typedef itk::ImageFileReader< ImageMaskType >    MaskReaderType;
329     typename MaskReaderType::Pointer  maskReader = MaskReaderType::New();
330     maskReader->SetFileName(m_ArgsInfo.referenceMask_arg);
331     try {
332       maskReader->Update();
333     } catch ( itk::ExceptionObject & err ) {
334       std::cerr << "ExceptionObject caught while reading mask !" << std::endl;
335       std::cerr << err << std::endl;
336       return;
337     }
338     if (m_Verbose)std::cout <<"Reference image mask was read..." <<std::endl;
339
340     // Set the image to the spatialObject
341     fixedMask->SetImage( maskReader->GetOutput() );
342   }
343
344   typedef itk::ImageMaskSpatialObject<  InputImageType::ImageDimension >   MaskType;
345   typename MaskType::Pointer  movingMask=NULL;
346   if (m_ArgsInfo.targetMask_given) {
347     movingMask= MaskType::New();
348     typedef itk::Image< unsigned char, InputImageType::ImageDimension >   ImageMaskType;
349     typedef itk::ImageFileReader< ImageMaskType >    MaskReaderType;
350     typename MaskReaderType::Pointer  maskReader = MaskReaderType::New();
351     maskReader->SetFileName(m_ArgsInfo.targetMask_arg);
352     try {
353       maskReader->Update();
354     } catch ( itk::ExceptionObject & err ) {
355       std::cerr << "ExceptionObject caught !" << std::endl;
356       std::cerr << err << std::endl;
357     }
358     if (m_Verbose)std::cout <<"Target image mask was read..." <<std::endl;
359
360     movingMask->SetImage( maskReader->GetOutput() );
361   }
362
363
364   //============================================================================
365   // The image pyramids
366   //============================================================================
367   typedef itk::RecursiveMultiResolutionPyramidImageFilter<InternalImageType,InternalImageType >  FixedImagePyramidType;
368   typedef itk::RecursiveMultiResolutionPyramidImageFilter<InternalImageType,InternalImageType >  MovingImagePyramidType;
369   typename FixedImagePyramidType::Pointer fixedImagePyramid = FixedImagePyramidType::New();
370   typename MovingImagePyramidType::Pointer movingImagePyramid = MovingImagePyramidType::New();
371   fixedImagePyramid->SetUseShrinkImageFilter(false);
372   fixedImagePyramid->SetInput(fixedImage);
373   fixedImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
374   movingImagePyramid->SetUseShrinkImageFilter(false);
375   movingImagePyramid->SetInput(movingImage);
376   movingImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
377   if (m_Verbose) std::cout<<"Creating the image pyramid..."<<std::endl;
378
379   fixedImagePyramid->Update();
380   movingImagePyramid->Update();
381
382
383
384   //============================================================================
385   // We retrieve the type of metric from the command line
386   //============================================================================
387   typedef clitk::GenericMetric<args_info_clitkAffineRegistration, InternalImageType, InternalImageType> GenericMetricType;
388   typename GenericMetricType::Pointer genericMetric=GenericMetricType::New();
389   genericMetric->SetArgsInfo(m_ArgsInfo);
390   genericMetric->SetFixedImage(fixedImagePyramid->GetOutput(0));
391   if (fixedMask) genericMetric->SetFixedImageMask(fixedMask);
392   typedef itk::ImageToImageMetric< InternalImageType, InternalImageType >  MetricType;
393   typename  MetricType::Pointer metric=genericMetric->GetMetricPointer();
394   if (movingMask) metric->SetMovingImageMask(movingMask);
395
396   if (threadsGiven) metric->SetNumberOfThreads( threads );
397
398   //============================================================================
399   // Initialize using image moments.
400   //============================================================================
401   if (m_ArgsInfo.moment_flag) {
402     typedef itk::ImageMomentsCalculator< InternalImageType > CalculatorType;
403     typename CalculatorType::Pointer fixedCalculator= CalculatorType::New();
404
405     typename InternalImageType::Pointer fixedThresh;
406     if (m_ArgsInfo.intThreshold_given) {
407       typedef itk::ThresholdImageFilter<InternalImageType> ThresholdImageFilterType;
408       typename ThresholdImageFilterType::Pointer thresholder = ThresholdImageFilterType::New();
409       thresholder->SetInput(fixedImage);
410       thresholder->SetLower(m_ArgsInfo.intThreshold_arg);
411       thresholder->Update();
412       fixedThresh=thresholder->GetOutput();
413     } else fixedThresh=fixedImage;
414
415     fixedCalculator->SetImage(fixedThresh);
416     fixedCalculator->Compute();
417     Vector<double, InputImageType::ImageDimension> fixedCenter=fixedCalculator->GetCenterOfGravity();
418     if (m_Verbose)std::cout<<"The fixed center of gravity is "<<fixedCenter<<"..."<<std::endl;
419
420     typedef itk::ImageMomentsCalculator< InternalImageType > CalculatorType;
421     typename CalculatorType::Pointer movingCalculator= CalculatorType::New();
422
423     typename InternalImageType::Pointer movingThresh;
424     if (m_ArgsInfo.intThreshold_given) {
425       typedef itk::ThresholdImageFilter<InternalImageType> ThresholdImageFilterType;
426       typename ThresholdImageFilterType::Pointer thresholder = ThresholdImageFilterType::New();
427       thresholder->SetInput(movingImage);
428       thresholder->SetLower(m_ArgsInfo.intThreshold_arg);
429       thresholder->Update();
430       movingThresh=thresholder->GetOutput();
431     } else movingThresh=movingImage;
432
433     movingCalculator->SetImage(movingThresh);
434     movingCalculator->Compute();
435     Vector<double, InputImageType::ImageDimension> movingCenter=movingCalculator->GetCenterOfGravity();
436     if (m_Verbose)std::cout<<"The moving center of gravity is "<<movingCenter<<"..."<<std::endl;
437
438     Vector<double, InputImageType::ImageDimension> shift= movingCenter-fixedCenter;
439     if (m_Verbose)std::cout<<"The initial shift applied is "<<shift<<"..."<<std::endl;
440
441     m_ArgsInfo.transX_arg= shift [0];
442     m_ArgsInfo.transY_arg= shift [1];
443     if (InputImageType::ImageDimension==3) m_ArgsInfo.transZ_arg=shift [2];
444   }
445
446   //============================================================================
447   // Transform
448   //============================================================================
449   typedef clitk::GenericAffineTransform<args_info_clitkAffineRegistration, TCoordRep, InputImageType::ImageDimension > GenericAffineTransformType;
450   typename GenericAffineTransformType::Pointer genericAffineTransform = GenericAffineTransformType::New();
451   genericAffineTransform->SetArgsInfo(m_ArgsInfo);
452   typedef itk::Transform< double, InputImageType::ImageDimension, InputImageType::ImageDimension > TransformType;
453   typename TransformType::Pointer transform = genericAffineTransform->GetTransform();
454    std::cout<<m_ArgsInfo.transform_arg<<std::endl;
455
456
457   //=======================================================
458   // Interpolator
459   //=======================================================
460   std::cout<<"setting Interpolator..."<<std::endl;
461   typedef clitk::GenericInterpolator<args_info_clitkAffineRegistration, InternalImageType,TCoordRep > GenericInterpolatorType;
462   typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
463   genericInterpolator->SetArgsInfo(m_ArgsInfo);
464   typedef itk::InterpolateImageFunction< InternalImageType, TCoordRep >  InterpolatorType;
465   typename  InterpolatorType::Pointer interpolator=genericInterpolator->GetInterpolatorPointer();
466   std::cout<<"end of interpolator"<<std::endl;
467
468   //============================================================================
469   // Optimizer
470   //============================================================================
471   typedef clitk::GenericOptimizer<args_info_clitkAffineRegistration> GenericOptimizerType;
472   unsigned int nParam = transform->GetNumberOfParameters();
473   typename GenericOptimizerType::Pointer genericOptimizer=GenericOptimizerType::New();
474   genericOptimizer->SetArgsInfo(m_ArgsInfo);
475   genericOptimizer->SetOutputIteration(m_Verbose);
476   genericOptimizer->SetOutputPosition(m_Verbose);
477   genericOptimizer->SetOutputValue(m_Verbose);
478   genericOptimizer->SetOutputGradient(m_ArgsInfo.gradient_flag);
479   genericOptimizer->SetMaximize(genericMetric->GetMaximize());
480   genericOptimizer->SetNumberOfParameters(nParam);
481   typedef itk::SingleValuedNonLinearOptimizer OptimizerType;
482   OptimizerType::Pointer optimizer=genericOptimizer->GetOptimizerPointer();
483
484   // Scales
485   itk::Optimizer::ScalesType scales( nParam );
486   for (unsigned int i=nParam-InputImageType::ImageDimension; i<nParam; i++) //Translations
487     scales[i] = m_ArgsInfo.tWeight_arg;
488   for (unsigned int i=0; i<nParam-InputImageType::ImageDimension; i++)      //Rest
489     scales[i] = m_ArgsInfo.rWeight_arg*180./M_PI;
490   optimizer->SetScales(scales);
491   //============================================================================
492   // Multiresolution registration
493   //============================================================================
494   std::cout<<"start MultiResolution..."<<std::endl;
495   typedef itk::MultiResolutionImageRegistrationMethod< InternalImageType,InternalImageType >  RegistrationType;
496   typename  RegistrationType::Pointer registration = RegistrationType::New();
497   registration->SetFixedImage( fixedImage  );
498   registration->SetFixedImageRegion(fixedImage->GetLargestPossibleRegion());
499   registration->SetMovingImage(  movingImage );
500   registration->SetFixedImagePyramid( fixedImagePyramid );
501   registration->SetMovingImagePyramid( movingImagePyramid );
502   registration->SetTransform( transform );
503   registration->SetInitialTransformParameters( transform->GetParameters() );
504   registration->SetInterpolator( interpolator );
505   registration->SetMetric(metric);
506   registration->SetOptimizer(optimizer);
507   registration->SetNumberOfLevels( m_ArgsInfo.levels_arg );
508   if (m_Verbose) std::cout << "Setting "<< m_ArgsInfo.levels_arg <<" resolution levels..." << std::endl;
509   if (m_Verbose) std::cout << "Initial Transform: "<< registration->GetInitialTransformParameters()<<std::endl;
510
511   //============================================================================
512   // Connecting the commander to the registration to monitor it
513   //============================================================================
514   if (m_Verbose) {
515
516     // Output iteration info
517     CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
518     observer->SetOptimizer(genericOptimizer);
519     optimizer->AddObserver( itk::IterationEvent(), observer );
520
521
522     // Output level info
523     typedef RegistrationInterfaceCommand<RegistrationType> CommandType;
524     typename CommandType::Pointer command = CommandType::New();
525     command->SetArgsInfo(m_ArgsInfo);
526     registration->AddObserver( itk::IterationEvent(), command );
527
528   }
529
530
531   //============================================================================
532   // Finally we can start the registration with the given amount of multiresolution levels
533   //============================================================================
534   if (m_Verbose) std::cout << "Starting the registration now..." << std::endl;
535
536   try {
537     registration->Update();
538   } catch ( itk::ExceptionObject & err ) {
539     std::cerr << "ExceptionObject caught !" << std::endl;
540     std::cerr << err << std::endl;
541   }
542
543
544   //============================================================================
545   // Processing the result of the registration
546   //============================================================================
547   OptimizerType::ParametersType finalParameters = registration->GetLastTransformParameters();
548   std::cout<< "Result : " <<std::setprecision(12)<<std::endl;
549
550   for (unsigned int i=nParam-InputImageType::ImageDimension; i<nParam; i++) //Translations
551     std::cout << " Translation " << i << " = " << finalParameters[i];
552   for (unsigned int i=0; i<nParam-InputImageType::ImageDimension; i++)      //Rest
553     std::cout << " Other parameter " << i << " = " << finalParameters[i];
554
555   itk::Matrix<double,InputImageType::ImageDimension+1,InputImageType::ImageDimension+1> matrix;
556   if (m_ArgsInfo.transform_arg == 3) {
557     for (unsigned int i=0; i<InputImageType::ImageDimension; i++) {
558       matrix[i][3] =  finalParameters[nParam-InputImageType::ImageDimension+i];
559       for (unsigned int j=0; j<InputImageType::ImageDimension; j++) {
560         matrix[i][j] = finalParameters[i*3+j];
561       }
562       matrix[3][3] = 1.0;
563     }
564   } else {
565     matrix = clitk::GetBackwardAffineMatrix<InputImageType::ImageDimension>(finalParameters);
566    std::cout<<"outside GetBackWardAffineMatrix...."<<std::endl;
567 }
568
569   std::cout << " Affine transform matrix =" << std::endl;
570   std::cout << matrix <<std::setprecision(6)<< std::endl;
571   std::cout << " End of Registration" << std::endl;
572   // Write matrix to a file
573   if (m_ArgsInfo.matrix_given) {
574     std::ofstream mFile;
575     mFile.open(m_ArgsInfo.matrix_arg);
576     mFile<<std::setprecision(12)<<matrix<< std::setprecision(6)<<std::endl;
577     mFile.close();
578   }
579
580   //============================================================================
581   // Prepare the resampling filter in order to transform the moving image.
582   //============================================================================
583  // if (m_ArgsInfo.output_given || m_ArgsInfo.checker_after_given || m_ArgsInfo.after_given ) {
584     transform->SetParameters( finalParameters );
585     typedef itk::ResampleImageFilter< InternalImageType,InternalImageType >    ResampleFilterType;
586     typename    ResampleFilterType::Pointer resampler = ResampleFilterType::New();
587
588     resampler->SetTransform( transform );
589     resampler->SetInput( movingImage );
590     resampler->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() );
591     resampler->SetOutputOrigin(  fixedImage->GetOrigin() );
592     resampler->SetOutputSpacing( fixedImage->GetSpacing() );
593     resampler->SetDefaultPixelValue( 0 );
594     resampler->Update();
595     //Output?
596    // if (m_ArgsInfo.output_given) {
597       //We write an output in the same pixeltype then the input
598       /*typedef itk::ImageFileWriter< FixedImageType >  WriterType;
599       typename WriterType::Pointer outputWriter =  WriterType::New();
600       outputWriter->SetFileName(m_ArgsInfo.output_arg );
601       outputWriter->SetInput( resampler->GetOutput()   );
602       outputWriter->Update();*/
603      typedef InternalImageType OutputImageType;
604      typename OutputImageType::Pointer outputImage = resampler->GetOutput();
605      std::cout<<"Writing Output....."<<std::endl;
606      this->template SetNextOutput<OutputImageType>(outputImage);
607   //  }
608
609
610     //============================================================================
611     // Checker after?
612     //============================================================================
613     if (m_ArgsInfo.checker_after_given) {
614       //To display correctly the checkerboard image, the intensities must lie in the same range (normalized)
615       //We write the image in the internal image type
616       typedef itk::ResampleImageFilter< InternalImageType,InternalImageType >    ResampleFilterType;
617       typename    ResampleFilterType::Pointer internalResampler = ResampleFilterType::New();
618       internalResampler->SetTransform( transform );
619       internalResampler->SetInput( inputMovingImage );
620       internalResampler->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() );
621       internalResampler->SetOutputOrigin(  fixedImage->GetOrigin() );
622       internalResampler->SetOutputSpacing( fixedImage->GetSpacing() );
623       internalResampler->SetDefaultPixelValue( 0 );
624
625       //We pass the normalized images to the checker filter
626       typedef itk::CheckerBoardImageFilter< InternalImageType > CheckerBoardFilterType;
627       typename CheckerBoardFilterType::Pointer checkerFilter= CheckerBoardFilterType::New();
628
629       checkerFilter->SetInput1(inputFixedImage);
630       checkerFilter->SetInput2(internalResampler->GetOutput());
631       typedef itk::ImageFileWriter< InternalImageType >  InternalWriterType;
632       typename  InternalWriterType::Pointer checkerWriter =  InternalWriterType::New();
633       checkerWriter->SetFileName(m_ArgsInfo.checker_after_arg);
634       checkerWriter->SetInput( checkerFilter->GetOutput() );
635       checkerWriter->Update();
636     }
637
638
639     //============================================================================
640     // Checker before?
641     //============================================================================
642     if (m_ArgsInfo.checker_before_given) {
643       //To display correctly the checkerboard image, the intensities must lie in the same range (normalized)
644       //We write the image in the internal image type
645       //We pass the normalized images to the checker filter
646       typedef itk::CheckerBoardImageFilter< InternalImageType > CheckerBoardFilterType;
647       typename CheckerBoardFilterType::Pointer checkerFilter= CheckerBoardFilterType::New();
648
649       checkerFilter->SetInput1(inputFixedImage);
650       checkerFilter->SetInput2(inputMovingImage);
651       typedef itk::ImageFileWriter< InternalImageType >  InternalWriterType;
652       typename  InternalWriterType::Pointer checkerWriter =  InternalWriterType::New();
653       checkerWriter->SetFileName(m_ArgsInfo.checker_before_arg);
654       checkerWriter->SetInput( checkerFilter->GetOutput() );
655       checkerWriter->Update();
656     }
657
658
659     //============================================================================
660     // Difference After?
661     //============================================================================
662     if (m_ArgsInfo.after_given) {
663       typedef itk::SubtractImageFilter< InternalImageType, FixedImageType,FixedImageType > DifferenceImageFilterType;
664       typename DifferenceImageFilterType::Pointer differenceAfterFilter= DifferenceImageFilterType::New();
665
666       differenceAfterFilter->SetInput1(fixedImage);
667       differenceAfterFilter->SetInput2(resampler->GetOutput());
668
669       // Prepare a writer to write the difference image
670       typedef itk::ImageFileWriter< FixedImageType >  WriterType;
671       typename   WriterType::Pointer     differenceAfterWriter =  WriterType::New();
672       differenceAfterWriter->SetFileName(m_ArgsInfo.after_arg );
673       differenceAfterWriter->SetInput( differenceAfterFilter->GetOutput()   );
674       differenceAfterWriter->Update();
675     }
676 //  }
677
678   //============================================================================
679   // Difference Before?
680   //============================================================================
681   if (m_ArgsInfo.before_given) {
682     typedef itk::CastImageFilter< InternalImageType,FixedImageType > CastFilterType;
683     typename    CastFilterType::Pointer  caster =  CastFilterType::New();
684     caster->SetInput( movingImage );
685
686     typedef itk::SubtractImageFilter< InternalImageType, FixedImageType, FixedImageType > DifferenceImageFilterType;
687     typename DifferenceImageFilterType::Pointer differenceBeforeFilter= DifferenceImageFilterType::New();
688
689
690     differenceBeforeFilter->SetInput1(fixedImage);
691     differenceBeforeFilter->SetInput2(caster->GetOutput());
692
693     // Prepare a writer to write the difference image
694     typedef itk::ImageFileWriter< FixedImageType >  WriterType;
695     typename WriterType::Pointer     differenceBeforeWriter =  WriterType::New();
696     differenceBeforeWriter->SetFileName(m_ArgsInfo.before_arg);
697     differenceBeforeWriter->SetInput( differenceBeforeFilter->GetOutput()   );
698     differenceBeforeWriter->Update();
699   }
700
701 }
702
703 }
704 //====================================================================
705
706 #endif  //#define CLITKAFFINEREGISTRATIONCGENERICFILTER_CXX