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 _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 m_RegistrationFilter->SetInitialDeformationField( NULL );
342 // Resample the field to be the same size as the fixed image
343 // at the current level
344 m_FieldExpander->SetInput( tempField );
346 typename FloatImageType::Pointer fi =
347 m_FixedImagePyramid->GetOutput( fixedLevel );
348 m_FieldExpander->SetSize(
349 fi->GetLargestPossibleRegion().GetSize() );
350 m_FieldExpander->SetOutputStartIndex(
351 fi->GetLargestPossibleRegion().GetIndex() );
352 m_FieldExpander->SetOutputOrigin( fi->GetOrigin() );
353 m_FieldExpander->SetOutputSpacing( fi->GetSpacing());
355 m_FieldExpander->UpdateLargestPossibleRegion();
356 m_FieldExpander->SetInput( NULL );
357 tempField = m_FieldExpander->GetOutput();
358 tempField->DisconnectPipeline();
360 m_RegistrationFilter->SetInitialDeformationField( tempField );
364 // setup registration filter and pyramids
365 m_RegistrationFilter->SetMovingImage( m_MovingImagePyramid->GetOutput(movingLevel) );
366 m_RegistrationFilter->SetFixedImage( m_FixedImagePyramid->GetOutput(fixedLevel) );
367 m_RegistrationFilter->SetNumberOfIterations(
368 m_NumberOfIterations[m_CurrentLevel] );
370 // cache shrink factors for computing the next expand factors.
371 lastShrinkFactorsAllOnes = true;
372 for( unsigned int idim = 0; idim < ImageDimension; idim++ )
374 if ( m_FixedImagePyramid->GetSchedule()[fixedLevel][idim] > 1 )
376 lastShrinkFactorsAllOnes = false;
381 // Invoke an iteration event.
382 this->InvokeEvent( itk::IterationEvent() );
384 // compute new deformation field
385 m_RegistrationFilter->UpdateLargestPossibleRegion();
386 tempField = m_RegistrationFilter->GetOutput();
387 tempField->DisconnectPipeline();
389 // Increment level counter.
391 movingLevel = vnl_math_min( (int) m_CurrentLevel,
392 (int) m_MovingImagePyramid->GetNumberOfLevels() );
393 fixedLevel = vnl_math_min( (int) m_CurrentLevel,
394 (int) m_FixedImagePyramid->GetNumberOfLevels() );
396 // We can release data from pyramid which are no longer required.
397 if ( movingLevel > 0 )
399 m_MovingImagePyramid->GetOutput( movingLevel - 1 )->ReleaseData();
403 m_FixedImagePyramid->GetOutput( fixedLevel - 1 )->ReleaseData();
406 } // while not Halt()
408 if( !lastShrinkFactorsAllOnes )
410 // Some of the last shrink factors are not one
411 // graft the output of the expander filter to
412 // to output of this filter
414 // resample the field to the same size as the fixed image
415 m_FieldExpander->SetInput( tempField );
416 m_FieldExpander->SetSize(
417 fixedImage->GetLargestPossibleRegion().GetSize() );
418 m_FieldExpander->SetOutputStartIndex(
419 fixedImage->GetLargestPossibleRegion().GetIndex() );
420 m_FieldExpander->SetOutputOrigin( fixedImage->GetOrigin() );
421 m_FieldExpander->SetOutputSpacing( fixedImage->GetSpacing());
422 m_FieldExpander->UpdateLargestPossibleRegion();
423 this->GraftOutput( m_FieldExpander->GetOutput() );
427 // all the last shrink factors are all ones
428 // graft the output of registration filter to
429 // to output of this filter
430 this->GraftOutput( tempField );
434 m_FieldExpander->SetInput( NULL );
435 m_FieldExpander->GetOutput()->ReleaseData();
436 m_RegistrationFilter->SetInput( NULL );
437 m_RegistrationFilter->GetOutput()->ReleaseData();
442 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
444 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
447 m_RegistrationFilter->StopRegistration();
448 m_StopRegistrationFlag = true;
451 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
453 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
456 // Halt the registration after the user-specified number of levels
457 if (m_NumberOfLevels != 0)
459 this->UpdateProgress( static_cast<float>( m_CurrentLevel ) /
460 static_cast<float>( m_NumberOfLevels ) );
463 if ( m_CurrentLevel >= m_NumberOfLevels )
467 if ( m_StopRegistrationFlag )
479 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
481 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
482 ::GenerateOutputInformation()
485 typename itk::DataObject::Pointer output;
487 if( this->GetInput(0) )
489 // Initial deformation field is set.
490 // Copy information from initial field.
491 this->Superclass::GenerateOutputInformation();
494 else if( this->GetFixedImage() )
496 // Initial deforamtion field is not set.
497 // Copy information from the fixed image.
498 for (unsigned int idx = 0; idx <
499 this->GetNumberOfOutputs(); ++idx )
501 output = this->GetOutput(idx);
504 output->CopyInformation(this->GetFixedImage());
513 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
515 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
516 ::GenerateInputRequestedRegion()
519 // call the superclass's implementation
520 Superclass::GenerateInputRequestedRegion();
522 // request the largest possible region for the moving image
523 MovingImagePointer movingPtr =
524 const_cast< MovingImageType * >( this->GetMovingImage() );
527 movingPtr->SetRequestedRegionToLargestPossibleRegion();
530 // just propagate up the output requested region for
531 // the fixed image and initial deformation field.
532 DeformationFieldPointer inputPtr =
533 const_cast< DeformationFieldType * >( this->GetInput() );
534 DeformationFieldPointer outputPtr = this->GetOutput();
535 FixedImagePointer fixedPtr =
536 const_cast< FixedImageType *>( this->GetFixedImage() );
540 inputPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
545 fixedPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
551 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
553 MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
554 ::EnlargeOutputRequestedRegion(
555 itk::DataObject * ptr )
557 // call the superclass's implementation
558 Superclass::EnlargeOutputRequestedRegion( ptr );
560 // set the output requested region to largest possible.
561 DeformationFieldType * outputPtr;
562 outputPtr = dynamic_cast<DeformationFieldType*>( ptr );
566 outputPtr->SetRequestedRegionToLargestPossibleRegion();
572 } // end namespace itk