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 __clitkSpatioTemporalMultiResolutionImageRegistrationMethod_txx
19 #define __clitkSpatioTemporalMultiResolutionImageRegistrationMethod_txx
20 #include "clitkSpatioTemporalMultiResolutionImageRegistrationMethod.h"
21 #include "clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter.h"
29 template < typename TFixedImage, typename TMovingImage >
30 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
31 ::SpatioTemporalMultiResolutionImageRegistrationMethod()
33 this->SetNumberOfRequiredOutputs( 1 ); // for the Transform
35 m_FixedImage = 0; // has to be provided by the user.
36 m_MovingImage = 0; // has to be provided by the user.
37 m_Transform = 0; // has to be provided by the user.
38 m_Interpolator = 0; // has to be provided by the user.
39 m_Metric = 0; // has to be provided by the user.
40 m_Optimizer = 0; // has to be provided by the user.
42 // Use SpatioTemporalMultiResolutionPyramidImageFilter as the default
44 m_FixedImagePyramid = FixedImagePyramidType::New();
45 m_MovingImagePyramid = MovingImagePyramidType::New();
52 m_ScheduleSpecified = false;
53 m_NumberOfLevelsSpecified = false;
55 m_InitialTransformParameters = ParametersType(1);
56 m_InitialTransformParametersOfNextLevel = ParametersType(1);
57 m_LastTransformParameters = ParametersType(1);
59 m_InitialTransformParameters.Fill( 0.0f );
60 m_InitialTransformParametersOfNextLevel.Fill( 0.0f );
61 m_LastTransformParameters.Fill( 0.0f );
64 TransformOutputPointer transformDecorator =
65 static_cast< TransformOutputType * >(
66 this->MakeOutput(0).GetPointer() );
68 this->ProcessObject::SetNthOutput( 0, transformDecorator.GetPointer() );
73 * Initialize by setting the interconnects between components.
75 template < typename TFixedImage, typename TMovingImage >
77 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
78 ::Initialize() throw (ExceptionObject)
84 itkExceptionMacro(<<"Metric is not present" );
89 itkExceptionMacro(<<"Optimizer is not present" );
94 itkExceptionMacro(<<"Transform is not present");
99 itkExceptionMacro(<<"Interpolator is not present");
103 m_Metric->SetMovingImage( m_MovingImagePyramid->GetOutput(m_CurrentLevel) );
104 m_Metric->SetFixedImage( m_FixedImagePyramid->GetOutput(m_CurrentLevel) );
105 m_Metric->SetTransform( m_Transform );
106 m_Metric->SetInterpolator( m_Interpolator );
107 m_Metric->SetFixedImageRegion( m_FixedImageRegionPyramid[ m_CurrentLevel ] );
108 m_Metric->Initialize();
110 // Setup the optimizer
111 m_Optimizer->SetCostFunction( m_Metric );
112 m_Optimizer->SetInitialPosition( m_InitialTransformParametersOfNextLevel );
115 // Connect the transform to the Decorator.
117 TransformOutputType * transformOutput =
118 static_cast< TransformOutputType * >( this->ProcessObject::GetOutput(0) );
120 transformOutput->Set( m_Transform.GetPointer() );
126 * Stop the Registration Process
128 template < typename TFixedImage, typename TMovingImage >
130 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
131 ::StopRegistration( void )
137 * Set the schedules for the fixed and moving image pyramid
139 template < typename TFixedImage, typename TMovingImage >
141 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
142 ::SetSchedules( const ScheduleType & fixedImagePyramidSchedule,
143 const ScheduleType & movingImagePyramidSchedule )
145 if( m_NumberOfLevelsSpecified )
147 itkExceptionMacro( "SetSchedules should not be used "
148 << "if numberOfLevelves are specified using SetNumberOfLevels" );
150 m_FixedImagePyramidSchedule = fixedImagePyramidSchedule;
151 m_MovingImagePyramidSchedule = movingImagePyramidSchedule;
152 m_ScheduleSpecified = true;
154 //Set the number of levels based on the pyramid schedule specified
155 if ( m_FixedImagePyramidSchedule.rows() !=
156 m_MovingImagePyramidSchedule.rows())
158 itkExceptionMacro("The specified schedules contain unequal number of levels");
162 m_NumberOfLevels = m_FixedImagePyramidSchedule.rows();
169 * Set the number of levels
171 template < typename TFixedImage, typename TMovingImage >
173 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
174 ::SetNumberOfLevels( unsigned long numberOfLevels )
176 if( m_ScheduleSpecified )
178 itkExceptionMacro( "SetNumberOfLevels should not be used "
179 << "if schedules have been specified using SetSchedules method " );
182 m_NumberOfLevels = numberOfLevels;
183 m_NumberOfLevelsSpecified = true;
188 * Stop the Registration Process
190 template < typename TFixedImage, typename TMovingImage >
192 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
193 ::PreparePyramids( void )
198 itkExceptionMacro(<<"Transform is not present");
201 m_InitialTransformParametersOfNextLevel = m_InitialTransformParameters;
203 if ( m_InitialTransformParametersOfNextLevel.Size() !=
204 m_Transform->GetNumberOfParameters() )
206 itkExceptionMacro(<<"Size mismatch between initial parameter and transform");
212 itkExceptionMacro(<<"FixedImage is not present");
217 itkExceptionMacro(<<"MovingImage is not present");
220 if( !m_FixedImagePyramid )
222 itkExceptionMacro(<<"Fixed image pyramid is not present");
225 if( !m_MovingImagePyramid )
227 itkExceptionMacro(<<"Moving image pyramid is not present");
230 // Setup the fixed and moving image pyramid
231 if( m_NumberOfLevelsSpecified )
233 m_FixedImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
234 m_MovingImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
237 if( m_ScheduleSpecified )
239 m_FixedImagePyramid->SetNumberOfLevels( m_FixedImagePyramidSchedule.rows());
240 m_FixedImagePyramid->SetSchedule( m_FixedImagePyramidSchedule );
242 m_MovingImagePyramid->SetNumberOfLevels( m_MovingImagePyramidSchedule.rows());
243 m_MovingImagePyramid->SetSchedule( m_MovingImagePyramidSchedule );
246 m_FixedImagePyramid->SetInput( m_FixedImage );
247 m_FixedImagePyramid->UpdateLargestPossibleRegion();
249 // Setup the moving image pyramid
250 m_MovingImagePyramid->SetInput( m_MovingImage );
251 m_MovingImagePyramid->UpdateLargestPossibleRegion();
253 typedef typename FixedImageRegionType::SizeType SizeType;
254 typedef typename FixedImageRegionType::IndexType IndexType;
256 ScheduleType schedule = m_FixedImagePyramid->GetSchedule();
257 std::cout << "FixedImage schedule: " << schedule << std::endl;
259 ScheduleType movingschedule = m_MovingImagePyramid->GetSchedule();
260 std::cout << "MovingImage schedule: " << movingschedule << std::endl;
262 SizeType inputSize = m_FixedImageRegion.GetSize();
263 IndexType inputStart = m_FixedImageRegion.GetIndex();
265 const unsigned long numberOfLevels =
266 m_FixedImagePyramid->GetNumberOfLevels();
268 m_FixedImageRegionPyramid.reserve( numberOfLevels );
269 m_FixedImageRegionPyramid.resize( numberOfLevels );
271 // Compute the FixedImageRegion corresponding to each level of the
272 // pyramid. This uses the same algorithm of the ShrinkImageFilter
273 // since the regions should be compatible.
274 for ( unsigned int level=0; level < numberOfLevels; level++ )
278 for ( unsigned int dim = 0; dim < TFixedImage::ImageDimension; dim++)
280 const float scaleFactor = static_cast<float>( schedule[ level ][ dim ] );
282 size[ dim ] = static_cast<typename SizeType::SizeValueType>(
283 vcl_floor(static_cast<float>( inputSize[ dim ] ) / scaleFactor ) );
284 if( size[ dim ] < 1 )
289 start[ dim ] = static_cast<typename IndexType::IndexValueType>(
290 vcl_ceil(static_cast<float>( inputStart[ dim ] ) / scaleFactor ) );
292 m_FixedImageRegionPyramid[ level ].SetSize( size );
293 m_FixedImageRegionPyramid[ level ].SetIndex( start );
299 * Starts the Registration Process
301 template < typename TFixedImage, typename TMovingImage >
303 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
304 ::StartRegistration( void )
307 // StartRegistration is an old API from before
308 // this egistrationMethod was a subclass of ProcessObject.
309 // Historically, one could call StartRegistration() instead of
310 // calling Update(). However, when called directly by the user, the
311 // inputs to the RegistrationMethod may not be up to date. This
312 // may cause an unexpected behavior.
314 // Since we cannot eliminate StartRegistration for backward
315 // compability reasons, we check whether StartRegistration was
316 // called directly or whether Update() (which in turn called
317 // StartRegistration()).
326 this->PreparePyramids();
328 for ( m_CurrentLevel = 0; m_CurrentLevel < m_NumberOfLevels;
332 // Invoke an iteration event.
333 // This allows a UI to reset any of the components between
335 this->InvokeEvent( IterationEvent() );
337 // Check if there has been a stop request
345 // initialize the interconnects between components
348 catch( ExceptionObject& err )
350 m_LastTransformParameters = ParametersType(1);
351 m_LastTransformParameters.Fill( 0.0f );
353 // pass exception to caller
359 // do the optimization
360 m_Optimizer->StartOptimization();
362 catch( ExceptionObject& err )
364 // An error has occurred in the optimization.
365 // Update the parameters
366 m_LastTransformParameters = m_Optimizer->GetCurrentPosition();
368 // Pass exception to caller
373 m_LastTransformParameters = m_Optimizer->GetCurrentPosition();
374 m_Transform->SetParameters( m_LastTransformParameters );
376 // setup the initial parameters for next level
377 if ( m_CurrentLevel < m_NumberOfLevels - 1 )
379 m_InitialTransformParametersOfNextLevel =
380 m_LastTransformParameters;
391 template < typename TFixedImage, typename TMovingImage >
393 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
394 ::PrintSelf(std::ostream& os, itk::Indent indent) const
396 Superclass::PrintSelf( os, indent );
397 os << indent << "Metric: " << m_Metric.GetPointer() << std::endl;
398 os << indent << "Optimizer: " << m_Optimizer.GetPointer() << std::endl;
399 os << indent << "Transform: " << m_Transform.GetPointer() << std::endl;
400 os << indent << "Interpolator: " << m_Interpolator.GetPointer() << std::endl;
401 os << indent << "FixedImage: " << m_FixedImage.GetPointer() << std::endl;
402 os << indent << "MovingImage: " << m_MovingImage.GetPointer() << std::endl;
403 os << indent << "FixedImagePyramid: ";
404 os << m_FixedImagePyramid.GetPointer() << std::endl;
405 os << indent << "MovingImagePyramid: ";
406 os << m_MovingImagePyramid.GetPointer() << std::endl;
408 os << indent << "NumberOfLevels: ";
409 os << m_NumberOfLevels << std::endl;
411 os << indent << "CurrentLevel: ";
412 os << m_CurrentLevel << std::endl;
414 os << indent << "InitialTransformParameters: ";
415 os << m_InitialTransformParameters << std::endl;
416 os << indent << "InitialTransformParametersOfNextLevel: ";
417 os << m_InitialTransformParametersOfNextLevel << std::endl;
418 os << indent << "LastTransformParameters: ";
419 os << m_LastTransformParameters << std::endl;
420 os << indent << "FixedImageRegion: ";
421 os << m_FixedImageRegion << std::endl;
422 for(unsigned int level=0; level< m_FixedImageRegionPyramid.size(); level++)
424 os << indent << "FixedImageRegion at level " << level << ": ";
425 os << m_FixedImageRegionPyramid[level] << std::endl;
427 os << indent << "FixedImagePyramidSchedule : " << std::endl;
428 os << m_FixedImagePyramidSchedule << std::endl;
429 os << indent << "MovingImagePyramidSchedule : " << std::endl;
430 os << m_MovingImagePyramidSchedule << std::endl;
438 template < typename TFixedImage, typename TMovingImage >
440 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
443 this->StartRegistration();
446 template < typename TFixedImage, typename TMovingImage >
448 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
451 unsigned long mtime = Superclass::GetMTime();
455 // Some of the following should be removed once ivars are put in the
456 // input and output lists
460 m = m_Transform->GetMTime();
461 mtime = (m > mtime ? m : mtime);
466 m = m_Interpolator->GetMTime();
467 mtime = (m > mtime ? m : mtime);
472 m = m_Metric->GetMTime();
473 mtime = (m > mtime ? m : mtime);
478 m = m_Optimizer->GetMTime();
479 mtime = (m > mtime ? m : mtime);
484 m = m_FixedImage->GetMTime();
485 mtime = (m > mtime ? m : mtime);
490 m = m_MovingImage->GetMTime();
491 mtime = (m > mtime ? m : mtime);
501 template < typename TFixedImage, typename TMovingImage >
502 const typename SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>::TransformOutputType *
503 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
506 return static_cast< const TransformOutputType * >( this->ProcessObject::GetOutput(0) );
509 template < typename TFixedImage, typename TMovingImage >
511 SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
512 ::MakeOutput(unsigned int output)
517 return static_cast<DataObject*>(TransformOutputType::New().GetPointer());
520 itkExceptionMacro("MakeOutput request for an output number larger than the expected number of outputs");
525 } // end namespace clitk