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 ===========================================================================**/
18 #ifndef _clitkMultiResolutionPDEDeformableRegistration_txx
19 #define _clitkMultiResolutionPDEDeformableRegistration_txx
20 #include "clitkMultiResolutionPDEDeformableRegistration.h"
22 #include "itkRecursiveMultiResolutionPyramidImageFilter.h"
23 #include "itkImageRegionIterator.h"
24 #include "vnl/vnl_math.h"
31 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
32 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
33 ::MultiResolutionPDEDeformableRegistration()
36 this->SetNumberOfRequiredInputs(2);
38 typename DefaultRegistrationType::Pointer registrator =
39 DefaultRegistrationType::New();
40 m_RegistrationFilter = static_cast<RegistrationType*>(
41 registrator.GetPointer() );
43 m_MovingImagePyramid = MovingImagePyramidType::New();
44 m_FixedImagePyramid = FixedImagePyramidType::New();
45 m_FieldExpander = FieldExpanderType::New();
46 m_InitialDeformationField = NULL;
49 m_NumberOfIterations.resize( m_NumberOfLevels );
50 m_FixedImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
51 m_MovingImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
54 for( ilevel = 0; ilevel < m_NumberOfLevels; ilevel++ )
56 m_NumberOfIterations[ilevel] = 10;
60 m_StopRegistrationFlag = false;
66 * Set the moving image image.
68 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
70 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
72 const MovingImageType * ptr )
74 this->itk::ProcessObject::SetNthInput( 2, const_cast< MovingImageType * >( ptr ) );
79 * Get the moving image image.
81 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
82 const typename MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
84 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
85 ::GetMovingImage(void) const
87 return dynamic_cast< const MovingImageType * >
88 ( this->itk::ProcessObject::GetInput( 2 ) );
93 * Set the fixed image.
95 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
97 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
99 const FixedImageType * ptr )
101 this->itk::ProcessObject::SetNthInput( 1, const_cast< FixedImageType * >( ptr ) );
106 * Get the fixed image.
108 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
109 const typename MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
111 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
112 ::GetFixedImage(void) const
114 return dynamic_cast< const FixedImageType * >
115 ( this->itk::ProcessObject::GetInput( 1 ) );
121 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
122 std::vector<itk::SmartPointer<itk::DataObject> >::size_type
123 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
124 ::GetNumberOfValidRequiredInputs() const
126 typename std::vector<itk::SmartPointer<itk::DataObject> >::size_type num = 0;
128 if (this->GetFixedImage())
133 if (this->GetMovingImage())
143 * Set the number of multi-resolution levels
145 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
147 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
151 if( m_NumberOfLevels != num )
154 m_NumberOfLevels = num;
155 m_NumberOfIterations.resize( m_NumberOfLevels );
158 if( m_MovingImagePyramid && m_MovingImagePyramid->GetNumberOfLevels() != num )
160 m_MovingImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
162 if( m_FixedImagePyramid && m_FixedImagePyramid->GetNumberOfLevels() != num )
164 m_FixedImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
170 * Standard PrintSelf method.
172 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
174 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
175 ::PrintSelf(std::ostream& os, itk::Indent indent) const
177 Superclass::PrintSelf(os, indent);
178 os << indent << "NumberOfLevels: " << m_NumberOfLevels << std::endl;
179 os << indent << "CurrentLevel: " << m_CurrentLevel << std::endl;
181 os << indent << "NumberOfIterations: [";
183 for( ilevel = 0; ilevel < m_NumberOfLevels - 1; ilevel++ )
185 os << m_NumberOfIterations[ilevel] << ", ";
187 os << m_NumberOfIterations[ilevel] << "]" << std::endl;
189 os << indent << "RegistrationFilter: ";
190 os << m_RegistrationFilter.GetPointer() << std::endl;
191 os << indent << "MovingImagePyramid: ";
192 os << m_MovingImagePyramid.GetPointer() << std::endl;
193 os << indent << "FixedImagePyramid: ";
194 os << m_FixedImagePyramid.GetPointer() << std::endl;
196 os << indent << "FieldExpander: ";
197 os << m_FieldExpander.GetPointer() << std::endl;
199 os << indent << "StopRegistrationFlag: ";
200 os << m_StopRegistrationFlag << std::endl;
205 * Perform a the deformable registration using a multiresolution scheme
206 * using an internal mini-pipeline
208 * ref_pyramid -> registrator -> field_expander --|| tempField
209 * test_pyramid -> | |
211 * --------------------------------
213 * A tempField image is used to break the cycle between the
214 * registrator and field_expander.
217 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
219 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
222 // Check for NULL images and pointers
223 MovingImageConstPointer movingImage = this->GetMovingImage();
224 FixedImageConstPointer fixedImage = this->GetFixedImage();
226 if( !movingImage || !fixedImage )
228 itkExceptionMacro( << "Fixed and/or moving image not set" );
231 if( !m_MovingImagePyramid || !m_FixedImagePyramid )
233 itkExceptionMacro( << "Fixed and/or moving pyramid not set" );
236 if( !m_RegistrationFilter )
238 itkExceptionMacro( << "Registration filter not set" );
241 if( this->m_InitialDeformationField && this->GetInput(0) )
243 itkExceptionMacro( << "Only one initial deformation can be given. "
244 << "SetInitialDeformationField should not be used in "
245 << "cunjunction with SetArbitraryInitialDeformationField "
249 //Update the number of levels for the pyramids
250 this->SetNumberOfLevels(m_NumberOfLevels);
252 // Create the image pyramids.
253 m_MovingImagePyramid->SetInput( movingImage );
254 m_MovingImagePyramid->UpdateLargestPossibleRegion();
256 m_FixedImagePyramid->SetInput( fixedImage );
257 m_FixedImagePyramid->UpdateLargestPossibleRegion();
261 m_StopRegistrationFlag = false;
263 unsigned int movingLevel = vnl_math_min( (int) m_CurrentLevel,
264 (int) m_MovingImagePyramid->GetNumberOfLevels() );
266 unsigned int fixedLevel = vnl_math_min( (int) m_CurrentLevel,
267 (int) m_FixedImagePyramid->GetNumberOfLevels() );
269 DeformationFieldPointer tempField = NULL;
271 DeformationFieldPointer inputPtr =
272 const_cast< DeformationFieldType * >( this->GetInput(0) );
274 if ( this->m_InitialDeformationField )
276 tempField = this->m_InitialDeformationField;
280 // Arbitrary initial deformation field is set.
281 // smooth it and resample
284 tempField = inputPtr;
286 typedef itk::RecursiveGaussianImageFilter< DeformationFieldType,
287 DeformationFieldType> GaussianFilterType;
288 typename GaussianFilterType::Pointer smoother
289 = GaussianFilterType::New();
291 for (unsigned int dim=0; dim<DeformationFieldType::ImageDimension; ++dim)
293 // sigma accounts for the subsampling of the pyramid
294 double sigma = 0.5 * static_cast<float>(
295 m_FixedImagePyramid->GetSchedule()[fixedLevel][dim] );
297 // but also for a possible discrepancy in the spacing
298 sigma *= fixedImage->GetSpacing()[dim]
299 / inputPtr->GetSpacing()[dim];
301 smoother->SetInput( tempField );
302 smoother->SetSigma( sigma );
303 smoother->SetDirection( dim );
307 tempField = smoother->GetOutput();
308 tempField->DisconnectPipeline();
313 m_FieldExpander->SetInput( tempField );
315 typename FloatImageType::Pointer fi =
316 m_FixedImagePyramid->GetOutput( fixedLevel );
317 m_FieldExpander->SetSize(
318 fi->GetLargestPossibleRegion().GetSize() );
319 m_FieldExpander->SetOutputStartIndex(
320 fi->GetLargestPossibleRegion().GetIndex() );
321 m_FieldExpander->SetOutputOrigin( fi->GetOrigin() );
322 m_FieldExpander->SetOutputSpacing( fi->GetSpacing());
323 m_FieldExpander->SetOutputDirection( fi->GetDirection());
325 m_FieldExpander->UpdateLargestPossibleRegion();
326 m_FieldExpander->SetInput( NULL );
327 tempField = m_FieldExpander->GetOutput();
328 tempField->DisconnectPipeline();
332 bool lastShrinkFactorsAllOnes = false;
333 while ( !this->Halt() )
336 if( tempField.IsNull() )
338 #if ITK_VERSION_MAJOR >= 4
339 m_RegistrationFilter->SetInitialDisplacementField( NULL );
341 m_RegistrationFilter->SetInitialDeformationField( NULL );
346 // Resample the field to be the same size as the fixed image
347 // at the current level
348 m_FieldExpander->SetInput( tempField );
350 typename FloatImageType::Pointer fi =
351 m_FixedImagePyramid->GetOutput( fixedLevel );
352 m_FieldExpander->SetSize(
353 fi->GetLargestPossibleRegion().GetSize() );
354 m_FieldExpander->SetOutputStartIndex(
355 fi->GetLargestPossibleRegion().GetIndex() );
356 m_FieldExpander->SetOutputOrigin( fi->GetOrigin() );
357 m_FieldExpander->SetOutputSpacing( fi->GetSpacing());
359 m_FieldExpander->UpdateLargestPossibleRegion();
360 m_FieldExpander->SetInput( NULL );
361 tempField = m_FieldExpander->GetOutput();
362 tempField->DisconnectPipeline();
364 #if ITK_VERSION_MAJOR >= 4
365 m_RegistrationFilter->SetInitialDisplacementField( tempField );
367 m_RegistrationFilter->SetInitialDeformationField( tempField );
372 // setup registration filter and pyramids
373 m_RegistrationFilter->SetMovingImage( m_MovingImagePyramid->GetOutput(movingLevel) );
374 m_RegistrationFilter->SetFixedImage( m_FixedImagePyramid->GetOutput(fixedLevel) );
375 m_RegistrationFilter->SetNumberOfIterations(
376 m_NumberOfIterations[m_CurrentLevel] );
378 // cache shrink factors for computing the next expand factors.
379 lastShrinkFactorsAllOnes = true;
380 for( unsigned int idim = 0; idim < ImageDimension; idim++ )
382 if ( m_FixedImagePyramid->GetSchedule()[fixedLevel][idim] > 1 )
384 lastShrinkFactorsAllOnes = false;
389 // Invoke an iteration event.
390 this->InvokeEvent( itk::IterationEvent() );
392 // compute new deformation field
393 m_RegistrationFilter->UpdateLargestPossibleRegion();
394 tempField = m_RegistrationFilter->GetOutput();
395 tempField->DisconnectPipeline();
397 // Increment level counter.
399 movingLevel = vnl_math_min( (int) m_CurrentLevel,
400 (int) m_MovingImagePyramid->GetNumberOfLevels() );
401 fixedLevel = vnl_math_min( (int) m_CurrentLevel,
402 (int) m_FixedImagePyramid->GetNumberOfLevels() );
404 // We can release data from pyramid which are no longer required.
405 if ( movingLevel > 0 )
407 m_MovingImagePyramid->GetOutput( movingLevel - 1 )->ReleaseData();
411 m_FixedImagePyramid->GetOutput( fixedLevel - 1 )->ReleaseData();
414 } // while not Halt()
416 if( !lastShrinkFactorsAllOnes )
418 // Some of the last shrink factors are not one
419 // graft the output of the expander filter to
420 // to output of this filter
422 // resample the field to the same size as the fixed image
423 m_FieldExpander->SetInput( tempField );
424 m_FieldExpander->SetSize(
425 fixedImage->GetLargestPossibleRegion().GetSize() );
426 m_FieldExpander->SetOutputStartIndex(
427 fixedImage->GetLargestPossibleRegion().GetIndex() );
428 m_FieldExpander->SetOutputOrigin( fixedImage->GetOrigin() );
429 m_FieldExpander->SetOutputSpacing( fixedImage->GetSpacing());
430 m_FieldExpander->UpdateLargestPossibleRegion();
431 this->GraftOutput( m_FieldExpander->GetOutput() );
435 // all the last shrink factors are all ones
436 // graft the output of registration filter to
437 // to output of this filter
438 this->GraftOutput( tempField );
442 m_FieldExpander->SetInput( NULL );
443 m_FieldExpander->GetOutput()->ReleaseData();
444 m_RegistrationFilter->SetInput( NULL );
445 m_RegistrationFilter->GetOutput()->ReleaseData();
450 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
452 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
455 m_RegistrationFilter->StopRegistration();
456 m_StopRegistrationFlag = true;
459 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
461 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
464 // Halt the registration after the user-specified number of levels
465 if (m_NumberOfLevels != 0)
467 this->UpdateProgress( static_cast<float>( m_CurrentLevel ) /
468 static_cast<float>( m_NumberOfLevels ) );
471 if ( m_CurrentLevel >= m_NumberOfLevels )
475 if ( m_StopRegistrationFlag )
487 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
489 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
490 ::GenerateOutputInformation()
493 typename itk::DataObject::Pointer output;
495 if( this->GetInput(0) )
497 // Initial deformation field is set.
498 // Copy information from initial field.
499 this->Superclass::GenerateOutputInformation();
502 else if( this->GetFixedImage() )
504 // Initial deforamtion field is not set.
505 // Copy information from the fixed image.
506 for (unsigned int idx = 0; idx <
507 this->GetNumberOfOutputs(); ++idx )
509 output = this->GetOutput(idx);
512 output->CopyInformation(this->GetFixedImage());
521 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
523 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
524 ::GenerateInputRequestedRegion()
527 // call the superclass's implementation
528 Superclass::GenerateInputRequestedRegion();
530 // request the largest possible region for the moving image
531 MovingImagePointer movingPtr =
532 const_cast< MovingImageType * >( this->GetMovingImage() );
535 movingPtr->SetRequestedRegionToLargestPossibleRegion();
538 // just propagate up the output requested region for
539 // the fixed image and initial deformation field.
540 DeformationFieldPointer inputPtr =
541 const_cast< DeformationFieldType * >( this->GetInput() );
542 DeformationFieldPointer outputPtr = this->GetOutput();
543 FixedImagePointer fixedPtr =
544 const_cast< FixedImageType *>( this->GetFixedImage() );
548 inputPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
553 fixedPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
559 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
561 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
562 ::EnlargeOutputRequestedRegion(
563 itk::DataObject * ptr )
565 // call the superclass's implementation
566 Superclass::EnlargeOutputRequestedRegion( ptr );
568 // set the output requested region to largest possible.
569 DeformationFieldType * outputPtr;
570 outputPtr = dynamic_cast<DeformationFieldType*>( ptr );
574 outputPtr->SetRequestedRegionToLargestPossibleRegion();
580 } // end namespace itk