25 m_CrossModalityRegistration(true),
26 m_UseAffineTransform(true),
27 m_UseWindowedSincInterpolator(false),
28 m_UseNearestNeighborInterpolator(false),
30 m_EstimatedParameters(0),
31 m_InitialParameters(0),
39 if( m_EstimatedParameters != NULL)
41 delete [] m_EstimatedParameters;
48 if( fixed.IsNotNull() )
56 if( moving.IsNotNull() )
58 m_MovingImage = moving;
65 m_FixedImageMask = mask;
70 if( m_MovingImage.IsNull() )
75 if( m_FixedImage.IsNull() )
80 unsigned int allowedDimension = 3;
82 if( m_FixedImage->GetDimension() != allowedDimension ||
83 m_MovingImage->GetDimension() != allowedDimension )
85 mitkThrow() <<
" Only 3D Images supported.";
101 if( m_EstimatedParameters == NULL )
103 output.set_identity();
107 typedef itk::MatrixOffsetTransformBase< double, 3, 3> BaseTransformType;
110 if( this->m_UseAffineTransform )
112 typedef itk::AffineTransform< double > TransformType;
115 TransformType::ParametersType affine_params( TransformType::ParametersDimension );
116 this->GetParameters( &affine_params[0] );
118 transform->SetParameters( affine_params );
119 base_transform = transform;
126 RigidTransformType::ParametersType rigid_params( RigidTransformType::ParametersDimension );
127 this->GetParameters( &rigid_params[0] );
129 rtransform->SetParameters( rigid_params );
131 base_transform = rtransform;
134 return base_transform->GetMatrix().GetVnlMatrix();
156 unsigned int dim = 12;
157 if( !m_UseAffineTransform )
160 if (m_EstimatedParameters == NULL)
161 m_EstimatedParameters =
new double[dim];
163 double tmpParams[12];
165 for(
unsigned int i=0; i<dim; i++)
167 tmpParams[i] = m_EstimatedParameters[i];
168 m_EstimatedParameters[i] = transform[i];
174 for(
unsigned int i=0; i<dim; i++)
176 m_EstimatedParameters[i] = tmpParams[i];
184 #include <itkImageRegistrationMethodv4.h>
185 #include <itkGradientDescentLineSearchOptimizerv4.h>
186 #include <itkMattesMutualInformationImageToImageMetricv4.h>
187 #include <itkJointHistogramMutualInformationImageToImageMetricv4.h>
188 #include <itkCorrelationImageToImageMetricv4.h>
189 #include <itkOptimizerParameterScalesEstimator.h>
190 #include <itkRegistrationParameterScalesFromPhysicalShift.h>
192 template <
typename TPixel1,
unsigned int VImageDimension1,
typename TPixel2,
unsigned int VImageDimension2>
194 RegisterTwoImagesV4(itk::Image<TPixel1, VImageDimension1>* itkImage1, itk::Image<TPixel2, VImageDimension2>* itkImage2)
197 typedef typename itk::Image<TPixel1, VImageDimension1> ItkImageTypeFixed;
198 typedef typename itk::Image<TPixel2, VImageDimension1> ItkImageTypeMoving;
200 typedef itk::MatrixOffsetTransformBase< double, VImageDimension1, VImageDimension2 > BaseTransformType;
202 typedef itk::Image< double, 3> ItkRegistrationImageType;
203 typedef itk::CastImageFilter< ItkImageTypeFixed, ItkRegistrationImageType> FixedCastFilterType;
204 typedef itk::CastImageFilter< ItkImageTypeMoving, ItkRegistrationImageType> MovingCastFilterType;
206 typedef typename itk::ImageRegistrationMethodv4< ItkRegistrationImageType, ItkRegistrationImageType, AffineTransformType>
RegistrationType;
207 typedef typename itk::MattesMutualInformationImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType> MIMetricType;
208 typedef typename itk::CorrelationImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType > NCMetricType;
209 typedef typename itk::ImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType > BaseMetricType;
211 typedef typename itk::ImageRegistrationMethodv4< ItkRegistrationImageType, ItkRegistrationImageType, RigidTransformType> RigidRegistrationType;
213 typedef itk::GradientDescentLineSearchOptimizerv4 OptimizerType;
219 unsigned int paramDim = 12;
221 if( m_UseAffineTransform )
231 typename BaseTransformType::ParametersType initialParams(paramDim);
233 initialParams.Fill(0);
234 if( m_UseAffineTransform )
236 initialParams[0] = initialParams[4] = initialParams[8] = 1;
247 caster_f->SetInput(0, referenceImage );
248 caster_m->SetInput(0, movingImage );
254 catch(
const itk::ExceptionObject & )
262 unsigned int max_pyramid_lvl = 4;
263 unsigned int max_schedule_val = 8;
264 const unsigned int min_required_image_size = 12;
265 typename ItkImageTypeFixed::RegionType::SizeType image_size = referenceImage->GetLargestPossibleRegion().GetSize();
266 unsigned int min_value =
std::min( image_size[0],
std::min( image_size[1], image_size[2]));
269 float optmaxstep = 10;
270 float optminstep = 0.1f;
271 unsigned int iterations = 40;
272 unsigned int convergence_win_size = 8;
273 double convergence_tolerance = 1e-5;
274 while( max_schedule_val > 1.0 && (min_value / max_schedule_val < min_required_image_size) )
276 max_schedule_val /= 2;
280 convergence_win_size += 4;
281 convergence_tolerance *= 0.5;
284 typename RegistrationType::ShrinkFactorsArrayType shrink_factors(max_pyramid_lvl);
285 shrink_factors.Fill(1);
287 shrink_factors[0] = max_schedule_val;
288 for(
unsigned int i=1; i<max_pyramid_lvl; i++)
290 shrink_factors[i] =
std::max( shrink_factors[i-1]/2, 1ul);
295 MITK_INFO(
"dw.pyramid.reg") <<
" : Pyramid size set to : " << max_pyramid_lvl;
303 if( m_CrossModalityRegistration )
309 mi_estimator->SetMetric( metric );
311 optimizer->SetScalesEstimator( mi_estimator );
313 base_metric = metric;
322 nc_estimator->SetMetric( metric );
324 optimizer->SetScalesEstimator( nc_estimator );
326 base_metric = metric;
329 optimizer->SetDoEstimateLearningRateOnce(
false );
330 optimizer->SetDoEstimateLearningRateAtEachIteration(
true );
331 optimizer->SetNumberOfIterations( iterations );
332 optimizer->SetConvergenceWindowSize( convergence_win_size );
333 optimizer->SetMaximumStepSizeInPhysicalUnits( optmaxstep );
334 optimizer->SetMinimumConvergenceValue( convergence_tolerance );
337 optimizer->SetEpsilon( 1e-3 );
338 optimizer->SetLowerLimit( 0.3 );
339 optimizer->SetUpperLimit( 1.7 );
340 optimizer->SetMaximumLineSearchIterations( 20 );
343 unsigned long vopt_tag = 0;
346 MITK_INFO <<
" :: Starting at " << initialParams;
351 vopt_tag = optimizer->AddObserver( itk::IterationEvent(), iterationObserver );
356 if( !m_UseAffineTransform && m_InitializeByGeometry )
358 typedef itk::CenteredVersorTransformInitializer< ItkImageTypeFixed, ItkImageTypeMoving> TransformInitializerType;
360 MITK_INFO <<
"Initializer starting at : " << rigidTransform->GetParameters();
363 initializer->SetTransform( rigidTransform);
364 initializer->SetFixedImage( referenceImage.GetPointer() );
365 initializer->SetMovingImage( movingImage.GetPointer() );
366 initializer->MomentsOn();
367 initializer->InitializeTransform();
369 MITK_INFO <<
"Initialized Rigid position : " << rigidTransform->GetParameters();
370 initialParams[3] = rigidTransform->GetParameters()[3];
371 initialParams[4] = rigidTransform->GetParameters()[4];
372 initialParams[5] = rigidTransform->GetParameters()[5];
385 notFilter->SetInput(itkFixedImageMask);
387 fixedMaskSpatialObject->SetImage( notFilter->GetOutput() );
388 base_metric->SetFixedImageMask( fixedMaskSpatialObject );
392 if( m_EstimatedParameters != NULL)
394 delete [] m_EstimatedParameters;
397 m_EstimatedParameters =
new double[paramDim];
404 if( m_UseAffineTransform )
409 registration->SetFixedImage( 0, caster_f->GetOutput() );
410 registration->SetMovingImage( 0, caster_m->GetOutput() );
411 registration->SetMetric( base_metric );
412 registration->SetOptimizer( optimizer );
413 registration->SetMovingInitialTransform( transform.GetPointer() );
414 registration->SetNumberOfLevels(max_pyramid_lvl);
415 registration->SetShrinkFactorsPerLevel( shrink_factors );
420 unsigned int pyramid_tag = registration->AddObserver( itk::InitializeEvent(), pyramid_observer );
425 registration->Update();
427 catch(
const itk::ExceptionObject &e)
429 registration->Print( std::cout );
431 MITK_ERROR <<
"[Registration Update] Caught ITK exception: ";
434 mitkThrow() <<
"Registration failed with exception: " << e.what();
439 typename BaseTransformType::ParametersType finalParameters = registration->GetOptimizer()->GetCurrentPosition();
440 for(
unsigned int i=0; i<paramDim; i++)
442 m_EstimatedParameters[i] = finalParameters[i];
447 MITK_INFO(
"Params") << optimizer->GetValue() <<
" :: " << finalParameters;
452 registration->RemoveObserver( pyramid_tag );
463 registration->SetFixedImage( 0, caster_f->GetOutput() );
464 registration->SetMovingImage( 0, caster_m->GetOutput() );
465 registration->SetMetric( base_metric );
466 registration->SetOptimizer( optimizer );
467 registration->SetMovingInitialTransform( transform.GetPointer() );
468 registration->SetNumberOfLevels(max_pyramid_lvl);
469 registration->SetShrinkFactorsPerLevel( shrink_factors );
474 unsigned int pyramid_tag = registration->AddObserver( itk::InitializeEvent(), pyramid_observer );
479 registration->Update();
481 catch(
const itk::ExceptionObject &e)
483 registration->Print( std::cout );
485 MITK_ERROR <<
"[Registration Update] Caught ITK exception: ";
488 mitkThrow() <<
"Registration failed with exception: " << e.what();
493 typename BaseTransformType::ParametersType finalParameters = registration->GetOptimizer()->GetCurrentPosition();
494 for(
unsigned int i=0; i<paramDim; i++)
496 m_EstimatedParameters[i] = finalParameters[i];
501 MITK_INFO(
"Params") << optimizer->GetValue() <<
" :: " << finalParameters;
506 registration->RemoveObserver( pyramid_tag );
513 MITK_INFO(
"Termination") << optimizer->GetStopConditionDescription();
519 optimizer->RemoveObserver( vopt_tag );
528 template<
typename TPixel,
unsigned int VDimension>
533 typedef typename itk::Image< TPixel, VDimension>
ImageType;
534 typedef typename itk::ResampleImageFilter< ImageType, ImageType, double> ResampleImageFilterType;
536 typedef itk::LinearInterpolateImageFunction< ImageType, double > InterpolatorType;
540 typedef itk::NearestNeighborInterpolateImageFunction< ImageType, double > NearestNeighborInterpolatorType;
544 typedef itk::WindowedSincInterpolateImageFunction< ImageType, 7> WindowedSincInterpolatorType;
550 typedef itk::MatrixOffsetTransformBase< double, 3, 3> BaseTransformType;
553 if( this->m_UseAffineTransform )
555 typedef itk::AffineTransform< double > TransformType;
558 TransformType::ParametersType affine_params( TransformType::ParametersDimension );
559 this->GetParameters( &affine_params[0] );
561 transform->SetParameters( affine_params );
563 base_transform = transform;
571 RigidTransformType::ParametersType rigid_params( RigidTransformType::ParametersDimension );
572 this->GetParameters( &rigid_params[0] );
574 rtransform->SetParameters( rigid_params );
576 base_transform = rtransform;
581 resampler->SetInterpolator( linear_interpolator );
582 if( m_UseWindowedSincInterpolator )
583 resampler->SetInterpolator( sinc_interpolator );
584 if ( m_UseNearestNeighborInterpolator)
585 resampler->SetInterpolator ( nn_interpolator );
589 resampler->SetInput( itkImage );
590 resampler->SetTransform( base_transform );
591 resampler->SetReferenceImage( reference_image );
592 resampler->UseReferenceImageOn();
PyramidImageRegistrationMethod()
mitk::Image::Pointer GetResampledMovingImage()
Returns the moving image transformed according to the estimated transformation and resampled to the g...
itk::SmartPointer< Self > Pointer
itk::Euler3DTransform< double > RigidTransformType
void SetMovingImage(mitk::Image::Pointer)
void ResampleMitkImage(itk::Image< TPixel, VDimension > *itkImage, mitk::Image::Pointer &outputImage)
ResampleMitkImage applies the functionality of an the itk::ResampleImageFilter to the given mitk::Ima...
void RegisterTwoImagesV4(itk::Image< TPixel1, VImageDimension1 > *itkImage1, itk::Image< TPixel2, VImageDimension2 > *itkImage2)
The method takes two itk::Images and performs a multi-scale registration on them. ...
Image::Pointer GrabItkImageMemory(itk::SmartPointer< ItkOutputImageType > &itkimage, mitk::Image *mitkImage=nullptr, const BaseGeometry *geometry=nullptr, bool update=true)
Grabs the memory of an itk::Image (with a specific type) and puts it into an mitk::Image.The memory is managed by the mitk::Image after calling this function. The itk::Image remains valid until the mitk::Image decides to free the memory.
map::core::discrete::Elements< 3 >::InternalImageType ImageType
void SetFixedImage(mitk::Image::Pointer)
#define AccessTwoImagesFixedDimensionTypeSubsetByItk(mitkImage1, mitkImage2, itkImageTypeFunction, dimension)
Provides same functionality as AccessTwoImagesFixedDimensionByItk for a subset of types...
itk::Image< unsigned char, 3 > BinaryImageType
void SetFixedImageMask(mitk::Image::Pointer mask)
TransformMatrixType GetLastRotationMatrix()
Get the rotation part of the transformation as a vnl_fixed_matrix
vnl_matrix_fixed< double, 3, 3 > TransformMatrixType
#define AccessFixedDimensionByItk_1(mitkImage, itkImageTypeFunction, dimension, arg1)
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
~PyramidImageRegistrationMethod()
::map::core::RegistrationBase RegistrationType
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.