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 ======================================================================-====*/
18 #ifndef clitkBLUTDIRGenericFilter_cxx
19 #define clitkBLUTDIRGenericFilter_cxx
21 /* =================================================
22 * @file clitkBLUTDIRGenericFilter.cxx
28 ===================================================*/
30 #include "clitkBLUTDIRGenericFilter.h"
35 //==============================================================================
36 // Creating an observer class that allows output at each iteration
37 //==============================================================================
38 class CommandIterationUpdate : public itk::Command
41 typedef CommandIterationUpdate Self;
42 typedef itk::Command Superclass;
43 typedef itk::SmartPointer<Self> Pointer;
46 CommandIterationUpdate() {};
48 typedef clitk::GenericOptimizer<args_info_clitkBLUTDIR> OptimizerType;
49 typedef const OptimizerType * OptimizerPointer;
51 // Set the generic optimizer
52 void SetOptimizer(OptimizerPointer o){m_Optimizer=o;}
55 void Execute(itk::Object *caller, const itk::EventObject & event)
57 Execute( (const itk::Object *)caller, event);
60 void Execute(const itk::Object * object, const itk::EventObject & event)
62 if( !(itk::IterationEvent().CheckEvent( &event )) )
67 m_Optimizer->OutputIterationInfo();
70 OptimizerPointer m_Optimizer;
73 //===========================================================================//
75 //==========================================================================//
76 BLUTDIRGenericFilter::BLUTDIRGenericFilter():
77 ImageToImageGenericFilter<Self>("Register DIR")
79 InitializeImageType<2>();
80 InitializeImageType<3>();
84 //=========================================================================//
86 //==========================================================================//
87 void BLUTDIRGenericFilter::SetArgsInfo(const args_info_clitkBLUTDIR & a){
89 if (m_ArgsInfo.reference_given) AddInputFilename(m_ArgsInfo.reference_arg);
91 if (m_ArgsInfo.target_given) {
92 AddInputFilename(m_ArgsInfo.target_arg);
95 if (m_ArgsInfo.output_given) SetOutputFilename(m_ArgsInfo.output_arg);
98 //=========================================================================//
99 //===========================================================================//
100 template<unsigned int Dim>
101 void BLUTDIRGenericFilter::InitializeImageType()
103 ADD_DEFAULT_IMAGE_TYPES(3);
105 //--------------------------------------------------------------------
107 //==============================================================================
108 //Creating an observer class that allows us to change parameters at subsequent levels
109 //==============================================================================
110 template <typename TRegistration,class args_info_clitkBLUTDIR>
111 class RegistrationInterfaceCommand : public itk::Command
114 typedef RegistrationInterfaceCommand Self;
115 typedef itk::Command Superclass;
116 typedef itk::SmartPointer<Self> Pointer;
119 RegistrationInterfaceCommand() { };
123 typedef TRegistration RegistrationType;
124 typedef RegistrationType * RegistrationPointer;
127 typedef typename RegistrationType::FixedImageType FixedImageType;
128 typedef typename FixedImageType::RegionType RegionType;
129 itkStaticConstMacro(ImageDimension, unsigned int,FixedImageType::ImageDimension);
130 typedef clitk::MultipleBSplineDeformableTransform<double, ImageDimension, ImageDimension> TransformType;
131 typedef clitk::MultipleBSplineDeformableTransformInitializer<TransformType, FixedImageType> InitializerType;
132 typedef typename InitializerType::CoefficientImageType CoefficientImageType;
133 typedef itk::CastImageFilter<CoefficientImageType, CoefficientImageType> CastImageFilterType;
134 typedef typename TransformType::ParametersType ParametersType;
135 typedef typename InitializerType::Pointer InitializerPointer;
136 typedef CommandIterationUpdate::Pointer CommandIterationUpdatePointer;
139 typedef clitk::GenericOptimizer<args_info_clitkBLUTDIR> GenericOptimizerType;
140 typedef typename GenericOptimizerType::Pointer GenericOptimizerPointer;
143 typedef typename RegistrationType::FixedImageType InternalImageType;
144 typedef clitk::GenericMetric<args_info_clitkBLUTDIR, InternalImageType, InternalImageType> GenericMetricType;
145 typedef typename GenericMetricType::Pointer GenericMetricPointer;
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)
152 if( !(itk::IterationEvent().CheckEvent( &event )) )
158 RegistrationPointer registration = dynamic_cast<RegistrationPointer>( object );
159 unsigned int numberOfLevels=registration->GetNumberOfLevels();
160 unsigned int currentLevel=registration->GetCurrentLevel()+1;
163 std::cout<<std::endl;
164 std::cout<<"========================================"<<std::endl;
165 std::cout<<"Starting resolution level "<<currentLevel<<" of "<<numberOfLevels<<"..."<<std::endl;
166 std::cout<<"========================================"<<std::endl;
167 std::cout<<std::endl;
172 // fixed image region pyramid
173 typedef clitk::MultiResolutionPyramidRegionFilter<InternalImageType> FixedImageRegionPyramidType;
174 typename FixedImageRegionPyramidType::Pointer fixedImageRegionPyramid=FixedImageRegionPyramidType::New();
175 fixedImageRegionPyramid->SetRegion(m_MetricRegion);
176 fixedImageRegionPyramid->SetSchedule(registration->GetFixedImagePyramid()->GetSchedule());
178 // Reinitialize the metric (!= number of samples)
179 m_GenericMetric= GenericMetricType::New();
180 m_GenericMetric->SetArgsInfo(m_ArgsInfo);
181 m_GenericMetric->SetFixedImage(registration->GetFixedImagePyramid()->GetOutput(registration->GetCurrentLevel()));
182 if (m_ArgsInfo.referenceMask_given) m_GenericMetric->SetFixedImageMask(registration->GetMetric()->GetFixedImageMask());
183 m_GenericMetric->SetFixedImageRegion(fixedImageRegionPyramid->GetOutput(registration->GetCurrentLevel()));
184 typedef itk::ImageToImageMetric< InternalImageType, InternalImageType > MetricType;
185 typename MetricType::Pointer metric=m_GenericMetric->GetMetricPointer();
186 registration->SetMetric(metric);
188 // Get the current coefficient image and make a COPY
189 typename itk::ImageDuplicator<CoefficientImageType>::Pointer caster = itk::ImageDuplicator<CoefficientImageType>::New();
190 std::vector<typename CoefficientImageType::Pointer> currentCoefficientImages = m_Initializer->GetTransform()->GetCoefficientImages();
191 for (unsigned i = 0; i < currentCoefficientImages.size(); ++i)
193 caster->SetInputImage(currentCoefficientImages[i]);
195 currentCoefficientImages[i] = caster->GetOutput();
199 // Write the intermediate result?
200 if (m_ArgsInfo.intermediate_given>=numberOfLevels)
201 writeImage<CoefficientImageType>(currentCoefficientImage, m_ArgsInfo.intermediate_arg[currentLevel-2], m_ArgsInfo.verbose_flag);
204 // Set the new transform properties
205 m_Initializer->SetImage(registration->GetFixedImagePyramid()->GetOutput(currentLevel-1));
206 if( m_Initializer->m_ControlPointSpacingIsGiven)
207 m_Initializer->SetControlPointSpacing(m_Initializer->m_ControlPointSpacingArray[registration->GetCurrentLevel()]);
208 if( m_Initializer->m_NumberOfControlPointsIsGiven)
209 m_Initializer->SetNumberOfControlPointsInsideTheImage(m_Initializer->m_NumberOfControlPointsInsideTheImageArray[registration->GetCurrentLevel()]);
211 // Reinitialize the transform
212 if (m_ArgsInfo.verbose_flag) std::cout<<"Initializing transform for level "<<currentLevel<<" of "<<numberOfLevels<<"..."<<std::endl;
213 m_Initializer->InitializeTransform();
214 ParametersType* newParameters= new typename TransformType::ParametersType(m_Initializer->GetTransform()->GetNumberOfParameters());
216 // DS : if we want to skip the last pyramid level, force to only 1 iteration
217 DD(m_ArgsInfo.skipLastPyramidLevel_flag);
218 if ((currentLevel == numberOfLevels) && (m_ArgsInfo.skipLastPyramidLevel_flag)) {
219 DD(m_ArgsInfo.maxIt_arg);
220 std::cout << "I skip the last pyramid level : set max iteration to 0" << std::endl;
221 m_ArgsInfo.maxIt_arg = 0;
222 DD(m_ArgsInfo.maxIt_arg);
225 // Reinitialize an Optimizer (!= number of parameters)
226 m_GenericOptimizer = GenericOptimizerType::New();
227 m_GenericOptimizer->SetArgsInfo(m_ArgsInfo);
228 m_GenericOptimizer->SetMaximize(m_Maximize);
229 m_GenericOptimizer->SetNumberOfParameters(m_Initializer->GetTransform()->GetNumberOfParameters());
232 typedef itk::SingleValuedNonLinearOptimizer OptimizerType;
233 OptimizerType::Pointer optimizer = m_GenericOptimizer->GetOptimizerPointer();
234 optimizer->AddObserver( itk::IterationEvent(), m_CommandIterationUpdate);
235 registration->SetOptimizer(optimizer);
236 m_CommandIterationUpdate->SetOptimizer(m_GenericOptimizer);
238 // Set the previous transform parameters to the registration
239 // if(m_Initializer->m_Parameters!=NULL )delete m_Initializer->m_Parameters;
240 m_Initializer->SetInitialParameters(currentCoefficientImages, *newParameters);
241 registration->SetInitialTransformParametersOfNextLevel(*newParameters);
245 void Execute(const itk::Object * , const itk::EventObject & )
250 void SetInitializer(InitializerPointer i){m_Initializer=i;}
251 InitializerPointer m_Initializer;
253 void SetArgsInfo(args_info_clitkBLUTDIR a){m_ArgsInfo=a;}
254 args_info_clitkBLUTDIR m_ArgsInfo;
256 void SetCommandIterationUpdate(CommandIterationUpdatePointer c){m_CommandIterationUpdate=c;};
257 CommandIterationUpdatePointer m_CommandIterationUpdate;
259 GenericOptimizerPointer m_GenericOptimizer;
260 void SetMaximize(bool b){m_Maximize=b;}
263 GenericMetricPointer m_GenericMetric;
264 void SetMetricRegion(RegionType i){m_MetricRegion=i;}
265 RegionType m_MetricRegion;
270 //==============================================================================
271 // Update with the number of dimensions and pixeltype
272 //==============================================================================
273 template<class InputImageType>
274 void BLUTDIRGenericFilter::UpdateWithInputImageType()
276 //=============================================================================
278 //=============================================================================
279 bool threadsGiven=m_ArgsInfo.threads_given;
280 int threads=m_ArgsInfo.threads_arg;
281 typedef typename InputImageType::PixelType PixelType;
283 typedef double TCoordRep;
285 typename InputImageType::Pointer fixedImage = this->template GetInput<InputImageType>(0);
287 typename InputImageType::Pointer inputFixedImage = this->template GetInput<InputImageType>(0);
290 typename InputImageType::Pointer movingImage = this->template GetInput<InputImageType>(1);
292 typename InputImageType::Pointer inputMovingImage = this->template GetInput<InputImageType>(1);
294 typedef itk::Image< PixelType,InputImageType::ImageDimension > FixedImageType;
295 typedef itk::Image< PixelType, InputImageType::ImageDimension> MovingImageType;
296 const unsigned int SpaceDimension = InputImageType::ImageDimension;
297 //Whatever the pixel type, internally we work with an image represented in float
298 //Reading reference image
299 if (m_Verbose) std::cout<<"Reading images..."<<std::endl;
300 //=======================================================
302 //=======================================================
303 typename FixedImageType::Pointer croppedFixedImage=fixedImage;
304 //=======================================================
306 //=======================================================
307 // The original input region
308 typename FixedImageType::RegionType fixedImageRegion = fixedImage->GetLargestPossibleRegion();
310 // The transform region with respect to the input region:
311 // where should the transform be DEFINED (depends on mask)
312 typename FixedImageType::RegionType transformRegion = fixedImage->GetLargestPossibleRegion();
313 typename FixedImageType::RegionType::SizeType transformRegionSize=transformRegion.GetSize();
314 typename FixedImageType::RegionType::IndexType transformRegionIndex=transformRegion.GetIndex();
315 typename FixedImageType::PointType transformRegionOrigin=fixedImage->GetOrigin();
317 // The metric region with respect to the extracted transform region:
318 // where should the metric be CALCULATED (depends on transform)
319 typename FixedImageType::RegionType metricRegion = fixedImage->GetLargestPossibleRegion();
320 typename FixedImageType::RegionType::SizeType metricRegionSize=metricRegion.GetSize();
321 typename FixedImageType::RegionType::IndexType metricRegionIndex=metricRegion.GetIndex();
322 typename FixedImageType::PointType metricRegionOrigin=fixedImage->GetOrigin();
325 //===========================================================================
326 // If given, we connect a mask to reference or target
327 //============================================================================
328 typedef itk::ImageMaskSpatialObject< InputImageType::ImageDimension > MaskType;
329 typedef itk::Image< unsigned char, InputImageType::ImageDimension > ImageLabelType;
330 typename MaskType::Pointer fixedMask = NULL;
331 typename ImageLabelType::Pointer labels = NULL;
332 if (m_ArgsInfo.referenceMask_given)
334 fixedMask = MaskType::New();
335 labels = ImageLabelType::New();
336 typedef itk::ImageFileReader< ImageLabelType > LabelReaderType;
337 typename LabelReaderType::Pointer labelReader = LabelReaderType::New();
338 labelReader->SetFileName(m_ArgsInfo.referenceMask_arg);
341 labelReader->Update();
343 catch( itk::ExceptionObject & err )
345 std::cerr << "ExceptionObject caught while reading mask or labels !" << std::endl;
346 std::cerr << err << std::endl;
349 if (m_Verbose)std::cout <<"Reference image mask was read..." <<std::endl;
352 typedef itk::ResampleImageFilter<ImageLabelType, ImageLabelType> ResamplerType;
353 typename ResamplerType::Pointer resampler = ResamplerType::New();
354 typedef itk::NearestNeighborInterpolateImageFunction<ImageLabelType, TCoordRep> InterpolatorType;
355 typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
356 resampler->SetOutputParametersFromImage(fixedImage);
357 resampler->SetInterpolator(interpolator);
358 resampler->SetInput(labelReader->GetOutput());
360 labels = resampler->GetOutput();
362 // Set the image to the spatialObject
363 fixedMask->SetImage(labels);
365 // Find the bounding box of the "inside" label
366 typedef itk::LabelGeometryImageFilter<ImageLabelType> GeometryImageFilterType;
367 typename GeometryImageFilterType::Pointer geometryImageFilter=GeometryImageFilterType::New();
368 geometryImageFilter->SetInput(labels);
369 geometryImageFilter->Update();
370 typename GeometryImageFilterType::BoundingBoxType boundingBox = geometryImageFilter->GetBoundingBox(1);
372 // Limit the transform region to the mask
373 for (unsigned int i=0; i<InputImageType::ImageDimension; i++)
375 transformRegionIndex[i]=boundingBox[2*i];
376 transformRegionSize[i]=boundingBox[2*i+1]-boundingBox[2*i]+1;
378 transformRegion.SetSize(transformRegionSize);
379 transformRegion.SetIndex(transformRegionIndex);
380 fixedImage->TransformIndexToPhysicalPoint(transformRegion.GetIndex(), transformRegionOrigin);
382 // Crop the fixedImage to the bounding box to facilitate multi-resolution
383 typedef itk::ExtractImageFilter<FixedImageType,FixedImageType> ExtractImageFilterType;
384 typename ExtractImageFilterType::Pointer extractImageFilter=ExtractImageFilterType::New();
385 extractImageFilter->SetInput(fixedImage);
386 extractImageFilter->SetExtractionRegion(transformRegion);
387 extractImageFilter->Update();
388 croppedFixedImage=extractImageFilter->GetOutput();
390 // Update the metric region
391 metricRegion = croppedFixedImage->GetLargestPossibleRegion();
392 metricRegionIndex=metricRegion.GetIndex();
393 croppedFixedImage->TransformIndexToPhysicalPoint(metricRegionIndex, metricRegionOrigin);
395 // Set start index to zero (with respect to croppedFixedImage/transform region)
396 metricRegionIndex.Fill(0);
397 metricRegion.SetIndex(metricRegionIndex);
398 croppedFixedImage->SetRegions(metricRegion);
399 croppedFixedImage->SetOrigin(metricRegionOrigin);
402 typedef itk::ImageMaskSpatialObject< InputImageType::ImageDimension > MaskType;
403 typename MaskType::Pointer movingMask=NULL;
404 if (m_ArgsInfo.targetMask_given)
406 movingMask= MaskType::New();
407 typedef itk::Image< unsigned char, InputImageType::ImageDimension > ImageMaskType;
408 typedef itk::ImageFileReader< ImageMaskType > MaskReaderType;
409 typename MaskReaderType::Pointer maskReader = MaskReaderType::New();
410 maskReader->SetFileName(m_ArgsInfo.targetMask_arg);
413 maskReader->Update();
415 catch( itk::ExceptionObject & err )
417 std::cerr << "ExceptionObject caught !" << std::endl;
418 std::cerr << err << std::endl;
420 if (m_Verbose)std::cout <<"Target image mask was read..." <<std::endl;
422 movingMask->SetImage( maskReader->GetOutput() );
426 //=======================================================
428 //=======================================================
432 // Fixed image region
433 std::cout<<"The fixed image has its origin at "<<fixedImage->GetOrigin()<<std::endl
434 <<"The fixed image region starts at index "<<fixedImageRegion.GetIndex()<<std::endl
435 <<"The fixed image region has size "<< fixedImageRegion.GetSize()<<std::endl;
438 std::cout<<"The transform has its origin at "<<transformRegionOrigin<<std::endl
439 <<"The transform region will start at index "<<transformRegion.GetIndex()<<std::endl
440 <<"The transform region has size "<< transformRegion.GetSize()<<std::endl;
443 std::cout<<"The metric region has its origin at "<<metricRegionOrigin<<std::endl
444 <<"The metric region will start at index "<<metricRegion.GetIndex()<<std::endl
445 <<"The metric region has size "<< metricRegion.GetSize()<<std::endl;
450 //=======================================================
451 // Pyramids (update them for transform initializer)
452 //=======================================================
453 typedef itk::RecursiveMultiResolutionPyramidImageFilter< FixedImageType, FixedImageType> FixedImagePyramidType;
454 typedef itk::RecursiveMultiResolutionPyramidImageFilter< MovingImageType, MovingImageType> MovingImagePyramidType;
455 typename FixedImagePyramidType::Pointer fixedImagePyramid = FixedImagePyramidType::New();
456 typename MovingImagePyramidType::Pointer movingImagePyramid = MovingImagePyramidType::New();
457 fixedImagePyramid->SetUseShrinkImageFilter(false);
458 fixedImagePyramid->SetInput(croppedFixedImage);
459 fixedImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
460 movingImagePyramid->SetUseShrinkImageFilter(false);
461 movingImagePyramid->SetInput(movingImage);
462 movingImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
463 if (m_Verbose) std::cout<<"Creating the image pyramid..."<<std::endl;
464 fixedImagePyramid->Update();
465 movingImagePyramid->Update();
466 typedef clitk::MultiResolutionPyramidRegionFilter<FixedImageType> FixedImageRegionPyramidType;
467 typename FixedImageRegionPyramidType::Pointer fixedImageRegionPyramid=FixedImageRegionPyramidType::New();
468 fixedImageRegionPyramid->SetRegion(metricRegion);
469 fixedImageRegionPyramid->SetSchedule(fixedImagePyramid->GetSchedule());
472 //=======================================================
473 // Rigid or Affine Transform
474 //=======================================================
475 typedef itk::AffineTransform <double,3> RigidTransformType;
476 RigidTransformType::Pointer rigidTransform=NULL;
477 if (m_ArgsInfo.initMatrix_given)
479 if(m_Verbose) std::cout<<"Reading the prior transform matrix "<< m_ArgsInfo.initMatrix_arg<<"..."<<std::endl;
480 rigidTransform=RigidTransformType::New();
481 itk::Matrix<double,4,4> rigidTransformMatrix=clitk::ReadMatrix3D(m_ArgsInfo.initMatrix_arg);
484 itk::Matrix<double,3,3> finalRotation = clitk::GetRotationalPartMatrix3D(rigidTransformMatrix);
485 rigidTransform->SetMatrix(finalRotation);
487 //Set the translation
488 itk::Vector<double,3> finalTranslation = clitk::GetTranslationPartMatrix3D(rigidTransformMatrix);
489 rigidTransform->SetTranslation(finalTranslation);
493 //=======================================================
494 // B-LUT FFD Transform
495 //=======================================================
496 typedef clitk::MultipleBSplineDeformableTransform<TCoordRep,InputImageType::ImageDimension, SpaceDimension > TransformType;
497 typename TransformType::Pointer transform = TransformType::New();
498 if (labels) transform->SetLabels(labels);
499 if (rigidTransform) transform->SetBulkTransform(rigidTransform);
501 //-------------------------------------------------------------------------
502 // The transform initializer
503 //-------------------------------------------------------------------------
504 typedef clitk::MultipleBSplineDeformableTransformInitializer< TransformType,FixedImageType> InitializerType;
505 typename InitializerType::Pointer initializer = InitializerType::New();
506 initializer->SetVerbose(m_Verbose);
507 initializer->SetImage(fixedImagePyramid->GetOutput(0));
508 initializer->SetTransform(transform);
510 //-------------------------------------------------------------------------
512 //-------------------------------------------------------------------------
513 typename FixedImageType::RegionType::SizeType splineOrders ;
514 splineOrders.Fill(3);
515 if (m_ArgsInfo.order_given)
516 for(unsigned int i=0; i<InputImageType::ImageDimension;i++)
517 splineOrders[i]=m_ArgsInfo.order_arg[i];
518 if (m_Verbose) std::cout<<"Setting the spline orders to "<<splineOrders<<"..."<<std::endl;
519 initializer->SetSplineOrders(splineOrders);
521 //-------------------------------------------------------------------------
523 //-------------------------------------------------------------------------
526 if (m_ArgsInfo.spacing_given)
528 initializer->m_ControlPointSpacingArray.resize(m_ArgsInfo.levels_arg);
529 initializer->SetControlPointSpacing(m_ArgsInfo.spacing_arg);
530 initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1]=initializer->m_ControlPointSpacing;
531 if (m_Verbose) std::cout<<"Using a control point spacing of "<<initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1]
532 <<" at level "<<m_ArgsInfo.levels_arg<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;
534 for (int i=1; i<m_ArgsInfo.levels_arg; i++ )
536 initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1-i]=initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-i]*2;
537 if (m_Verbose) std::cout<<"Using a control point spacing of "<<initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1-i]
538 <<" at level "<<m_ArgsInfo.levels_arg-i<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;
544 if (m_ArgsInfo.control_given)
546 initializer->m_NumberOfControlPointsInsideTheImageArray.resize(m_ArgsInfo.levels_arg);
547 initializer->SetNumberOfControlPointsInsideTheImage(m_ArgsInfo.control_arg);
548 initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1]=initializer->m_NumberOfControlPointsInsideTheImage;
549 if (m_Verbose) std::cout<<"Using "<< initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1]<<"control points inside the image"
550 <<" at level "<<m_ArgsInfo.levels_arg<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;
552 for (int i=1; i<m_ArgsInfo.levels_arg; i++ )
554 for(unsigned int j=0;j<InputImageType::ImageDimension;j++)
555 initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1-i][j]=ceil ((double)initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-i][j]/2.);
556 // initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1-i]=ceil ((double)initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-i]/2.);
557 if (m_Verbose) std::cout<<"Using "<< initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1-i]<<"control points inside the image"
558 <<" at level "<<m_ArgsInfo.levels_arg<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;
563 // Inialize on the first level
564 if (m_ArgsInfo.verbose_flag) std::cout<<"Initializing transform for level 1 of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;
565 if (m_ArgsInfo.spacing_given) initializer->SetControlPointSpacing( initializer->m_ControlPointSpacingArray[0]);
566 if (m_ArgsInfo.control_given) initializer->SetNumberOfControlPointsInsideTheImage(initializer->m_NumberOfControlPointsInsideTheImageArray[0]);
567 if (m_ArgsInfo.samplingFactor_given) initializer->SetSamplingFactors(m_ArgsInfo.samplingFactor_arg);
570 initializer->InitializeTransform();
572 //-------------------------------------------------------------------------
573 // Initial parameters (passed by reference)
574 //-------------------------------------------------------------------------
575 typedef typename TransformType::ParametersType ParametersType;
576 const unsigned int numberOfParameters = transform->GetNumberOfParameters();
577 ParametersType parameters(numberOfParameters);
578 parameters.Fill( 0.0 );
579 transform->SetParameters( parameters );
580 if (m_ArgsInfo.initCoeff_given) initializer->SetInitialParameters(m_ArgsInfo.initCoeff_arg, parameters);
583 //=======================================================
585 //=======================================================
586 typedef clitk::GenericInterpolator<args_info_clitkBLUTDIR, FixedImageType, TCoordRep > GenericInterpolatorType;
587 typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
588 genericInterpolator->SetArgsInfo(m_ArgsInfo);
589 typedef itk::InterpolateImageFunction< FixedImageType, TCoordRep > InterpolatorType;
590 typename InterpolatorType::Pointer interpolator=genericInterpolator->GetInterpolatorPointer();
593 //=======================================================
595 //=======================================================
596 typedef clitk::GenericMetric<args_info_clitkBLUTDIR, FixedImageType,MovingImageType > GenericMetricType;
597 typename GenericMetricType::Pointer genericMetric=GenericMetricType::New();
598 genericMetric->SetArgsInfo(m_ArgsInfo);
599 genericMetric->SetFixedImage(fixedImagePyramid->GetOutput(0));
600 if (fixedMask) genericMetric->SetFixedImageMask(fixedMask);
601 genericMetric->SetFixedImageRegion(fixedImageRegionPyramid->GetOutput(0));
602 typedef itk::ImageToImageMetric< FixedImageType, MovingImageType > MetricType;
603 typename MetricType::Pointer metric=genericMetric->GetMetricPointer();
604 if (movingMask) metric->SetMovingImageMask(movingMask);
606 #ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
608 metric->SetNumberOfThreads( threads );
609 if (m_Verbose) std::cout<< "Using " << threads << " threads." << std::endl;
612 if (m_Verbose) std::cout<<"Not setting the number of threads (not compiled with USE_OPTIMIZED_REGISTRATION_METHODS)..."<<std::endl;
616 //=======================================================
618 //=======================================================
619 typedef clitk::GenericOptimizer<args_info_clitkBLUTDIR> GenericOptimizerType;
620 GenericOptimizerType::Pointer genericOptimizer = GenericOptimizerType::New();
621 genericOptimizer->SetArgsInfo(m_ArgsInfo);
622 genericOptimizer->SetMaximize(genericMetric->GetMaximize());
623 genericOptimizer->SetNumberOfParameters(transform->GetNumberOfParameters());
624 typedef itk::SingleValuedNonLinearOptimizer OptimizerType;
625 OptimizerType::Pointer optimizer = genericOptimizer->GetOptimizerPointer();
628 //=======================================================
630 //=======================================================
631 typedef itk::MultiResolutionImageRegistrationMethod< FixedImageType, MovingImageType > RegistrationType;
632 typename RegistrationType::Pointer registration = RegistrationType::New();
633 registration->SetMetric( metric );
634 registration->SetOptimizer( optimizer );
635 registration->SetInterpolator( interpolator );
636 registration->SetTransform (transform);
638 registration->SetNumberOfThreads(threads);
639 if (m_Verbose) std::cout<< "Using " << threads << " threads." << std::endl;
641 registration->SetFixedImage( croppedFixedImage );
642 registration->SetMovingImage( movingImage );
643 registration->SetFixedImageRegion( metricRegion );
644 registration->SetFixedImagePyramid( fixedImagePyramid );
645 registration->SetMovingImagePyramid( movingImagePyramid );
646 registration->SetInitialTransformParameters( transform->GetParameters() );
647 registration->SetNumberOfLevels( m_ArgsInfo.levels_arg );
648 if (m_Verbose) std::cout<<"Setting the number of resolution levels to "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;
651 //================================================================================================
653 //================================================================================================
656 // Output iteration info
657 CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
658 observer->SetOptimizer(genericOptimizer);
659 optimizer->AddObserver( itk::IterationEvent(), observer );
662 typedef RegistrationInterfaceCommand<RegistrationType,args_info_clitkBLUTDIR> CommandType;
663 typename CommandType::Pointer command = CommandType::New();
664 command->SetInitializer(initializer);
665 command->SetArgsInfo(m_ArgsInfo);
666 command->SetCommandIterationUpdate(observer);
667 command->SetMaximize(genericMetric->GetMaximize());
668 command->SetMetricRegion(metricRegion);
669 registration->AddObserver( itk::IterationEvent(), command );
673 //=======================================================
675 //=======================================================
676 if (m_Verbose) std::cout << std::endl << "Starting Registration" << std::endl;
680 registration->StartRegistration();
682 catch( itk::ExceptionObject & err )
684 std::cerr << "ExceptionObject caught while registering!" << std::endl;
685 std::cerr << err << std::endl;
690 //=======================================================
692 //=======================================================
693 OptimizerType::ParametersType finalParameters = registration->GetLastTransformParameters();
694 transform->SetParameters( finalParameters );
697 std::cout<<"Stop condition description: "
698 <<registration->GetOptimizer()->GetStopConditionDescription()<<std::endl;
702 //=======================================================
703 // Get the BSpline coefficient images and write them
704 //=======================================================
705 if (m_ArgsInfo.coeff_given)
707 typedef typename TransformType::CoefficientImageType CoefficientImageType;
708 std::vector<typename CoefficientImageType::Pointer> coefficientImages = transform->GetCoefficientImages();
709 typedef itk::ImageFileWriter<CoefficientImageType> CoeffWriterType;
710 typename CoeffWriterType::Pointer coeffWriter = CoeffWriterType::New();
711 unsigned nLabels = transform->GetnLabels();
713 std::string fname(m_ArgsInfo.coeff_arg);
714 int dotpos = fname.length() - 1;
715 while (dotpos >= 0 && fname[dotpos] != '.')
718 for (unsigned i = 0; i < nLabels; ++i)
720 std::ostringstream osfname;
721 osfname << fname.substr(0, dotpos) << '_' << i << fname.substr(dotpos);
722 coeffWriter->SetInput(coefficientImages[i]);
723 coeffWriter->SetFileName(osfname.str());
724 coeffWriter->Update();
730 //=======================================================
731 // Compute the DVF (only deformable transform)
732 //=======================================================
733 typedef itk::Vector< float, SpaceDimension > DisplacementType;
734 typedef itk::Image< DisplacementType, InputImageType::ImageDimension > DeformationFieldType;
735 typedef itk::TransformToDeformationFieldSource<DeformationFieldType, double> ConvertorType;
736 typename ConvertorType::Pointer filter= ConvertorType::New();
737 filter->SetNumberOfThreads(1);
738 transform->SetBulkTransform(NULL);
739 filter->SetTransform(transform);
740 filter->SetOutputParametersFromImage(fixedImage);
742 typename DeformationFieldType::Pointer field = filter->GetOutput();
745 //=======================================================
747 //=======================================================
748 typedef itk::ImageFileWriter< DeformationFieldType > FieldWriterType;
749 typename FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
750 fieldWriter->SetFileName( m_ArgsInfo.vf_arg );
751 fieldWriter->SetInput( field );
754 fieldWriter->Update();
756 catch( itk::ExceptionObject & excp )
758 std::cerr << "Exception thrown writing the DVF" << std::endl;
759 std::cerr << excp << std::endl;
764 //=======================================================
765 // Resample the moving image
766 //=======================================================
767 typedef itk::ResampleImageFilter< MovingImageType, FixedImageType > ResampleFilterType;
768 typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
769 if (rigidTransform) transform->SetBulkTransform(rigidTransform);
770 resampler->SetTransform( transform );
771 resampler->SetInput( movingImage);
772 resampler->SetOutputParametersFromImage(fixedImage);
774 typename FixedImageType::Pointer result=resampler->GetOutput();
776 // typedef itk::WarpImageFilter< MovingImageType, FixedImageType, DeformationFieldType > WarpFilterType;
777 // typename WarpFilterType::Pointer warp = WarpFilterType::New();
779 // warp->SetDeformationField( field );
780 // warp->SetInput( movingImageReader->GetOutput() );
781 // warp->SetOutputOrigin( fixedImage->GetOrigin() );
782 // warp->SetOutputSpacing( fixedImage->GetSpacing() );
783 // warp->SetOutputDirection( fixedImage->GetDirection() );
784 // warp->SetEdgePaddingValue( 0.0 );
788 //=======================================================
789 // Write the warped image
790 //=======================================================
791 typedef itk::ImageFileWriter< FixedImageType > WriterType;
792 typename WriterType::Pointer writer = WriterType::New();
793 writer->SetFileName( m_ArgsInfo.output_arg );
794 writer->SetInput( result );
800 catch( itk::ExceptionObject & err )
802 std::cerr << "ExceptionObject caught !" << std::endl;
803 std::cerr << err << std::endl;
808 //=======================================================
809 // Calculate the difference after the deformable transform
810 //=======================================================
811 typedef clitk::DifferenceImageFilter< FixedImageType, FixedImageType> DifferenceFilterType;
812 if (m_ArgsInfo.after_given)
814 typename DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
815 difference->SetValidInput( fixedImage );
816 difference->SetTestInput( result );
820 difference->Update();
822 catch( itk::ExceptionObject & err )
824 std::cerr << "ExceptionObject caught calculating the difference !" << std::endl;
825 std::cerr << err << std::endl;
829 typename WriterType::Pointer differenceWriter=WriterType::New();
830 differenceWriter->SetInput(difference->GetOutput());
831 differenceWriter->SetFileName(m_ArgsInfo.after_arg);
832 differenceWriter->Update();
837 //=======================================================
838 // Calculate the difference before the deformable transform
839 //=======================================================
840 if( m_ArgsInfo.before_given )
843 typename FixedImageType::Pointer moving=FixedImageType::New();
844 if (m_ArgsInfo.initMatrix_given)
846 typedef itk::ResampleImageFilter<MovingImageType, FixedImageType> ResamplerType;
847 typename ResamplerType::Pointer resampler=ResamplerType::New();
848 resampler->SetInput(movingImage);
849 resampler->SetOutputOrigin(fixedImage->GetOrigin());
850 resampler->SetSize(fixedImage->GetLargestPossibleRegion().GetSize());
851 resampler->SetOutputSpacing(fixedImage->GetSpacing());
852 resampler->SetDefaultPixelValue( 0. );
853 if (rigidTransform ) resampler->SetTransform(rigidTransform);
855 moving=resampler->GetOutput();
860 typename DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
861 difference->SetValidInput( fixedImage );
862 difference->SetTestInput( moving );
866 difference->Update();
868 catch( itk::ExceptionObject & err )
870 std::cerr << "ExceptionObject caught calculating the difference !" << std::endl;
871 std::cerr << err << std::endl;
875 typename WriterType::Pointer differenceWriter=WriterType::New();
876 writer->SetFileName( m_ArgsInfo.before_arg );
877 writer->SetInput( difference->GetOutput() );
886 #endif // #define clitkBLUTDIRGenericFilter_txx