1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
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
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.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
19 #ifndef CLITKAFFINEREGISTRATIONGENERICFILTER_CXX
20 #define CLITKAFFINEREGISTRATIONGENERICFILTER_CXX
22 #include "clitkAffineRegistrationGenericFilter.h"
25 #include "clitkCommon.h"
26 #include "clitkImageCommon.h"
27 #include "clitkAffineRegistration_ggo.h"
28 #include "clitkImageArithm_ggo.h"
29 #include "clitkCorrelationRatioImageToImageMetric.h"
30 #include "clitkTransformUtilities.h"
31 #include "clitkGenericMetric.h"
32 #include "clitkGenericOptimizer.h"
33 #include "clitkGenericInterpolator.h"
34 #include "clitkGenericAffineTransform.h"
35 #include "clitkImageToImageGenericFilter.h"
39 #include <itkMultiResolutionImageRegistrationMethod.h>
40 #include <itkMultiResolutionPyramidImageFilter.h>
41 #include <itkImageToImageMetric.h>
42 #include <itkEuler2DTransform.h>
43 #include <itkCenteredEuler3DTransform.h>
45 #include <itkResampleImageFilter.h>
46 #include <itkCastImageFilter.h>
47 #include <itkNormalizeImageFilter.h>
48 #include <itkDiscreteGaussianImageFilter.h>
49 #include <itkImageMaskSpatialObject.h>
50 #include <itkCommand.h>
51 #include <itkCheckerBoardImageFilter.h>
52 #include <itkSubtractImageFilter.h>
53 #include <itkLightObject.h>
54 #include <itkImageMomentsCalculator.h>
55 #include <itkThresholdImageFilter.h>
65 //==============================================================================
66 //Creating an observer class that allows us to monitor the registration
67 //================================================================================
68 class CommandIterationUpdate : public itk::Command
71 typedef CommandIterationUpdate Self;
72 typedef itk::Command Superclass;
73 typedef itk::SmartPointer<Self> Pointer;
76 CommandIterationUpdate() {};
78 typedef clitk::GenericOptimizer<args_info_clitkAffineRegistration> OptimizerType;
79 typedef const OptimizerType * OptimizerPointer;
81 // Set the generic optimizer
82 void SetOptimizer(OptimizerPointer o) {
87 void Execute(itk::Object *caller, const itk::EventObject & event) ITK_OVERRIDE {
88 Execute( (const itk::Object *)caller, event);
91 void Execute(const itk::Object * object, const itk::EventObject & event) ITK_OVERRIDE {
92 if ( !(itk::IterationEvent().CheckEvent( &event )) ) {
96 m_Optimizer->OutputIterationInfo();
99 OptimizerPointer m_Optimizer;
101 //==================================================================================================================================//
103 //===================================================================================================================================//
105 AffineRegistrationGenericFilter::AffineRegistrationGenericFilter():
106 ImageToImageGenericFilter<Self>("Register")
109 InitializeImageType<2>();
110 InitializeImageType<3>();
113 //==========================================================================================================//
114 //============================================================================================================//
115 //--------------------------------------------------------------------
116 template<unsigned int Dim>
117 void AffineRegistrationGenericFilter::InitializeImageType()
119 ADD_DEFAULT_IMAGE_TYPES(Dim);
121 //--------------------------------------------------------------------
124 //==============================================================================
125 //Creating an observer class that allows us to change parameters at subsequent levels
126 //==============================================================================
127 template <typename TRegistration>
128 class RegistrationInterfaceCommand : public itk::Command
131 typedef RegistrationInterfaceCommand Self;
132 typedef itk::Command Superclass;
133 typedef itk::SmartPointer<Self> Pointer;
136 RegistrationInterfaceCommand() {};
140 typedef TRegistration RegistrationType;
141 typedef RegistrationType * RegistrationPointer;
144 typedef typename RegistrationType::FixedImageType InternalImageType;
145 typedef clitk::GenericMetric<args_info_clitkAffineRegistration, InternalImageType, InternalImageType> GenericMetricType;
147 // Two arguments are passed to the Execute() method: the first
148 // is the pointer to the object which invoked the event and the
149 // second is the event that was invoked.
150 void Execute(itk::Object * object, const itk::EventObject & event) ITK_OVERRIDE {
151 if ( !(itk::IterationEvent().CheckEvent( &event )) ) {
156 RegistrationPointer registration = dynamic_cast<RegistrationPointer>( object );
157 unsigned int numberOfLevels=registration->GetNumberOfLevels();
158 unsigned int currentLevel=registration->GetCurrentLevel()+1;
161 std::cout<<std::endl;
162 std::cout<<"========================================"<<std::endl;
163 std::cout<<"Starting resolution level "<<currentLevel<<" of "<<numberOfLevels<<"..."<<std::endl;
164 std::cout<<"========================================"<<std::endl;
165 std::cout<<std::endl;
168 if (currentLevel>1) {
169 // Reinitialize the metric (!= number of samples)
170 typename GenericMetricType::Pointer genericMetric= GenericMetricType::New();
171 genericMetric->SetArgsInfo(m_ArgsInfo);
172 genericMetric->SetFixedImage(registration->GetFixedImagePyramid()->GetOutput(registration->GetCurrentLevel()));
173 if (m_ArgsInfo.referenceMask_given) genericMetric->SetFixedImageMask(registration->GetMetric()->GetFixedImageMask());
174 typedef itk::ImageToImageMetric< InternalImageType, InternalImageType > MetricType;
175 typename MetricType::Pointer metric=genericMetric->GetMetricPointer();
176 registration->SetMetric(metric);
180 void Execute(const itk::Object * , const itk::EventObject & ) ITK_OVERRIDE {
184 void SetArgsInfo(args_info_clitkAffineRegistration a) {
187 args_info_clitkAffineRegistration m_ArgsInfo;
190 //==============================================================================================//
192 //==============================================================================================//
193 void AffineRegistrationGenericFilter::SetArgsInfo(const args_info_clitkAffineRegistration & a)
196 if (m_ArgsInfo.reference_given) AddInputFilename(m_ArgsInfo.reference_arg);
198 if (m_ArgsInfo.target_given) {
199 AddInputFilename(m_ArgsInfo.target_arg);
202 if (m_ArgsInfo.output_given) SetOutputFilename(m_ArgsInfo.output_arg);
204 //==============================================================================
205 // Update with the number of dimensions and pixeltype
206 //==============================================================================
207 template<class InputImageType>
208 void AffineRegistrationGenericFilter::UpdateWithInputImageType()
210 //=============================================================================
212 //=============================================================================
214 typedef typename InputImageType::PixelType PixelType;
215 //typedef typename InputImageType::ImageDimension Dimension;
217 bool threadsGiven=m_ArgsInfo.threads_given;
218 int threads=m_ArgsInfo.threads_arg;
220 //Coordinate Representation
221 typedef double TCoordRep;
224 typename InputImageType::Pointer fixedImage = this->template GetInput<InputImageType>(0);
226 typename InputImageType::Pointer inputFixedImage = this->template GetInput<InputImageType>(0);
229 typename InputImageType::Pointer movingImage = this->template GetInput<InputImageType>(1);
231 typename InputImageType::Pointer inputMovingImage = this->template GetInput<InputImageType>(1);
235 //The pixeltype of the fixed image will be used for output
236 typedef itk::Image< PixelType, InputImageType::ImageDimension > FixedImageType;
238 //Whatever the pixel type, internally we work with an image represented in float
239 typedef typename InputImageType::PixelType InternalPixelType;
240 typedef itk::Image< PixelType, InputImageType::ImageDimension > InternalImageType;
243 //Read in the reference/fixed image
244 // typedef itk::ImageFileReader< InternalImageType > ReaderType;
245 // typename ReaderType::Pointer fixedImageReader = ReaderType::New();
246 // fixedImageReader->SetFileName( m_ArgsInfo.reference_arg);
249 //Read in the object/moving image
250 // typename ReaderType::Pointer movingImageReader = ReaderType::New();
251 // movingImageReader->SetFileName( m_ArgsInfo.target_arg );
252 if (m_Verbose) std::cout<<"Reading images..."<<std::endl;
253 // fixedImageReader->Update();
254 // movingImageReader->Update();
256 if (m_Verbose) std::cout << "Reading images... " << std::endl;
258 //we connect pointers to these internal images
259 // typedef typename fixedImageReader fixedImage;
260 // typedef typename movingImageReader movingImage;
262 //We keep the images used for input for possible output
263 // typedef typename fixedImageReader inputFixedImage;
264 // typedef typename movingImageReader inputMovingImage;
267 //============================================================================
269 //============================================================================
271 //If given, the intensities of both images are first normalized to a zero mean and SD of 1
272 // (usefull for MI, not necessary for Mattes' MI but performed anyway for the ouput)
273 if ( m_ArgsInfo.normalize_flag ) {
274 typedef itk::NormalizeImageFilter< InternalImageType,InternalImageType > NormalizeFilterType;
276 typename NormalizeFilterType::Pointer fixedNormalizeFilter = NormalizeFilterType::New();
277 typename NormalizeFilterType::Pointer movingNormalizeFilter = NormalizeFilterType::New();
279 fixedNormalizeFilter->SetInput( fixedImage );
280 movingNormalizeFilter->SetInput( movingImage );
282 fixedNormalizeFilter->Update();
283 movingNormalizeFilter->Update();
285 //We keep the images used for input for possible output
286 inputFixedImage= fixedNormalizeFilter->GetOutput();
287 inputMovingImage= movingNormalizeFilter->GetOutput();
289 //the pointers are reconnected for further output
290 fixedImage=fixedNormalizeFilter->GetOutput();
291 movingImage=movingNormalizeFilter->GetOutput();
293 if (m_Verbose) std::cout << "Normalizing image intensities to zero mean and SD of 1..." << std::endl;
297 //If given, the images are blurred before processing
298 if ( m_ArgsInfo.blur_arg!= 0) {
299 typedef itk::DiscreteGaussianImageFilter<InternalImageType,InternalImageType> GaussianFilterType;
300 typename GaussianFilterType::Pointer fixedSmoother = GaussianFilterType::New();
301 typename GaussianFilterType::Pointer movingSmoother = GaussianFilterType::New();
302 fixedSmoother->SetVariance( m_ArgsInfo.blur_arg );
303 movingSmoother->SetVariance(m_ArgsInfo.blur_arg );
305 fixedSmoother->SetInput( fixedImage );
306 movingSmoother->SetInput( movingImage );
308 fixedSmoother->Update();
309 movingSmoother->Update();
311 fixedImage=fixedSmoother->GetOutput();
312 movingImage=movingSmoother->GetOutput();
314 if (m_Verbose) std::cout << "Blurring images with a Gaussian with standard deviation of " << m_ArgsInfo.blur_arg <<"..." << std::endl;
318 //============================================================================
319 // Setting up the moving image in a reference system
320 //============================================================================
321 const itk::Vector<double, InputImageType::ImageDimension> movingResolution = movingImage->GetSpacing();
322 typename InternalImageType::RegionType movingRegion = movingImage->GetLargestPossibleRegion();
323 typename InternalImageType::RegionType::SizeType movingSize = movingRegion.GetSize();
325 // Print the parameters of the moving image
327 std::cout << "Object or Moving image:"<<std::endl;
328 std::cout << "Size: " << movingSize[0] << ", " << movingSize[1];
329 if (InputImageType::ImageDimension==3) std::cout<<", " << movingSize[2];
330 std::cout << std::endl;
332 std::cout<< "Resolution: "<< movingResolution[0] << ", " << movingResolution[1];
333 if (InputImageType::ImageDimension==3) std::cout<< ", " << movingResolution[2];
334 std::cout << std::endl;
338 //============================================================================
339 // Setting up the fixed image in a reference system
340 //============================================================================
341 const itk::Vector<double, InputImageType::ImageDimension> fixedResolution = fixedImage->GetSpacing();
342 typename InternalImageType::RegionType fixedRegion = fixedImage->GetLargestPossibleRegion();
343 typename InternalImageType::RegionType::SizeType fixedSize = fixedRegion.GetSize();
345 // Print the parameters of the moving image and the transform
347 std::cout << "Target or Moving image:"<<std::endl;
348 std::cout << "Size: " << fixedSize[0] << ", " << fixedSize[1];
349 if (InputImageType::ImageDimension==3) std::cout<<", " << fixedSize[2];
350 std::cout << std::endl;
352 std::cout<< "Resolution: "<< fixedResolution[0] << ", " << fixedResolution[1];
353 if (InputImageType::ImageDimension==3) std::cout<< ", " << fixedResolution[2];
354 std::cout << std::endl;
359 //===========================================================================
360 // If given, we connect a mask to reference or target
361 //============================================================================
362 typedef itk::ImageMaskSpatialObject< InputImageType::ImageDimension > MaskType;
363 typename MaskType::Pointer fixedMask=ITK_NULLPTR;
364 if (m_ArgsInfo.referenceMask_given) {
365 fixedMask= MaskType::New();
366 typedef itk::Image< unsigned char, InputImageType::ImageDimension > ImageMaskType;
367 typedef itk::ImageFileReader< ImageMaskType > MaskReaderType;
368 typename MaskReaderType::Pointer maskReader = MaskReaderType::New();
369 maskReader->SetFileName(m_ArgsInfo.referenceMask_arg);
371 maskReader->Update();
372 } catch ( itk::ExceptionObject & err ) {
373 std::cerr << "ExceptionObject caught while reading mask !" << std::endl;
374 std::cerr << err << std::endl;
377 if (m_Verbose)std::cout <<"Reference image mask was read..." <<std::endl;
379 // Set the image to the spatialObject
380 fixedMask->SetImage( maskReader->GetOutput() );
383 typedef itk::ImageMaskSpatialObject< InputImageType::ImageDimension > MaskType;
384 typename MaskType::Pointer movingMask=ITK_NULLPTR;
385 if (m_ArgsInfo.targetMask_given) {
386 movingMask= MaskType::New();
387 typedef itk::Image< unsigned char, InputImageType::ImageDimension > ImageMaskType;
388 typedef itk::ImageFileReader< ImageMaskType > MaskReaderType;
389 typename MaskReaderType::Pointer maskReader = MaskReaderType::New();
390 maskReader->SetFileName(m_ArgsInfo.targetMask_arg);
392 maskReader->Update();
393 } catch ( itk::ExceptionObject & err ) {
394 std::cerr << "ExceptionObject caught !" << std::endl;
395 std::cerr << err << std::endl;
397 if (m_Verbose)std::cout <<"Target image mask was read..." <<std::endl;
399 movingMask->SetImage( maskReader->GetOutput() );
403 //============================================================================
404 // The image pyramids
405 //============================================================================
406 typedef itk::RecursiveMultiResolutionPyramidImageFilter<InternalImageType,InternalImageType > FixedImagePyramidType;
407 typedef itk::RecursiveMultiResolutionPyramidImageFilter<InternalImageType,InternalImageType > MovingImagePyramidType;
408 typename FixedImagePyramidType::Pointer fixedImagePyramid = FixedImagePyramidType::New();
409 typename MovingImagePyramidType::Pointer movingImagePyramid = MovingImagePyramidType::New();
410 fixedImagePyramid->SetUseShrinkImageFilter(false);
411 fixedImagePyramid->SetInput(fixedImage);
412 fixedImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
413 movingImagePyramid->SetUseShrinkImageFilter(false);
414 movingImagePyramid->SetInput(movingImage);
415 movingImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
416 if (m_Verbose) std::cout<<"Creating the image pyramid..."<<std::endl;
418 fixedImagePyramid->Update();
419 movingImagePyramid->Update();
423 //============================================================================
424 // We retrieve the type of metric from the command line
425 //============================================================================
426 typedef clitk::GenericMetric<args_info_clitkAffineRegistration, InternalImageType, InternalImageType> GenericMetricType;
427 typename GenericMetricType::Pointer genericMetric=GenericMetricType::New();
428 genericMetric->SetArgsInfo(m_ArgsInfo);
429 genericMetric->SetFixedImage(fixedImagePyramid->GetOutput(0));
430 if (fixedMask) genericMetric->SetFixedImageMask(fixedMask);
431 typedef itk::ImageToImageMetric< InternalImageType, InternalImageType > MetricType;
432 typename MetricType::Pointer metric=genericMetric->GetMetricPointer();
433 if (movingMask) metric->SetMovingImageMask(movingMask);
436 #if ITK_VERSION_MAJOR <= 4
437 metric->SetNumberOfThreads( threads );
439 metric->SetNumberOfWorkUnits( threads );
443 //============================================================================
444 // Initialize using image moments.
445 //============================================================================
446 if (m_ArgsInfo.moment_flag) {
447 typedef itk::ImageMomentsCalculator< InternalImageType > CalculatorType;
448 typename CalculatorType::Pointer fixedCalculator= CalculatorType::New();
450 typename InternalImageType::Pointer fixedThresh;
451 if (m_ArgsInfo.intThreshold_given) {
452 typedef itk::ThresholdImageFilter<InternalImageType> ThresholdImageFilterType;
453 typename ThresholdImageFilterType::Pointer thresholder = ThresholdImageFilterType::New();
454 thresholder->SetInput(fixedImage);
455 thresholder->SetLower(m_ArgsInfo.intThreshold_arg);
456 thresholder->Update();
457 fixedThresh=thresholder->GetOutput();
458 } else fixedThresh=fixedImage;
460 fixedCalculator->SetImage(fixedThresh);
461 fixedCalculator->Compute();
462 Vector<double, InputImageType::ImageDimension> fixedCenter=fixedCalculator->GetCenterOfGravity();
463 if (m_Verbose)std::cout<<"The fixed center of gravity is "<<fixedCenter<<"..."<<std::endl;
465 typedef itk::ImageMomentsCalculator< InternalImageType > CalculatorType;
466 typename CalculatorType::Pointer movingCalculator= CalculatorType::New();
468 typename InternalImageType::Pointer movingThresh;
469 if (m_ArgsInfo.intThreshold_given) {
470 typedef itk::ThresholdImageFilter<InternalImageType> ThresholdImageFilterType;
471 typename ThresholdImageFilterType::Pointer thresholder = ThresholdImageFilterType::New();
472 thresholder->SetInput(movingImage);
473 thresholder->SetLower(m_ArgsInfo.intThreshold_arg);
474 thresholder->Update();
475 movingThresh=thresholder->GetOutput();
476 } else movingThresh=movingImage;
478 movingCalculator->SetImage(movingThresh);
479 movingCalculator->Compute();
480 Vector<double, InputImageType::ImageDimension> movingCenter=movingCalculator->GetCenterOfGravity();
481 if (m_Verbose)std::cout<<"The moving center of gravity is "<<movingCenter<<"..."<<std::endl;
483 Vector<double, InputImageType::ImageDimension> shift= movingCenter-fixedCenter;
484 if (m_Verbose)std::cout<<"The initial shift applied is "<<shift<<"..."<<std::endl;
486 m_ArgsInfo.transX_arg= shift [0];
487 m_ArgsInfo.transY_arg= shift [1];
488 if (InputImageType::ImageDimension==3) m_ArgsInfo.transZ_arg=shift [2];
491 //============================================================================
493 //============================================================================
494 typedef clitk::GenericAffineTransform<args_info_clitkAffineRegistration, TCoordRep, InputImageType::ImageDimension > GenericAffineTransformType;
495 typename GenericAffineTransformType::Pointer genericAffineTransform = GenericAffineTransformType::New();
496 genericAffineTransform->SetArgsInfo(m_ArgsInfo);
497 typedef itk::Transform< double, InputImageType::ImageDimension, InputImageType::ImageDimension > TransformType;
498 typename TransformType::Pointer transform = genericAffineTransform->GetTransform();
499 std::cout<<m_ArgsInfo.transform_arg<<std::endl;
502 //=======================================================
504 //=======================================================
505 std::cout<<"setting Interpolator..."<<std::endl;
506 typedef clitk::GenericInterpolator<args_info_clitkAffineRegistration, InternalImageType,TCoordRep > GenericInterpolatorType;
507 typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
508 genericInterpolator->SetArgsInfo(m_ArgsInfo);
509 typedef itk::InterpolateImageFunction< InternalImageType, TCoordRep > InterpolatorType;
510 typename InterpolatorType::Pointer interpolator=genericInterpolator->GetInterpolatorPointer();
511 std::cout<<"end of interpolator"<<std::endl;
513 //============================================================================
515 //============================================================================
516 typedef clitk::GenericOptimizer<args_info_clitkAffineRegistration> GenericOptimizerType;
517 unsigned int nParam = transform->GetNumberOfParameters();
518 typename GenericOptimizerType::Pointer genericOptimizer=GenericOptimizerType::New();
519 genericOptimizer->SetArgsInfo(m_ArgsInfo);
520 genericOptimizer->SetOutputIteration(m_Verbose);
521 genericOptimizer->SetOutputPosition(m_Verbose);
522 genericOptimizer->SetOutputValue(m_Verbose);
523 genericOptimizer->SetOutputGradient(m_ArgsInfo.gradient_flag);
524 genericOptimizer->SetMaximize(genericMetric->GetMaximize());
525 genericOptimizer->SetNumberOfParameters(nParam);
526 typedef itk::SingleValuedNonLinearOptimizer OptimizerType;
527 OptimizerType::Pointer optimizer=genericOptimizer->GetOptimizerPointer();
530 itk::Optimizer::ScalesType scales( nParam );
531 for (unsigned int i=nParam-InputImageType::ImageDimension; i<nParam; i++) //Translations
532 scales[i] = m_ArgsInfo.tWeight_arg;
533 for (unsigned int i=0; i<nParam-InputImageType::ImageDimension; i++) //Rest
534 scales[i] = m_ArgsInfo.rWeight_arg*180./M_PI;
535 optimizer->SetScales(scales);
536 //============================================================================
537 // Multiresolution registration
538 //============================================================================
539 std::cout<<"start MultiResolution..."<<std::endl;
540 typedef itk::MultiResolutionImageRegistrationMethod< InternalImageType,InternalImageType > RegistrationType;
541 typename RegistrationType::Pointer registration = RegistrationType::New();
542 registration->SetFixedImage( fixedImage );
543 registration->SetFixedImageRegion(fixedImage->GetLargestPossibleRegion());
544 registration->SetMovingImage( movingImage );
545 registration->SetFixedImagePyramid( fixedImagePyramid );
546 registration->SetMovingImagePyramid( movingImagePyramid );
547 registration->SetTransform( transform );
548 registration->SetInitialTransformParameters( transform->GetParameters() );
549 registration->SetInterpolator( interpolator );
550 registration->SetMetric(metric);
551 registration->SetOptimizer(optimizer);
552 registration->SetNumberOfLevels( m_ArgsInfo.levels_arg );
553 if (m_Verbose) std::cout << "Setting "<< m_ArgsInfo.levels_arg <<" resolution levels..." << std::endl;
554 if (m_Verbose) std::cout << "Initial Transform: "<< registration->GetInitialTransformParameters()<<std::endl;
556 //============================================================================
557 // Connecting the commander to the registration to monitor it
558 //============================================================================
561 // Output iteration info
562 CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
563 observer->SetOptimizer(genericOptimizer);
564 optimizer->AddObserver( itk::IterationEvent(), observer );
568 typedef RegistrationInterfaceCommand<RegistrationType> CommandType;
569 typename CommandType::Pointer command = CommandType::New();
570 command->SetArgsInfo(m_ArgsInfo);
571 registration->AddObserver( itk::IterationEvent(), command );
576 //============================================================================
577 // Finally we can start the registration with the given amount of multiresolution levels
578 //============================================================================
579 if (m_Verbose) std::cout << "Starting the registration now..." << std::endl;
582 registration->Update();
583 } catch ( itk::ExceptionObject & err ) {
584 std::cerr << "ExceptionObject caught !" << std::endl;
585 std::cerr << err << std::endl;
589 //============================================================================
590 // Processing the result of the registration
591 //============================================================================
592 OptimizerType::ParametersType finalParameters = registration->GetLastTransformParameters();
593 std::cout<< "Result : " <<std::setprecision(12)<<std::endl;
595 for (unsigned int i=nParam-InputImageType::ImageDimension; i<nParam; i++) //Translations
596 std::cout << " Translation " << i << " = " << finalParameters[i];
597 for (unsigned int i=0; i<nParam-InputImageType::ImageDimension; i++) //Rest
598 std::cout << " Other parameter " << i << " = " << finalParameters[i];
600 itk::Matrix<double,InputImageType::ImageDimension+1,InputImageType::ImageDimension+1> matrix;
601 if (m_ArgsInfo.transform_arg == 3) {
602 for (unsigned int i=0; i<InputImageType::ImageDimension; i++) {
603 matrix[i][3] = finalParameters[nParam-InputImageType::ImageDimension+i];
604 for (unsigned int j=0; j<InputImageType::ImageDimension; j++) {
605 matrix[i][j] = finalParameters[i*3+j];
610 matrix = clitk::GetBackwardAffineMatrix<InputImageType::ImageDimension>(finalParameters);
611 std::cout<<"outside GetBackWardAffineMatrix...."<<std::endl;
614 std::cout << " Affine transform matrix =" << std::endl;
615 std::cout << matrix <<std::setprecision(6)<< std::endl;
616 std::cout << " End of Registration" << std::endl;
617 // Write matrix to a file
618 if (m_ArgsInfo.matrix_given) {
620 mFile.open(m_ArgsInfo.matrix_arg);
621 mFile<<std::setprecision(12)<<matrix<< std::setprecision(6)<<std::endl;
625 //============================================================================
626 // Prepare the resampling filter in order to transform the moving image.
627 //============================================================================
628 // if (m_ArgsInfo.output_given || m_ArgsInfo.checker_after_given || m_ArgsInfo.after_given ) {
629 transform->SetParameters( finalParameters );
630 typedef itk::ResampleImageFilter< InternalImageType,InternalImageType > ResampleFilterType;
631 typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
633 resampler->SetTransform( transform );
634 resampler->SetInput( movingImage );
635 resampler->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() );
636 resampler->SetOutputOrigin( fixedImage->GetOrigin() );
637 resampler->SetOutputSpacing( fixedImage->GetSpacing() );
638 resampler->SetDefaultPixelValue( 0 );
641 // if (m_ArgsInfo.output_given) {
642 //We write an output in the same pixeltype then the input
643 /*typedef itk::ImageFileWriter< FixedImageType > WriterType;
644 typename WriterType::Pointer outputWriter = WriterType::New();
645 outputWriter->SetFileName(m_ArgsInfo.output_arg );
646 outputWriter->SetInput( resampler->GetOutput() );
647 outputWriter->Update();*/
648 typedef InternalImageType OutputImageType;
649 typename OutputImageType::Pointer outputImage = resampler->GetOutput();
650 std::cout<<"Writing Output....."<<std::endl;
651 this->template SetNextOutput<OutputImageType>(outputImage);
655 //============================================================================
657 //============================================================================
658 if (m_ArgsInfo.checker_after_given) {
659 //To display correctly the checkerboard image, the intensities must lie in the same range (normalized)
660 //We write the image in the internal image type
661 typedef itk::ResampleImageFilter< InternalImageType,InternalImageType > ResampleFilterType;
662 typename ResampleFilterType::Pointer internalResampler = ResampleFilterType::New();
663 internalResampler->SetTransform( transform );
664 internalResampler->SetInput( inputMovingImage );
665 internalResampler->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() );
666 internalResampler->SetOutputOrigin( fixedImage->GetOrigin() );
667 internalResampler->SetOutputSpacing( fixedImage->GetSpacing() );
668 internalResampler->SetDefaultPixelValue( 0 );
670 //We pass the normalized images to the checker filter
671 typedef itk::CheckerBoardImageFilter< InternalImageType > CheckerBoardFilterType;
672 typename CheckerBoardFilterType::Pointer checkerFilter= CheckerBoardFilterType::New();
674 checkerFilter->SetInput1(inputFixedImage);
675 checkerFilter->SetInput2(internalResampler->GetOutput());
676 typedef itk::ImageFileWriter< InternalImageType > InternalWriterType;
677 typename InternalWriterType::Pointer checkerWriter = InternalWriterType::New();
678 checkerWriter->SetFileName(m_ArgsInfo.checker_after_arg);
679 checkerWriter->SetInput( checkerFilter->GetOutput() );
680 checkerWriter->Update();
684 //============================================================================
686 //============================================================================
687 if (m_ArgsInfo.checker_before_given) {
688 //To display correctly the checkerboard image, the intensities must lie in the same range (normalized)
689 //We write the image in the internal image type
690 //We pass the normalized images to the checker filter
691 typedef itk::CheckerBoardImageFilter< InternalImageType > CheckerBoardFilterType;
692 typename CheckerBoardFilterType::Pointer checkerFilter= CheckerBoardFilterType::New();
694 checkerFilter->SetInput1(inputFixedImage);
695 checkerFilter->SetInput2(inputMovingImage);
696 typedef itk::ImageFileWriter< InternalImageType > InternalWriterType;
697 typename InternalWriterType::Pointer checkerWriter = InternalWriterType::New();
698 checkerWriter->SetFileName(m_ArgsInfo.checker_before_arg);
699 checkerWriter->SetInput( checkerFilter->GetOutput() );
700 checkerWriter->Update();
704 //============================================================================
706 //============================================================================
707 if (m_ArgsInfo.after_given) {
708 typedef itk::SubtractImageFilter< InternalImageType, FixedImageType,FixedImageType > DifferenceImageFilterType;
709 typename DifferenceImageFilterType::Pointer differenceAfterFilter= DifferenceImageFilterType::New();
711 differenceAfterFilter->SetInput1(fixedImage);
712 differenceAfterFilter->SetInput2(resampler->GetOutput());
714 // Prepare a writer to write the difference image
715 typedef itk::ImageFileWriter< FixedImageType > WriterType;
716 typename WriterType::Pointer differenceAfterWriter = WriterType::New();
717 differenceAfterWriter->SetFileName(m_ArgsInfo.after_arg );
718 differenceAfterWriter->SetInput( differenceAfterFilter->GetOutput() );
719 differenceAfterWriter->Update();
723 //============================================================================
724 // Difference Before?
725 //============================================================================
726 if (m_ArgsInfo.before_given) {
727 typedef itk::CastImageFilter< InternalImageType,FixedImageType > CastFilterType;
728 typename CastFilterType::Pointer caster = CastFilterType::New();
729 caster->SetInput( movingImage );
731 typedef itk::SubtractImageFilter< InternalImageType, FixedImageType, FixedImageType > DifferenceImageFilterType;
732 typename DifferenceImageFilterType::Pointer differenceBeforeFilter= DifferenceImageFilterType::New();
735 differenceBeforeFilter->SetInput1(fixedImage);
736 differenceBeforeFilter->SetInput2(caster->GetOutput());
738 // Prepare a writer to write the difference image
739 typedef itk::ImageFileWriter< FixedImageType > WriterType;
740 typename WriterType::Pointer differenceBeforeWriter = WriterType::New();
741 differenceBeforeWriter->SetFileName(m_ArgsInfo.before_arg);
742 differenceBeforeWriter->SetInput( differenceBeforeFilter->GetOutput() );
743 differenceBeforeWriter->Update();
749 //====================================================================
751 #endif //#define CLITKAFFINEREGISTRATIONCGENERICFILTER_CXX