Orfeo Toolbox  3.16
itkMultiResolutionPDEDeformableRegistration.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkMultiResolutionPDEDeformableRegistration.txx,v $
5  Language: C++
6  Date: $Date: 2009-01-26 21:45:51 $
7  Version: $Revision: 1.33 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #ifndef __itkMultiResolutionPDEDeformableRegistration_txx
18 #define __itkMultiResolutionPDEDeformableRegistration_txx
20 
23 #include "itkImageRegionIterator.h"
24 #include "vnl/vnl_math.h"
25 
26 namespace itk {
27 
31 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
34 {
35 
36  this->SetNumberOfRequiredInputs(2);
37 
38  typename DefaultRegistrationType::Pointer registrator =
39  DefaultRegistrationType::New();
40  m_RegistrationFilter = static_cast<RegistrationType*>(
41  registrator.GetPointer() );
42 
43  m_MovingImagePyramid = MovingImagePyramidType::New();
44  m_FixedImagePyramid = FixedImagePyramidType::New();
45  m_FieldExpander = FieldExpanderType::New();
46  m_InitialDeformationField = NULL;
47 
48  m_NumberOfLevels = 3;
49  m_NumberOfIterations.resize( m_NumberOfLevels );
50  m_FixedImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
51  m_MovingImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
52 
53  unsigned int ilevel;
54  for( ilevel = 0; ilevel < m_NumberOfLevels; ilevel++ )
55  {
56  m_NumberOfIterations[ilevel] = 10;
57  }
58  m_CurrentLevel = 0;
59 
60  m_StopRegistrationFlag = false;
61 
62 }
63 
64 
65 /*
66  * Set the moving image image.
67  */
68 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
69 void
72  const MovingImageType * ptr )
73 {
74  this->ProcessObject::SetNthInput( 2, const_cast< MovingImageType * >( ptr ) );
75 }
76 
77 
78 /*
79  * Get the moving image image.
80  */
81 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
83 ::MovingImageType *
85 ::GetMovingImage(void) const
86 {
87  return dynamic_cast< const MovingImageType * >
88  ( this->ProcessObject::GetInput( 2 ) );
89 }
90 
91 
92 /*
93  * Set the fixed image.
94  */
95 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
96 void
99  const FixedImageType * ptr )
100 {
101  this->ProcessObject::SetNthInput( 1, const_cast< FixedImageType * >( ptr ) );
102 }
103 
104 
105 /*
106  * Get the fixed image.
107  */
108 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
110 ::FixedImageType *
112 ::GetFixedImage(void) const
113 {
114  return dynamic_cast< const FixedImageType * >
115  ( this->ProcessObject::GetInput( 1 ) );
116 }
117 
118 /*
119  *
120  */
121 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
122 std::vector<SmartPointer<DataObject> >::size_type
125 {
126  typename std::vector<SmartPointer<DataObject> >::size_type num = 0;
127 
128  if (this->GetFixedImage())
129  {
130  num++;
131  }
132 
133  if (this->GetMovingImage())
134  {
135  num++;
136  }
137 
138  return num;
139 }
140 
141 
145 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
146 void
149  unsigned int num )
150 {
151  if( m_NumberOfLevels != num )
152  {
153  this->Modified();
154  m_NumberOfLevels = num;
155  m_NumberOfIterations.resize( m_NumberOfLevels );
156  }
157 
158  if( m_MovingImagePyramid && m_MovingImagePyramid->GetNumberOfLevels() != num )
159  {
160  m_MovingImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
161  }
162  if( m_FixedImagePyramid && m_FixedImagePyramid->GetNumberOfLevels() != num )
163  {
164  m_FixedImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
165  }
166 
167 }
168 
169 
173 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
174 void
176 ::PrintSelf(std::ostream& os, Indent indent) const
177 {
178  Superclass::PrintSelf(os, indent);
179  os << indent << "NumberOfLevels: " << m_NumberOfLevels << std::endl;
180  os << indent << "CurrentLevel: " << m_CurrentLevel << std::endl;
181 
182  os << indent << "NumberOfIterations: [";
183  unsigned int ilevel;
184  for( ilevel = 0; ilevel < m_NumberOfLevels - 1; ilevel++ )
185  {
186  os << m_NumberOfIterations[ilevel] << ", ";
187  }
188  os << m_NumberOfIterations[ilevel] << "]" << std::endl;
189 
190  os << indent << "RegistrationFilter: ";
191  os << m_RegistrationFilter.GetPointer() << std::endl;
192  os << indent << "MovingImagePyramid: ";
193  os << m_MovingImagePyramid.GetPointer() << std::endl;
194  os << indent << "FixedImagePyramid: ";
195  os << m_FixedImagePyramid.GetPointer() << std::endl;
196 
197  os << indent << "FieldExpander: ";
198  os << m_FieldExpander.GetPointer() << std::endl;
199 
200  os << indent << "StopRegistrationFlag: ";
201  os << m_StopRegistrationFlag << std::endl;
202 
203 }
204 
205 /*
206  * Perform a the deformable registration using a multiresolution scheme
207  * using an internal mini-pipeline
208  *
209  * ref_pyramid -> registrator -> field_expander --|| tempField
210  * test_pyramid -> | |
211  * | |
212  * --------------------------------
213  *
214  * A tempField image is used to break the cycle between the
215  * registrator and field_expander.
216  *
217  */
218 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
219 void
222 {
223  // Check for NULL images and pointers
224  MovingImageConstPointer movingImage = this->GetMovingImage();
225  FixedImageConstPointer fixedImage = this->GetFixedImage();
226 
227  if( !movingImage || !fixedImage )
228  {
229  itkExceptionMacro( << "Fixed and/or moving image not set" );
230  }
231 
232  if( !m_MovingImagePyramid || !m_FixedImagePyramid )
233  {
234  itkExceptionMacro( << "Fixed and/or moving pyramid not set" );
235  }
236 
237  if( !m_RegistrationFilter )
238  {
239  itkExceptionMacro( << "Registration filter not set" );
240  }
241 
242  if( this->m_InitialDeformationField && this->GetInput(0) )
243  {
244  itkExceptionMacro( << "Only one initial deformation can be given. "
245  << "SetInitialDeformationField should not be used in "
246  << "cunjunction with SetArbitraryInitialDeformationField "
247  << "or SetInput.");
248  }
249 
250  // Create the image pyramids.
251  m_MovingImagePyramid->SetInput( movingImage );
252  m_MovingImagePyramid->UpdateLargestPossibleRegion();
253 
254  m_FixedImagePyramid->SetInput( fixedImage );
255  m_FixedImagePyramid->UpdateLargestPossibleRegion();
256 
257  // Initializations
258  m_CurrentLevel = 0;
259  m_StopRegistrationFlag = false;
260 
261  unsigned int movingLevel = vnl_math_min( (int) m_CurrentLevel,
262  (int) m_MovingImagePyramid->GetNumberOfLevels() );
263 
264  unsigned int fixedLevel = vnl_math_min( (int) m_CurrentLevel,
265  (int) m_FixedImagePyramid->GetNumberOfLevels() );
266 
267  DeformationFieldPointer tempField = NULL;
268 
269  DeformationFieldPointer inputPtr =
270  const_cast< DeformationFieldType * >( this->GetInput(0) );
271 
272  if ( this->m_InitialDeformationField )
273  {
274  tempField = this->m_InitialDeformationField;
275  }
276  else if( inputPtr )
277  {
278  // Arbitrary initial deformation field is set.
279  // smooth it and resample
280 
281  // First smooth it
282  tempField = inputPtr;
283 
285  DeformationFieldType> GaussianFilterType;
286  typename GaussianFilterType::Pointer smoother
287  = GaussianFilterType::New();
288 
289  for (unsigned int dim=0; dim<DeformationFieldType::ImageDimension; ++dim)
290  {
291  // sigma accounts for the subsampling of the pyramid
292  double sigma = 0.5 * static_cast<float>(
293  m_FixedImagePyramid->GetSchedule()[fixedLevel][dim] );
294 
295  // but also for a possible discrepancy in the spacing
296  sigma *= fixedImage->GetSpacing()[dim]
297  / inputPtr->GetSpacing()[dim];
298 
299  smoother->SetInput( tempField );
300  smoother->SetSigma( sigma );
301  smoother->SetDirection( dim );
302 
303  smoother->Update();
304 
305  tempField = smoother->GetOutput();
306  tempField->DisconnectPipeline();
307  }
308 
309 
310  // Now resample
311  m_FieldExpander->SetInput( tempField );
312 
313  typename FloatImageType::Pointer fi =
314  m_FixedImagePyramid->GetOutput( fixedLevel );
315  m_FieldExpander->SetSize(
316  fi->GetLargestPossibleRegion().GetSize() );
317  m_FieldExpander->SetOutputStartIndex(
318  fi->GetLargestPossibleRegion().GetIndex() );
319  m_FieldExpander->SetOutputOrigin( fi->GetOrigin() );
320  m_FieldExpander->SetOutputSpacing( fi->GetSpacing());
321  m_FieldExpander->SetOutputDirection( fi->GetDirection());
322 
323  m_FieldExpander->UpdateLargestPossibleRegion();
324  m_FieldExpander->SetInput( NULL );
325  tempField = m_FieldExpander->GetOutput();
326  tempField->DisconnectPipeline();
327  }
328 
329  bool lastShrinkFactorsAllOnes = false;
330 
331  while ( !this->Halt() )
332  {
333 
334  if( tempField.IsNull() )
335  {
336  m_RegistrationFilter->SetInitialDeformationField( NULL );
337  }
338  else
339  {
340  // Resample the field to be the same size as the fixed image
341  // at the current level
342  m_FieldExpander->SetInput( tempField );
343 
344  typename FloatImageType::Pointer fi =
345  m_FixedImagePyramid->GetOutput( fixedLevel );
346  m_FieldExpander->SetSize(
347  fi->GetLargestPossibleRegion().GetSize() );
348  m_FieldExpander->SetOutputStartIndex(
349  fi->GetLargestPossibleRegion().GetIndex() );
350  m_FieldExpander->SetOutputOrigin( fi->GetOrigin() );
351  m_FieldExpander->SetOutputSpacing( fi->GetSpacing());
352  m_FieldExpander->SetOutputDirection( fi->GetDirection());
353 
354  m_FieldExpander->UpdateLargestPossibleRegion();
355  m_FieldExpander->SetInput( NULL );
356  tempField = m_FieldExpander->GetOutput();
357  tempField->DisconnectPipeline();
358 
359  m_RegistrationFilter->SetInitialDeformationField( tempField );
360 
361  }
362 
363  // setup registration filter and pyramids
364  m_RegistrationFilter->SetMovingImage( m_MovingImagePyramid->GetOutput(movingLevel) );
365  m_RegistrationFilter->SetFixedImage( m_FixedImagePyramid->GetOutput(fixedLevel) );
366 
367  m_RegistrationFilter->SetNumberOfIterations(
368  m_NumberOfIterations[m_CurrentLevel] );
369 
370  // cache shrink factors for computing the next expand factors.
371  lastShrinkFactorsAllOnes = true;
372  for( unsigned int idim = 0; idim < ImageDimension; idim++ )
373  {
374  if ( m_FixedImagePyramid->GetSchedule()[fixedLevel][idim] > 1 )
375  {
376  lastShrinkFactorsAllOnes = false;
377  break;
378  }
379  }
380 
381  // compute new deformation field
382  m_RegistrationFilter->UpdateLargestPossibleRegion();
383  tempField = m_RegistrationFilter->GetOutput();
384  tempField->DisconnectPipeline();
385 
386  // Increment level counter.
387  m_CurrentLevel++;
388  movingLevel = vnl_math_min( (int) m_CurrentLevel,
389  (int) m_MovingImagePyramid->GetNumberOfLevels() );
390  fixedLevel = vnl_math_min( (int) m_CurrentLevel,
391  (int) m_FixedImagePyramid->GetNumberOfLevels() );
392 
393  // Invoke an iteration event.
394  this->InvokeEvent( IterationEvent() );
395 
396  // We can release data from pyramid which are no longer required.
397  if ( movingLevel > 0 )
398  {
399  m_MovingImagePyramid->GetOutput( movingLevel - 1 )->ReleaseData();
400  }
401  if( fixedLevel > 0 )
402  {
403  m_FixedImagePyramid->GetOutput( fixedLevel - 1 )->ReleaseData();
404  }
405 
406  } // while not Halt()
407 
408  if( !lastShrinkFactorsAllOnes )
409  {
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
413 
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->SetOutputDirection( fixedImage->GetDirection());
423 
424  m_FieldExpander->UpdateLargestPossibleRegion();
425  this->GraftOutput( m_FieldExpander->GetOutput() );
426  }
427  else
428  {
429  // all the last shrink factors are all ones
430  // graft the output of registration filter to
431  // to output of this filter
432  this->GraftOutput( tempField );
433  }
434 
435  // Release memory
436  m_FieldExpander->SetInput( NULL );
437  m_FieldExpander->GetOutput()->ReleaseData();
438  m_RegistrationFilter->SetInput( NULL );
439  m_RegistrationFilter->GetOutput()->ReleaseData();
440 
441 }
442 
443 
444 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
445 void
448 {
449  m_RegistrationFilter->StopRegistration();
450  m_StopRegistrationFlag = true;
451 }
452 
453 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
454 bool
457 {
458  // Halt the registration after the user-specified number of levels
459  if (m_NumberOfLevels != 0)
460  {
461  this->UpdateProgress( static_cast<float>( m_CurrentLevel ) /
462  static_cast<float>( m_NumberOfLevels ) );
463  }
464 
465  if ( m_CurrentLevel >= m_NumberOfLevels )
466  {
467  return true;
468  }
469  if ( m_StopRegistrationFlag )
470  {
471  return true;
472  }
473  else
474  {
475  return false;
476  }
477 
478 }
479 
480 
481 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
482 void
485 {
486 
487  typename DataObject::Pointer output;
488 
489  if( this->GetInput(0) )
490  {
491  // Initial deformation field is set.
492  // Copy information from initial field.
493  this->Superclass::GenerateOutputInformation();
494 
495  }
496  else if( this->GetFixedImage() )
497  {
498  // Initial deforamtion field is not set.
499  // Copy information from the fixed image.
500  for (unsigned int idx = 0; idx <
501  this->GetNumberOfOutputs(); ++idx )
502  {
503  output = this->GetOutput(idx);
504  if (output)
505  {
506  output->CopyInformation(this->GetFixedImage());
507  }
508  }
509 
510  }
511 
512 }
513 
514 
515 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
516 void
519 {
520 
521  // call the superclass's implementation
522  Superclass::GenerateInputRequestedRegion();
523 
524  // request the largest possible region for the moving image
525  MovingImagePointer movingPtr =
526  const_cast< MovingImageType * >( this->GetMovingImage() );
527  if( movingPtr )
528  {
529  movingPtr->SetRequestedRegionToLargestPossibleRegion();
530  }
531 
532  // just propagate up the output requested region for
533  // the fixed image and initial deformation field.
534  DeformationFieldPointer inputPtr =
535  const_cast< DeformationFieldType * >( this->GetInput() );
536  DeformationFieldPointer outputPtr = this->GetOutput();
537  FixedImagePointer fixedPtr =
538  const_cast< FixedImageType *>( this->GetFixedImage() );
539 
540  if( inputPtr )
541  {
542  inputPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
543  }
544 
545  if( fixedPtr )
546  {
547  fixedPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
548  }
549 
550 }
551 
552 
553 template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
554 void
557  DataObject * ptr )
558 {
559  // call the superclass's implementation
560  Superclass::EnlargeOutputRequestedRegion( ptr );
561 
562  // set the output requested region to largest possible.
563  DeformationFieldType * outputPtr;
564  outputPtr = dynamic_cast<DeformationFieldType*>( ptr );
565 
566  if( outputPtr )
567  {
568  outputPtr->SetRequestedRegionToLargestPossibleRegion();
569  }
570 
571 }
572 
573 
574 } // end namespace itk
575 
576 #endif

Generated at Sat Feb 2 2013 23:54:39 for Orfeo Toolbox with doxygen 1.8.1.1