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://oncora1.lyon.fnclcc.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_TXX
20 #define CLITKAFFINEREGISTRATIONGENERICFILTER_TXX
25 //==============================================================================
26 //Creating an observer class that allows us to monitor the registration
27 //================================================================================
28 class CommandIterationUpdate : public itk::Command
31 typedef CommandIterationUpdate Self;
32 typedef itk::Command Superclass;
33 typedef itk::SmartPointer<Self> Pointer;
36 CommandIterationUpdate() {};
38 typedef clitk::GenericOptimizer<args_info_clitkAffineRegistration> OptimizerType;
39 typedef const OptimizerType * OptimizerPointer;
41 // Set the generic optimizer
42 void SetOptimizer(OptimizerPointer o) {
47 void Execute(itk::Object *caller, const itk::EventObject & event) {
48 Execute( (const itk::Object *)caller, event);
51 void Execute(const itk::Object * object, const itk::EventObject & event) {
52 if ( !(itk::IterationEvent().CheckEvent( &event )) ) {
56 m_Optimizer->OutputIterationInfo();
59 OptimizerPointer m_Optimizer;
61 //==================================================================================================================================//
63 //===================================================================================================================================//
65 template<class args_info_clitkAffineRegistration>
66 AffineRegistrationGenericFilter<args_info_clitkAffineRegistration>::AffineRegistrationGenericFilter():
67 ImageToImageGenericFilter<Self>("Register")
70 InitializeImageType<2>();
71 InitializeImageType<3>();
74 //==========================================================================================================//
75 //============================================================================================================//
76 //--------------------------------------------------------------------
77 template<class args_info_type>
78 template<unsigned int Dim>
79 void AffineRegistrationGenericFilter<args_info_type>::InitializeImageType()
81 ADD_DEFAULT_IMAGE_TYPES(Dim);
83 //--------------------------------------------------------------------
86 //==============================================================================
87 //Creating an observer class that allows us to change parameters at subsequent levels
88 //==============================================================================
89 template <typename TRegistration, class args_info_clitkAffineRegistration>
90 class RegistrationInterfaceCommand : public itk::Command
93 typedef RegistrationInterfaceCommand Self;
94 typedef itk::Command Superclass;
95 typedef itk::SmartPointer<Self> Pointer;
98 RegistrationInterfaceCommand() {};
102 typedef TRegistration RegistrationType;
103 typedef RegistrationType * RegistrationPointer;
106 typedef typename RegistrationType::FixedImageType InternalImageType;
107 typedef clitk::GenericMetric<args_info_clitkAffineRegistration, InternalImageType, InternalImageType> GenericMetricType;
109 // Two arguments are passed to the Execute() method: the first
110 // is the pointer to the object which invoked the event and the
111 // second is the event that was invoked.
112 void Execute(itk::Object * object, const itk::EventObject & event) {
113 if ( !(itk::IterationEvent().CheckEvent( &event )) ) {
118 RegistrationPointer registration = dynamic_cast<RegistrationPointer>( object );
119 unsigned int numberOfLevels=registration->GetNumberOfLevels();
120 unsigned int currentLevel=registration->GetCurrentLevel()+1;
123 std::cout<<std::endl;
124 std::cout<<"========================================"<<std::endl;
125 std::cout<<"Starting resolution level "<<currentLevel<<" of "<<numberOfLevels<<"..."<<std::endl;
126 std::cout<<"========================================"<<std::endl;
127 std::cout<<std::endl;
130 if (currentLevel>1) {
131 // Reinitialize the metric (!= number of samples)
132 typename GenericMetricType::Pointer genericMetric= GenericMetricType::New();
133 genericMetric->SetArgsInfo(m_ArgsInfo);
134 genericMetric->SetFixedImage(registration->GetFixedImagePyramid()->GetOutput(registration->GetCurrentLevel()));
135 if (m_ArgsInfo.referenceMask_given) genericMetric->SetFixedImageMask(registration->GetMetric()->GetFixedImageMask());
136 typedef itk::ImageToImageMetric< InternalImageType, InternalImageType > MetricType;
137 typename MetricType::Pointer metric=genericMetric->GetMetricPointer();
138 registration->SetMetric(metric);
142 void Execute(const itk::Object * , const itk::EventObject & ) {
146 void SetArgsInfo(args_info_clitkAffineRegistration a) {
149 args_info_clitkAffineRegistration m_ArgsInfo;
152 //==============================================================================================//
154 //==============================================================================================//
155 template<class args_info_clitkAffineRegistration>
156 void AffineRegistrationGenericFilter<args_info_clitkAffineRegistration>::SetArgsInfo(const args_info_clitkAffineRegistration & a)
159 if (m_ArgsInfo.reference_given) AddInputFilename(m_ArgsInfo.reference_arg);
161 if (m_ArgsInfo.target_given) {
162 AddInputFilename(m_ArgsInfo.target_arg);
165 if (m_ArgsInfo.output_given) SetOutputFilename(m_ArgsInfo.output_arg);
167 //==============================================================================
168 // Update with the number of dimensions and pixeltype
169 //==============================================================================
170 template<class args_info_clitkAffineRegistration>
171 template<class InputImageType>
172 void AffineRegistrationGenericFilter<args_info_clitkAffineRegistration>::UpdateWithInputImageType()
174 //=============================================================================
176 //=============================================================================
178 typedef typename InputImageType::PixelType PixelType;
179 //typedef typename InputImageType::ImageDimension Dimension;
182 bool threadsGiven=m_ArgsInfo.threads_given;
183 int threads=m_ArgsInfo.threads_arg;
185 //Coordinate Representation
186 typedef double TCoordRep;
189 typename InputImageType::Pointer fixedImage = this->template GetInput<InputImageType>(0);
191 typename InputImageType::Pointer inputFixedImage = this->template GetInput<InputImageType>(0);
194 typename InputImageType::Pointer movingImage = this->template GetInput<InputImageType>(1);
196 typename InputImageType::Pointer inputMovingImage = this->template GetInput<InputImageType>(1);
200 //The pixeltype of the fixed image will be used for output
201 typedef itk::Image< PixelType, InputImageType::ImageDimension > FixedImageType;
203 //Whatever the pixel type, internally we work with an image represented in float
204 typedef typename InputImageType::PixelType InternalPixelType;
205 typedef itk::Image< PixelType, InputImageType::ImageDimension > InternalImageType;
208 //Read in the reference/fixed image
209 // typedef itk::ImageFileReader< InternalImageType > ReaderType;
210 // typename ReaderType::Pointer fixedImageReader = ReaderType::New();
211 // fixedImageReader->SetFileName( m_ArgsInfo.reference_arg);
214 //Read in the object/moving image
215 // typename ReaderType::Pointer movingImageReader = ReaderType::New();
216 // movingImageReader->SetFileName( m_ArgsInfo.target_arg );
217 if (m_Verbose) std::cout<<"Reading images..."<<std::endl;
218 // fixedImageReader->Update();
219 // movingImageReader->Update();
221 if (m_Verbose) std::cout << "Reading images... " << std::endl;
223 //we connect pointers to these internal images
224 // typedef typename fixedImageReader fixedImage;
225 // typedef typename movingImageReader movingImage;
227 //We keep the images used for input for possible output
228 // typedef typename fixedImageReader inputFixedImage;
229 // typedef typename movingImageReader inputMovingImage;
232 //============================================================================
234 //============================================================================
236 //If given, the intensities of both images are first normalized to a zero mean and SD of 1
237 // (usefull for MI, not necessary for Mattes' MI but performed anyway for the ouput)
238 if ( m_ArgsInfo.normalize_flag ) {
239 typedef itk::NormalizeImageFilter< InternalImageType,InternalImageType > NormalizeFilterType;
241 typename NormalizeFilterType::Pointer fixedNormalizeFilter = NormalizeFilterType::New();
242 typename NormalizeFilterType::Pointer movingNormalizeFilter = NormalizeFilterType::New();
244 fixedNormalizeFilter->SetInput( fixedImage );
245 movingNormalizeFilter->SetInput( movingImage );
247 fixedNormalizeFilter->Update();
248 movingNormalizeFilter->Update();
250 //We keep the images used for input for possible output
251 inputFixedImage= fixedNormalizeFilter->GetOutput();
252 inputMovingImage= movingNormalizeFilter->GetOutput();
254 //the pointers are reconnected for further output
255 fixedImage=fixedNormalizeFilter->GetOutput();
256 movingImage=movingNormalizeFilter->GetOutput();
258 if (m_Verbose) std::cout << "Normalizing image intensities to zero mean and SD of 1..." << std::endl;
262 //If given, the images are blurred before processing
263 if ( m_ArgsInfo.blur_arg!= 0) {
264 typedef itk::DiscreteGaussianImageFilter<InternalImageType,InternalImageType> GaussianFilterType;
265 typename GaussianFilterType::Pointer fixedSmoother = GaussianFilterType::New();
266 typename GaussianFilterType::Pointer movingSmoother = GaussianFilterType::New();
267 fixedSmoother->SetVariance( m_ArgsInfo.blur_arg );
268 movingSmoother->SetVariance(m_ArgsInfo.blur_arg );
270 fixedSmoother->SetInput( fixedImage );
271 movingSmoother->SetInput( movingImage );
273 fixedSmoother->Update();
274 movingSmoother->Update();
276 fixedImage=fixedSmoother->GetOutput();
277 movingImage=movingSmoother->GetOutput();
279 if (m_Verbose) std::cout << "Blurring images with a Gaussian with standard deviation of " << m_ArgsInfo.blur_arg <<"..." << std::endl;
283 //============================================================================
284 // Setting up the moving image in a reference system
285 //============================================================================
286 const itk::Vector<double, InputImageType::ImageDimension> movingResolution = movingImage->GetSpacing();
287 typename InternalImageType::RegionType movingRegion = movingImage->GetLargestPossibleRegion();
288 typename InternalImageType::RegionType::SizeType movingSize = movingRegion.GetSize();
290 // Print the parameters of the moving image
292 std::cout << "Object or Moving image:"<<std::endl;
293 std::cout << "Size: " << movingSize[0] << ", " << movingSize[1];
294 if (InputImageType::ImageDimension==3) std::cout<<", " << movingSize[2];
295 std::cout << std::endl;
297 std::cout<< "Resolution: "<< movingResolution[0] << ", " << movingResolution[1];
298 if (InputImageType::ImageDimension==3) std::cout<< ", " << movingResolution[2];
299 std::cout << std::endl;
303 //============================================================================
304 // Setting up the fixed image in a reference system
305 //============================================================================
306 const itk::Vector<double, InputImageType::ImageDimension> fixedResolution = fixedImage->GetSpacing();
307 typename InternalImageType::RegionType fixedRegion = fixedImage->GetLargestPossibleRegion();
308 typename InternalImageType::RegionType::SizeType fixedSize = fixedRegion.GetSize();
310 // Print the parameters of the moving image and the transform
312 std::cout << "Target or Moving image:"<<std::endl;
313 std::cout << "Size: " << fixedSize[0] << ", " << fixedSize[1];
314 if (InputImageType::ImageDimension==3) std::cout<<", " << fixedSize[2];
315 std::cout << std::endl;
317 std::cout<< "Resolution: "<< fixedResolution[0] << ", " << fixedResolution[1];
318 if (InputImageType::ImageDimension==3) std::cout<< ", " << fixedResolution[2];
319 std::cout << std::endl;
324 //===========================================================================
325 // If given, we connect a mask to reference or target
326 //============================================================================
327 typedef itk::ImageMaskSpatialObject< InputImageType::ImageDimension > MaskType;
328 typename MaskType::Pointer fixedMask=NULL;
329 if (m_ArgsInfo.referenceMask_given) {
330 fixedMask= MaskType::New();
331 typedef itk::Image< unsigned char, InputImageType::ImageDimension > ImageMaskType;
332 typedef itk::ImageFileReader< ImageMaskType > MaskReaderType;
333 typename MaskReaderType::Pointer maskReader = MaskReaderType::New();
334 maskReader->SetFileName(m_ArgsInfo.referenceMask_arg);
336 maskReader->Update();
337 } catch ( itk::ExceptionObject & err ) {
338 std::cerr << "ExceptionObject caught while reading mask !" << std::endl;
339 std::cerr << err << std::endl;
342 if (m_Verbose)std::cout <<"Reference image mask was read..." <<std::endl;
344 // Set the image to the spatialObject
345 fixedMask->SetImage( maskReader->GetOutput() );
348 typedef itk::ImageMaskSpatialObject< InputImageType::ImageDimension > MaskType;
349 typename MaskType::Pointer movingMask=NULL;
350 if (m_ArgsInfo.targetMask_given) {
351 movingMask= MaskType::New();
352 typedef itk::Image< unsigned char, InputImageType::ImageDimension > ImageMaskType;
353 typedef itk::ImageFileReader< ImageMaskType > MaskReaderType;
354 typename MaskReaderType::Pointer maskReader = MaskReaderType::New();
355 maskReader->SetFileName(m_ArgsInfo.targetMask_arg);
357 maskReader->Update();
358 } catch ( itk::ExceptionObject & err ) {
359 std::cerr << "ExceptionObject caught !" << std::endl;
360 std::cerr << err << std::endl;
362 if (m_Verbose)std::cout <<"Target image mask was read..." <<std::endl;
364 movingMask->SetImage( maskReader->GetOutput() );
368 //============================================================================
369 // The image pyramids
370 //============================================================================
371 typedef itk::RecursiveMultiResolutionPyramidImageFilter<InternalImageType,InternalImageType > FixedImagePyramidType;
372 typedef itk::RecursiveMultiResolutionPyramidImageFilter<InternalImageType,InternalImageType > MovingImagePyramidType;
373 typename FixedImagePyramidType::Pointer fixedImagePyramid = FixedImagePyramidType::New();
374 typename MovingImagePyramidType::Pointer movingImagePyramid = MovingImagePyramidType::New();
375 fixedImagePyramid->SetUseShrinkImageFilter(false);
376 fixedImagePyramid->SetInput(fixedImage);
377 fixedImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
378 movingImagePyramid->SetUseShrinkImageFilter(false);
379 movingImagePyramid->SetInput(movingImage);
380 movingImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
381 if (m_Verbose) std::cout<<"Creating the image pyramid..."<<std::endl;
383 fixedImagePyramid->Update();
384 movingImagePyramid->Update();
388 //============================================================================
389 // We retrieve the type of metric from the command line
390 //============================================================================
391 typedef clitk::GenericMetric<args_info_clitkAffineRegistration, InternalImageType, InternalImageType> GenericMetricType;
392 typename GenericMetricType::Pointer genericMetric=GenericMetricType::New();
393 genericMetric->SetArgsInfo(m_ArgsInfo);
394 genericMetric->SetFixedImage(fixedImagePyramid->GetOutput(0));
395 if (fixedMask) genericMetric->SetFixedImageMask(fixedMask);
396 typedef itk::ImageToImageMetric< InternalImageType, InternalImageType > MetricType;
397 typename MetricType::Pointer metric=genericMetric->GetMetricPointer();
398 if (movingMask) metric->SetMovingImageMask(movingMask);
400 #ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
401 if (threadsGiven) metric->SetNumberOfThreads( threads );
403 if (m_Verbose) std::cout<<"Not setting the number of threads (not compiled with USE_OPTIMIZED_REGISTRATION_METHODS)..."<<std::endl;
406 //============================================================================
407 // Initialize using image moments.
408 //============================================================================
409 if (m_ArgsInfo.moment_flag) {
410 typedef itk::ImageMomentsCalculator< InternalImageType > CalculatorType;
411 typename CalculatorType::Pointer fixedCalculator= CalculatorType::New();
413 typename InternalImageType::Pointer fixedThresh;
414 if (m_ArgsInfo.intThreshold_given) {
415 typedef itk::ThresholdImageFilter<InternalImageType> ThresholdImageFilterType;
416 typename ThresholdImageFilterType::Pointer thresholder = ThresholdImageFilterType::New();
417 thresholder->SetInput(fixedImage);
418 thresholder->SetLower(m_ArgsInfo.intThreshold_arg);
419 thresholder->Update();
420 fixedThresh=thresholder->GetOutput();
421 } else fixedThresh=fixedImage;
423 fixedCalculator->SetImage(fixedThresh);
424 fixedCalculator->Compute();
425 Vector<double, InputImageType::ImageDimension> fixedCenter=fixedCalculator->GetCenterOfGravity();
426 if (m_Verbose)std::cout<<"The fixed center of gravity is "<<fixedCenter<<"..."<<std::endl;
428 typedef itk::ImageMomentsCalculator< InternalImageType > CalculatorType;
429 typename CalculatorType::Pointer movingCalculator= CalculatorType::New();
431 typename InternalImageType::Pointer movingThresh;
432 if (m_ArgsInfo.intThreshold_given) {
433 typedef itk::ThresholdImageFilter<InternalImageType> ThresholdImageFilterType;
434 typename ThresholdImageFilterType::Pointer thresholder = ThresholdImageFilterType::New();
435 thresholder->SetInput(movingImage);
436 thresholder->SetLower(m_ArgsInfo.intThreshold_arg);
437 thresholder->Update();
438 movingThresh=thresholder->GetOutput();
439 } else movingThresh=movingImage;
441 movingCalculator->SetImage(movingThresh);
442 movingCalculator->Compute();
443 Vector<double, InputImageType::ImageDimension> movingCenter=movingCalculator->GetCenterOfGravity();
444 if (m_Verbose)std::cout<<"The moving center of gravity is "<<movingCenter<<"..."<<std::endl;
446 Vector<double, InputImageType::ImageDimension> shift= movingCenter-fixedCenter;
447 if (m_Verbose)std::cout<<"The initial shift applied is "<<shift<<"..."<<std::endl;
449 m_ArgsInfo.transX_arg= shift [0];
450 m_ArgsInfo.transY_arg= shift [1];
451 if (InputImageType::ImageDimension==3) m_ArgsInfo.transZ_arg=shift [2];
454 //============================================================================
456 //============================================================================
457 typedef clitk::GenericAffineTransform<args_info_clitkAffineRegistration, TCoordRep, InputImageType::ImageDimension > GenericAffineTransformType;
458 typename GenericAffineTransformType::Pointer genericAffineTransform = GenericAffineTransformType::New();
459 genericAffineTransform->SetArgsInfo(m_ArgsInfo);
460 typedef itk::Transform< double, InputImageType::ImageDimension, InputImageType::ImageDimension > TransformType;
461 typename TransformType::Pointer transform = genericAffineTransform->GetTransform();
462 std::cout<<m_ArgsInfo.transform_arg<<std::endl;
465 //=======================================================
467 //=======================================================
468 std::cout<<"setting Interpolator..."<<std::endl;
469 typedef clitk::GenericInterpolator<args_info_clitkAffineRegistration, InternalImageType,TCoordRep > GenericInterpolatorType;
470 typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
471 genericInterpolator->SetArgsInfo(m_ArgsInfo);
472 typedef itk::InterpolateImageFunction< InternalImageType, TCoordRep > InterpolatorType;
473 typename InterpolatorType::Pointer interpolator=genericInterpolator->GetInterpolatorPointer();
474 std::cout<<"end of interpolator"<<std::endl;
476 //============================================================================
478 //============================================================================
479 typedef clitk::GenericOptimizer<args_info_clitkAffineRegistration> GenericOptimizerType;
480 unsigned int nParam = transform->GetNumberOfParameters();
481 typename GenericOptimizerType::Pointer genericOptimizer=GenericOptimizerType::New();
482 genericOptimizer->SetArgsInfo(m_ArgsInfo);
483 genericOptimizer->SetOutputIteration(m_Verbose);
484 genericOptimizer->SetOutputPosition(m_Verbose);
485 genericOptimizer->SetOutputValue(m_Verbose);
486 genericOptimizer->SetOutputGradient(m_ArgsInfo.gradient_flag);
487 genericOptimizer->SetMaximize(genericMetric->GetMaximize());
488 genericOptimizer->SetNumberOfParameters(nParam);
489 typedef itk::SingleValuedNonLinearOptimizer OptimizerType;
490 OptimizerType::Pointer optimizer=genericOptimizer->GetOptimizerPointer();
493 itk::Optimizer::ScalesType scales( nParam );
494 for (unsigned int i=nParam-InputImageType::ImageDimension; i<nParam; i++) //Translations
495 scales[i] = m_ArgsInfo.tWeight_arg;
496 for (unsigned int i=0; i<nParam-InputImageType::ImageDimension; i++) //Rest
497 scales[i] = m_ArgsInfo.rWeight_arg*180./M_PI;
498 optimizer->SetScales(scales);
499 //============================================================================
500 // Multiresolution registration
501 //============================================================================
502 std::cout<<"start MultiResolution..."<<std::endl;
503 typedef itk::MultiResolutionImageRegistrationMethod< InternalImageType,InternalImageType > RegistrationType;
504 typename RegistrationType::Pointer registration = RegistrationType::New();
505 registration->SetFixedImage( fixedImage );
506 registration->SetFixedImageRegion(fixedImage->GetLargestPossibleRegion());
507 registration->SetMovingImage( movingImage );
508 registration->SetFixedImagePyramid( fixedImagePyramid );
509 registration->SetMovingImagePyramid( movingImagePyramid );
510 registration->SetTransform( transform );
511 registration->SetInitialTransformParameters( transform->GetParameters() );
512 registration->SetInterpolator( interpolator );
513 registration->SetMetric(metric);
514 registration->SetOptimizer(optimizer);
515 registration->SetNumberOfLevels( m_ArgsInfo.levels_arg );
516 if (m_Verbose) std::cout << "Setting "<< m_ArgsInfo.levels_arg <<" resolution levels..." << std::endl;
517 if (m_Verbose) std::cout << "Initial Transform: "<< registration->GetInitialTransformParameters()<<std::endl;
519 //============================================================================
520 // Connecting the commander to the registration to monitor it
521 //============================================================================
524 // Output iteration info
525 CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
526 observer->SetOptimizer(genericOptimizer);
527 optimizer->AddObserver( itk::IterationEvent(), observer );
531 typedef RegistrationInterfaceCommand<RegistrationType, args_info_clitkAffineRegistration> CommandType;
532 typename CommandType::Pointer command = CommandType::New();
533 command->SetArgsInfo(m_ArgsInfo);
534 registration->AddObserver( itk::IterationEvent(), command );
539 //============================================================================
540 // Finally we can start the registration with the given amount of multiresolution levels
541 //============================================================================
542 if (m_Verbose) std::cout << "Starting the registration now..." << std::endl;
545 registration->StartRegistration();
546 } catch ( itk::ExceptionObject & err ) {
547 std::cerr << "ExceptionObject caught !" << std::endl;
548 std::cerr << err << std::endl;
552 //============================================================================
553 // Processing the result of the registration
554 //============================================================================
555 OptimizerType::ParametersType finalParameters = registration->GetLastTransformParameters();
556 std::cout<< "Result : " <<std::setprecision(12)<<std::endl;
558 for (unsigned int i=nParam-InputImageType::ImageDimension; i<nParam; i++) //Translations
559 std::cout << " Translation " << i << " = " << finalParameters[i];
560 for (unsigned int i=0; i<nParam-InputImageType::ImageDimension; i++) //Rest
561 std::cout << " Other parameter " << i << " = " << finalParameters[i];
563 itk::Matrix<double,InputImageType::ImageDimension+1,InputImageType::ImageDimension+1> matrix;
564 if (m_ArgsInfo.transform_arg == 3) {
565 for (unsigned int i=0; i<InputImageType::ImageDimension; i++) {
566 matrix[i][3] = finalParameters[nParam-InputImageType::ImageDimension+i];
567 for (unsigned int j=0; j<InputImageType::ImageDimension; j++) {
568 matrix[i][j] = finalParameters[i*3+j];
573 matrix = clitk::GetBackwardAffineMatrix<InputImageType::ImageDimension>(finalParameters);
574 std::cout<<"outside GetBackWardAffineMatrix...."<<std::endl;
577 std::cout << " Affine transform matrix =" << std::endl;
578 std::cout << matrix <<std::setprecision(6)<< std::endl;
579 std::cout << " End of Registration" << std::endl;
580 // Write matrix to a file
581 if (m_ArgsInfo.matrix_given) {
583 mFile.open(m_ArgsInfo.matrix_arg);
584 mFile<<std::setprecision(12)<<matrix<< std::setprecision(6)<<std::endl;
588 //============================================================================
589 // Prepare the resampling filter in order to transform the moving image.
590 //============================================================================
591 // if (m_ArgsInfo.output_given || m_ArgsInfo.checker_after_given || m_ArgsInfo.after_given ) {
592 transform->SetParameters( finalParameters );
593 typedef itk::ResampleImageFilter< InternalImageType,InternalImageType > ResampleFilterType;
594 typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
596 resampler->SetTransform( transform );
597 resampler->SetInput( movingImage );
598 resampler->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() );
599 resampler->SetOutputOrigin( fixedImage->GetOrigin() );
600 resampler->SetOutputSpacing( fixedImage->GetSpacing() );
601 resampler->SetDefaultPixelValue( 0 );
604 // if (m_ArgsInfo.output_given) {
605 //We write an output in the same pixeltype then the input
606 /*typedef itk::ImageFileWriter< FixedImageType > WriterType;
607 typename WriterType::Pointer outputWriter = WriterType::New();
608 outputWriter->SetFileName(m_ArgsInfo.output_arg );
609 outputWriter->SetInput( resampler->GetOutput() );
610 outputWriter->Update();*/
611 typedef InternalImageType OutputImageType;
612 typename OutputImageType::Pointer outputImage = resampler->GetOutput();
613 std::cout<<"Writing Output....."<<std::endl;
614 this->template SetNextOutput<OutputImageType>(outputImage);
618 //============================================================================
620 //============================================================================
621 if (m_ArgsInfo.checker_after_given) {
622 //To display correctly the checkerboard image, the intensities must lie in the same range (normalized)
623 //We write the image in the internal image type
624 typedef itk::ResampleImageFilter< InternalImageType,InternalImageType > ResampleFilterType;
625 typename ResampleFilterType::Pointer internalResampler = ResampleFilterType::New();
626 internalResampler->SetTransform( transform );
627 internalResampler->SetInput( inputMovingImage );
628 internalResampler->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() );
629 internalResampler->SetOutputOrigin( fixedImage->GetOrigin() );
630 internalResampler->SetOutputSpacing( fixedImage->GetSpacing() );
631 internalResampler->SetDefaultPixelValue( 0 );
633 //We pass the normalized images to the checker filter
634 typedef itk::CheckerBoardImageFilter< InternalImageType > CheckerBoardFilterType;
635 typename CheckerBoardFilterType::Pointer checkerFilter= CheckerBoardFilterType::New();
637 checkerFilter->SetInput1(inputFixedImage);
638 checkerFilter->SetInput2(internalResampler->GetOutput());
639 typedef itk::ImageFileWriter< InternalImageType > InternalWriterType;
640 typename InternalWriterType::Pointer checkerWriter = InternalWriterType::New();
641 checkerWriter->SetFileName(m_ArgsInfo.checker_after_arg);
642 checkerWriter->SetInput( checkerFilter->GetOutput() );
643 checkerWriter->Update();
647 //============================================================================
649 //============================================================================
650 if (m_ArgsInfo.checker_before_given) {
651 //To display correctly the checkerboard image, the intensities must lie in the same range (normalized)
652 //We write the image in the internal image type
653 //We pass the normalized images to the checker filter
654 typedef itk::CheckerBoardImageFilter< InternalImageType > CheckerBoardFilterType;
655 typename CheckerBoardFilterType::Pointer checkerFilter= CheckerBoardFilterType::New();
657 checkerFilter->SetInput1(inputFixedImage);
658 checkerFilter->SetInput2(inputMovingImage);
659 typedef itk::ImageFileWriter< InternalImageType > InternalWriterType;
660 typename InternalWriterType::Pointer checkerWriter = InternalWriterType::New();
661 checkerWriter->SetFileName(m_ArgsInfo.checker_before_arg);
662 checkerWriter->SetInput( checkerFilter->GetOutput() );
663 checkerWriter->Update();
667 //============================================================================
669 //============================================================================
670 if (m_ArgsInfo.after_given) {
671 typedef itk::SubtractImageFilter< InternalImageType, FixedImageType,FixedImageType > DifferenceImageFilterType;
672 typename DifferenceImageFilterType::Pointer differenceAfterFilter= DifferenceImageFilterType::New();
674 differenceAfterFilter->SetInput1(fixedImage);
675 differenceAfterFilter->SetInput2(resampler->GetOutput());
677 // Prepare a writer to write the difference image
678 typedef itk::ImageFileWriter< FixedImageType > WriterType;
679 typename WriterType::Pointer differenceAfterWriter = WriterType::New();
680 differenceAfterWriter->SetFileName(m_ArgsInfo.after_arg );
681 differenceAfterWriter->SetInput( differenceAfterFilter->GetOutput() );
682 differenceAfterWriter->Update();
686 //============================================================================
687 // Difference Before?
688 //============================================================================
689 if (m_ArgsInfo.before_given) {
690 typedef itk::CastImageFilter< InternalImageType,FixedImageType > CastFilterType;
691 typename CastFilterType::Pointer caster = CastFilterType::New();
692 caster->SetInput( movingImage );
694 typedef itk::SubtractImageFilter< InternalImageType, FixedImageType, FixedImageType > DifferenceImageFilterType;
695 typename DifferenceImageFilterType::Pointer differenceBeforeFilter= DifferenceImageFilterType::New();
698 differenceBeforeFilter->SetInput1(fixedImage);
699 differenceBeforeFilter->SetInput2(caster->GetOutput());
701 // Prepare a writer to write the difference image
702 typedef itk::ImageFileWriter< FixedImageType > WriterType;
703 typename WriterType::Pointer differenceBeforeWriter = WriterType::New();
704 differenceBeforeWriter->SetFileName(m_ArgsInfo.before_arg);
705 differenceBeforeWriter->SetInput( differenceBeforeFilter->GetOutput() );
706 differenceBeforeWriter->Update();
711 #endif //#define CLITKAFFINEREGISTRATIONGENERICFILTER_TXX