diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp index 22ec4e672b..adb6b13c99 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp @@ -1,526 +1,597 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPyramidImageRegistrationMethod.h" #include "mitkException.h" #include "mitkImageAccessByItk.h" mitk::PyramidImageRegistrationMethod::PyramidImageRegistrationMethod() : m_FixedImage(NULL), m_MovingImage(NULL), m_CrossModalityRegistration(true), m_UseAffineTransform(true), m_UseWindowedSincInterpolator(false), m_UseNearestNeighborInterpolator(false), m_UseMask(false), m_EstimatedParameters(0), m_InitialParameters(0), m_Verbose(false) { } mitk::PyramidImageRegistrationMethod::~PyramidImageRegistrationMethod() { if( m_EstimatedParameters != NULL) { delete [] m_EstimatedParameters; } } void mitk::PyramidImageRegistrationMethod::SetFixedImage(mitk::Image::Pointer fixed) { if( fixed.IsNotNull() ) { m_FixedImage = fixed; } } void mitk::PyramidImageRegistrationMethod::SetMovingImage(mitk::Image::Pointer moving) { if( moving.IsNotNull() ) { m_MovingImage = moving; } } void mitk::PyramidImageRegistrationMethod::SetFixedImageMask(mitk::Image::Pointer mask) { m_FixedImageMask = mask; } void mitk::PyramidImageRegistrationMethod::Update() { if( m_MovingImage.IsNull() ) { mitkThrow() << " Moving image is null"; } if( m_FixedImage.IsNull() ) { mitkThrow() << " Moving image is null"; } unsigned int allowedDimension = 3; if( m_FixedImage->GetDimension() != allowedDimension || m_MovingImage->GetDimension() != allowedDimension ) { mitkThrow() << " Only 3D Images supported."; } // // One possibility: use the FixedDimesnionByItk, but this instantiates ALL possible // pixel type combinations! // AccessTwoImagesFixedDimensionByItk( m_FixedImage, m_MovingImage, RegisterTwoImages, 3); // in helper: TypeSubset : short, float AccessTwoImagesFixedDimensionTypeSubsetByItk( m_FixedImage, m_MovingImage, RegisterTwoImagesV4, 3); } mitk::PyramidImageRegistrationMethod::TransformMatrixType mitk::PyramidImageRegistrationMethod ::GetLastRotationMatrix() { TransformMatrixType output; if( m_EstimatedParameters == NULL ) { output.set_identity(); return output; } typedef itk::MatrixOffsetTransformBase< double, 3, 3> BaseTransformType; BaseTransformType::Pointer base_transform = BaseTransformType::New(); if( this->m_UseAffineTransform ) { typedef itk::AffineTransform< double > TransformType; TransformType::Pointer transform = TransformType::New(); TransformType::ParametersType affine_params( TransformType::ParametersDimension ); this->GetParameters( &affine_params[0] ); transform->SetParameters( affine_params ); base_transform = transform; } else { typedef itk::Euler3DTransform< double > RigidTransformType; RigidTransformType::Pointer rtransform = RigidTransformType::New(); RigidTransformType::ParametersType rigid_params( RigidTransformType::ParametersDimension ); this->GetParameters( &rigid_params[0] ); rtransform->SetParameters( rigid_params ); base_transform = rtransform; } return base_transform->GetMatrix().GetVnlMatrix(); } mitk::Image::Pointer mitk::PyramidImageRegistrationMethod ::GetResampledMovingImage() { mitk::Image::Pointer output = mitk::Image::New(); //output->Initialize( this->m_FixedImage ); AccessFixedDimensionByItk_1( this->m_MovingImage, ResampleMitkImage, 3, output ); return output; } mitk::Image::Pointer mitk::PyramidImageRegistrationMethod::GetResampledMovingImage(mitk::Image::Pointer movingImage, double* transform) { mitk::Image::Pointer output = mitk::Image::New(); unsigned int dim = 12; if( !m_UseAffineTransform ) dim = 6; if (m_EstimatedParameters == NULL) m_EstimatedParameters = new double[dim]; double tmpParams[12]; // save and set temporal transformation values for( unsigned int i=0; i #include #include #include #include #include #include template void mitk::PyramidImageRegistrationMethod:: RegisterTwoImagesV4(itk::Image* itkImage1, itk::Image* itkImage2) { // Basic typedefs needed typedef typename itk::Image ItkImageTypeFixed; typedef typename itk::Image ItkImageTypeMoving; typedef itk::MatrixOffsetTransformBase< double, VImageDimension1, VImageDimension2 > BaseTransformType; typedef itk::Image< double, 3> ItkRegistrationImageType; typedef itk::CastImageFilter< ItkImageTypeFixed, ItkRegistrationImageType> FixedCastFilterType; typedef itk::CastImageFilter< ItkImageTypeMoving, ItkRegistrationImageType> MovingCastFilterType; typedef typename itk::ImageRegistrationMethodv4< ItkRegistrationImageType, ItkRegistrationImageType, AffineTransformType> RegistrationType; typedef typename itk::MattesMutualInformationImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType> MIMetricType; typedef typename itk::CorrelationImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType > NCMetricType; typedef typename itk::ImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType > BaseMetricType; + typedef typename itk::ImageRegistrationMethodv4< ItkRegistrationImageType, ItkRegistrationImageType, RigidTransformType> RigidRegistrationType; + typedef itk::GradientDescentLineSearchOptimizerv4 OptimizerType; typename ItkImageTypeFixed::Pointer referenceImage = itkImage1; typename ItkImageTypeMoving::Pointer movingImage = itkImage2; // initial parameter dimension ( affine = default ) unsigned int paramDim = 12; typename BaseTransformType::Pointer transform; if( m_UseAffineTransform ) { transform = AffineTransformType::New(); } else { transform = RigidTransformType::New(); paramDim = 6; } typename BaseTransformType::ParametersType initialParams(paramDim); initialParams.Fill(0); if( m_UseAffineTransform ) { initialParams[0] = initialParams[4] = initialParams[8] = 1; } // [Prepare registration] // The ITKv4 Methods ( the MI Metric ) require double-type images so we need to perform cast first typename FixedCastFilterType::Pointer caster_f = FixedCastFilterType::New(); typename MovingCastFilterType::Pointer caster_m = MovingCastFilterType::New(); try { caster_f->SetInput(0, referenceImage ); caster_m->SetInput(0, movingImage ); caster_f->Update(); caster_m->Update(); } catch( const itk::ExceptionObject &/*e*/ ) { return ; } // [Prepare Registration] // Estimate the size of the pyramid based on image dimension // here the image size on the topmost level must remain higher than the threshold unsigned int max_pyramid_lvl = 4; unsigned int max_schedule_val = 8; const unsigned int min_required_image_size = 12; typename ItkImageTypeFixed::RegionType::SizeType image_size = referenceImage->GetLargestPossibleRegion().GetSize(); unsigned int min_value = std::min( image_size[0], std::min( image_size[1], image_size[2])); // Adapt also the optimizer settings to the number of levels float optmaxstep = 10; float optminstep = 0.1f; unsigned int iterations = 40; unsigned int convergence_win_size = 8; double convergence_tolerance = 1e-5; while( min_value / max_schedule_val < min_required_image_size ) { max_schedule_val /= 2; max_pyramid_lvl--; optmaxstep -= 2; optminstep *= 0.5f; convergence_win_size += 4; convergence_tolerance *= 0.5; } typename RegistrationType::ShrinkFactorsArrayType shrink_factors(max_pyramid_lvl); shrink_factors.Fill(1); shrink_factors[0] = max_schedule_val; for( unsigned int i=1; i::Pointer mi_estimator = itk::RegistrationParameterScalesFromPhysicalShift< MIMetricType >::New(); mi_estimator->SetMetric( metric ); optimizer->SetScalesEstimator( mi_estimator ); base_metric = metric; } else { typename NCMetricType::Pointer metric = NCMetricType::New(); typename itk::RegistrationParameterScalesFromPhysicalShift< NCMetricType >::Pointer nc_estimator = itk::RegistrationParameterScalesFromPhysicalShift< NCMetricType >::New(); nc_estimator->SetMetric( metric ); optimizer->SetScalesEstimator( nc_estimator ); base_metric = metric; } optimizer->SetDoEstimateLearningRateOnce( false ); optimizer->SetDoEstimateLearningRateAtEachIteration( true ); optimizer->SetNumberOfIterations( iterations ); optimizer->SetConvergenceWindowSize( convergence_win_size ); optimizer->SetMaximumStepSizeInPhysicalUnits( optmaxstep ); optimizer->SetMinimumConvergenceValue( convergence_tolerance ); // line search options optimizer->SetEpsilon( 1e-3 ); optimizer->SetLowerLimit( 0.3 ); optimizer->SetUpperLimit( 1.7 ); optimizer->SetMaximumLineSearchIterations( 20 ); // add observer tag if verbose unsigned long vopt_tag = 0; if(m_Verbose) { MITK_INFO << " :: Starting at " << initialParams; OptimizerIterationCommandv4< OptimizerType >::Pointer iterationObserver = OptimizerIterationCommandv4::New(); vopt_tag = optimizer->AddObserver( itk::IterationEvent(), iterationObserver ); } // Initializing by Geometry if( !m_UseAffineTransform && m_InitializeByGeometry ) { typedef itk::CenteredVersorTransformInitializer< ItkImageTypeFixed, ItkImageTypeMoving> TransformInitializerType; typename TransformInitializerType::TransformType::Pointer rigidTransform = TransformInitializerType::TransformType::New() ; MITK_INFO << "Initializer starting at : " << rigidTransform->GetParameters(); typename TransformInitializerType::Pointer initializer = TransformInitializerType::New(); initializer->SetTransform( rigidTransform); initializer->SetFixedImage( referenceImage.GetPointer() ); initializer->SetMovingImage( movingImage.GetPointer() ); initializer->MomentsOn(); initializer->InitializeTransform(); MITK_INFO << "Initialized Rigid position : " << rigidTransform->GetParameters(); initialParams[3] = rigidTransform->GetParameters()[3]; initialParams[4] = rigidTransform->GetParameters()[4]; initialParams[5] = rigidTransform->GetParameters()[5]; } // [Prepare Registration] // Masking (Optional) if( m_UseMask ) { typedef itk::Image BinaryImageType; BinaryImageType::Pointer itkFixedImageMask = BinaryImageType::New(); itk::ImageMaskSpatialObject< 3 >::Pointer fixedMaskSpatialObject = itk::ImageMaskSpatialObject< 3 >::New(); CastToItkImage( m_FixedImageMask, itkFixedImageMask); itk::NotImageFilter::Pointer notFilter = itk::NotImageFilter::New(); notFilter->SetInput(itkFixedImageMask); notFilter->Update(); fixedMaskSpatialObject->SetImage( notFilter->GetOutput() ); base_metric->SetFixedImageMask( fixedMaskSpatialObject ); } + + if( m_EstimatedParameters != NULL) + { + delete [] m_EstimatedParameters; + } + + m_EstimatedParameters = new double[paramDim]; + + //----------------- + //----------------- + // [Prepare Registration] // combine all components to set-up registration - typename RegistrationType::Pointer registration = RegistrationType::New(); + if( m_UseAffineTransform ) + { - registration->SetFixedImage( 0, caster_f->GetOutput() ); - registration->SetMovingImage( 0, caster_m->GetOutput() ); - registration->SetMetric( base_metric ); - registration->SetOptimizer( optimizer ); - registration->SetMovingInitialTransform( transform.GetPointer() ); - registration->SetNumberOfLevels(max_pyramid_lvl); - registration->SetShrinkFactorsPerLevel( shrink_factors ); + typename RegistrationType::Pointer registration = RegistrationType::New(); - // observe the pyramid level change in order to adapt parameters - typename PyramidOptControlCommandv4::Pointer pyramid_observer = - PyramidOptControlCommandv4::New(); - unsigned int pyramid_tag = registration->AddObserver( itk::InitializeEvent(), pyramid_observer ); + registration->SetFixedImage( 0, caster_f->GetOutput() ); + registration->SetMovingImage( 0, caster_m->GetOutput() ); + registration->SetMetric( base_metric ); + registration->SetOptimizer( optimizer ); + registration->SetMovingInitialTransform( transform.GetPointer() ); + registration->SetNumberOfLevels(max_pyramid_lvl); + registration->SetShrinkFactorsPerLevel( shrink_factors ); + // observe the pyramid level change in order to adapt parameters + typename PyramidOptControlCommandv4::Pointer pyramid_observer = + PyramidOptControlCommandv4::New(); + unsigned int pyramid_tag = registration->AddObserver( itk::InitializeEvent(), pyramid_observer ); + + + try + { + registration->Update(); + } + catch( const itk::ExceptionObject &e) + { + registration->Print( std::cout ); + + MITK_ERROR << "[Registration Update] Caught ITK exception: "; + MITK_ERROR("itk.exception") << e.what(); + + mitkThrow() << "Registration failed with exception: " << e.what(); + } + + // [Post Registration] + // Retrieve the last transformation parameters from the performed registration task + typename BaseTransformType::ParametersType finalParameters = registration->GetOptimizer()->GetCurrentPosition(); + for( unsigned int i=0; iGetValue() << " :: " << finalParameters; + } + + if( pyramid_tag ) + { + registration->RemoveObserver( pyramid_tag ); + } - try - { - registration->Update(); } - catch( const itk::ExceptionObject &e) + //----------- + //----------- + else { - registration->Print( std::cout ); - MITK_ERROR << "[Registration Update] Caught ITK exception: "; - MITK_ERROR("itk.exception") << e.what(); + typename RigidRegistrationType::Pointer registration = RigidRegistrationType::New(); - mitkThrow() << "Registration failed with exception: " << e.what(); - } + registration->SetFixedImage( 0, caster_f->GetOutput() ); + registration->SetMovingImage( 0, caster_m->GetOutput() ); + registration->SetMetric( base_metric ); + registration->SetOptimizer( optimizer ); + registration->SetMovingInitialTransform( transform.GetPointer() ); + registration->SetNumberOfLevels(max_pyramid_lvl); + registration->SetShrinkFactorsPerLevel( shrink_factors ); - // [Post Registration] - // Retrieve the last transformation parameters from the performed registration task - if( m_EstimatedParameters != NULL) - { - delete [] m_EstimatedParameters; - } + // observe the pyramid level change in order to adapt parameters + typename PyramidOptControlCommandv4::Pointer pyramid_observer = + PyramidOptControlCommandv4::New(); + unsigned int pyramid_tag = registration->AddObserver( itk::InitializeEvent(), pyramid_observer ); - m_EstimatedParameters = new double[paramDim]; - typename BaseTransformType::ParametersType finalParameters = registration->GetOptimizer()->GetCurrentPosition(); - for( unsigned int i=0; iUpdate(); + } + catch( const itk::ExceptionObject &e) + { + registration->Print( std::cout ); - MITK_INFO("Params") << optimizer->GetValue() << " :: " << finalParameters; + MITK_ERROR << "[Registration Update] Caught ITK exception: "; + MITK_ERROR("itk.exception") << e.what(); + + mitkThrow() << "Registration failed with exception: " << e.what(); + } + + // [Post Registration] + // Retrieve the last transformation parameters from the performed registration task + typename BaseTransformType::ParametersType finalParameters = registration->GetOptimizer()->GetCurrentPosition(); + for( unsigned int i=0; iGetValue() << " :: " << finalParameters; + } + + if( pyramid_tag ) + { + registration->RemoveObserver( pyramid_tag ); + } + + } if( m_Verbose ) { MITK_INFO("Termination") << optimizer->GetStopConditionDescription(); } // remove optimizer tag if used if( vopt_tag ) { optimizer->RemoveObserver( vopt_tag ); } - if( pyramid_tag ) - { - registration->RemoveObserver( pyramid_tag ); - } + + } template< typename TPixel, unsigned int VDimension> void mitk::PyramidImageRegistrationMethod:: ResampleMitkImage( itk::Image* itkImage, mitk::Image::Pointer& outputImage ) { typedef typename itk::Image< TPixel, VDimension> ImageType; typedef typename itk::ResampleImageFilter< ImageType, ImageType, double> ResampleImageFilterType; typedef itk::LinearInterpolateImageFunction< ImageType, double > InterpolatorType; typename InterpolatorType::Pointer linear_interpolator = InterpolatorType::New(); typedef itk::NearestNeighborInterpolateImageFunction< ImageType, double > NearestNeighborInterpolatorType; typename NearestNeighborInterpolatorType::Pointer nn_interpolator = NearestNeighborInterpolatorType::New(); typedef itk::WindowedSincInterpolateImageFunction< ImageType, 7> WindowedSincInterpolatorType; typename WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); typename ImageType::Pointer reference_image = ImageType::New(); CastToItkImage(m_FixedImage,reference_image); typedef itk::MatrixOffsetTransformBase< double, 3, 3> BaseTransformType; BaseTransformType::Pointer base_transform = BaseTransformType::New(); if( this->m_UseAffineTransform ) { typedef itk::AffineTransform< double > TransformType; TransformType::Pointer transform = TransformType::New(); TransformType::ParametersType affine_params( TransformType::ParametersDimension ); this->GetParameters( &affine_params[0] ); transform->SetParameters( affine_params ); base_transform = transform; } // Rigid else { typedef itk::Euler3DTransform< double > RigidTransformType; RigidTransformType::Pointer rtransform = RigidTransformType::New(); RigidTransformType::ParametersType rigid_params( RigidTransformType::ParametersDimension ); this->GetParameters( &rigid_params[0] ); rtransform->SetParameters( rigid_params ); base_transform = rtransform; } typename ResampleImageFilterType::Pointer resampler = ResampleImageFilterType::New(); resampler->SetInterpolator( linear_interpolator ); if( m_UseWindowedSincInterpolator ) resampler->SetInterpolator( sinc_interpolator ); if ( m_UseNearestNeighborInterpolator) resampler->SetInterpolator ( nn_interpolator ); //resampler->SetNumberOfThreads(1); resampler->SetInput( itkImage ); resampler->SetTransform( base_transform ); resampler->SetReferenceImage( reference_image ); resampler->UseReferenceImageOn(); resampler->Update(); mitk::GrabItkImageMemory( resampler->GetOutput(), outputImage); } diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h index 2bf6d6097c..98d45a09ea 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h @@ -1,212 +1,212 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKPYRAMIDREGISTRATIONMETHODHELPER_H #define MITKPYRAMIDREGISTRATIONMETHODHELPER_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkImageAccessByItk.h" /** * @brief Provides same functionality as \a AccessTwoImagesFixedDimensionByItk for a subset of types * * For now, the subset defined is only short and float. */ #define AccessTwoImagesFixedDimensionTypeSubsetByItk(mitkImage1, mitkImage2, itkImageTypeFunction, dimension) \ { \ const mitk::PixelType& pixelType1 = mitkImage1->GetPixelType(); \ const mitk::PixelType& pixelType2 = mitkImage2->GetPixelType(); \ const mitk::Image* constImage1 = mitkImage1; \ const mitk::Image* constImage2 = mitkImage2; \ mitk::Image* nonConstImage1 = const_cast(constImage1); \ mitk::Image* nonConstImage2 = const_cast(constImage2); \ nonConstImage1->Update(); \ nonConstImage2->Update(); \ _checkSpecificDimension(mitkImage1, (dimension)); \ _checkSpecificDimension(mitkImage2, (dimension)); \ _accessTwoImagesByItkForEach(itkImageTypeFunction, ((short, dimension))((unsigned short, dimension))((float, dimension))((double, dimension)), ((short, dimension))((unsigned short, dimension))((float, dimension))((double, dimension)) ) \ { \ std::string msg("Pixel type "); \ msg.append(pixelType1.GetComponentTypeAsString() ); \ msg.append(" or pixel type "); \ msg.append(pixelType2.GetComponentTypeAsString() ); \ msg.append(" is not in " MITK_PP_STRINGIZE(MITK_ACCESSBYITK_TYPES_DIMN_SEQ(dimension))); \ throw mitk::AccessByItkException(msg); \ } \ } /** * @brief The PyramidOptControlCommand class stears the step lenght of the * gradient descent optimizer in multi-scale registration methods */ template class PyramidOptControlCommand : public itk::Command { public: typedef itk::RegularStepGradientDescentOptimizer OptimizerType; mitkClassMacro(PyramidOptControlCommand, itk::Command) itkFactorylessNewMacro(Self) itkCloneMacro(Self) void Execute(itk::Object *caller, const itk::EventObject & /*event*/) { RegistrationType* registration = dynamic_cast< RegistrationType* >( caller ); if( registration == NULL) return; MITK_DEBUG << "\t - Pyramid level " << registration->GetCurrentLevel(); if( registration->GetCurrentLevel() == 0 ) { MITK_WARN("OptCommand") << "Cast to registration failed"; return; } OptimizerType* optimizer = dynamic_cast< OptimizerType* >(registration->GetOptimizer()); if( optimizer == NULL) { MITK_WARN("OptCommand") << "Cast to optimizer failed"; return; } - MITK_INFO /*<< optimizer->GetStopConditionDescription() << "\n"*/ + MITK_DEBUG /*<< optimizer->GetStopConditionDescription() << "\n"*/ << optimizer->GetValue() << " : " << optimizer->GetCurrentPosition(); optimizer->SetMaximumStepLength( optimizer->GetMaximumStepLength() * 0.25f ); optimizer->SetMinimumStepLength( optimizer->GetMinimumStepLength() * 0.1f ); // optimizer->SetNumberOfIterations( optimizer->GetNumberOfIterations() * 1.5f ); } void Execute(const itk::Object * /*object*/, const itk::EventObject & /*event*/){} }; #include template class PyramidOptControlCommandv4 : public itk::Command { public: typedef itk::GradientDescentLineSearchOptimizerv4 OptimizerType; mitkClassMacro(PyramidOptControlCommandv4, itk::Command) itkFactorylessNewMacro(Self) itkCloneMacro(Self) void Execute(itk::Object *caller, const itk::EventObject & /*event*/) { RegistrationType* registration = dynamic_cast< RegistrationType* >( caller ); if( registration == NULL) return; MITK_DEBUG << "\t - Pyramid level " << registration->GetCurrentLevel(); if( registration->GetCurrentLevel() == 0 ) return; OptimizerType* optimizer = dynamic_cast< OptimizerType* >( registration->GetOptimizer() ); if( optimizer == NULL) { MITK_WARN("OptCommand4") << "Cast to optimizer failed"; return; } optimizer->SetNumberOfIterations( optimizer->GetNumberOfIterations() * 2.5 ); optimizer->SetMaximumStepSizeInPhysicalUnits( optimizer->GetMaximumStepSizeInPhysicalUnits() * 0.4); MITK_INFO("Pyramid.Command.Iter") << optimizer->GetNumberOfIterations(); MITK_INFO("Pyramid.Command.MaxStep") << optimizer->GetMaximumStepSizeInPhysicalUnits(); } void Execute(const itk::Object * /*object*/, const itk::EventObject & /*event*/){} }; template class OptimizerIterationCommand : public itk::Command { public: mitkClassMacro(OptimizerIterationCommand, itk::Command) itkFactorylessNewMacro(Self) itkCloneMacro(Self) void Execute(itk::Object *caller, const itk::EventObject & /*event*/) { OptimizerType* optimizer = dynamic_cast< OptimizerType* >( caller ); unsigned int currentIter = optimizer->GetCurrentIteration(); MITK_INFO << "[" << currentIter << "] : " << optimizer->GetValue() << " : " << optimizer->GetCurrentPosition(); } void Execute(const itk::Object * /*object*/, const itk::EventObject & /*event*/) { } }; template class OptimizerIterationCommandv4 : public itk::Command { public: itkNewMacro( OptimizerIterationCommandv4 ) void Execute(itk::Object *object, const itk::EventObject & event) { OptimizerType* optimizer = dynamic_cast< OptimizerType* >( object ); if( typeid( event ) != typeid( itk::IterationEvent ) ) { return; } unsigned int currentIter = optimizer->GetCurrentIteration(); MITK_INFO << "[" << currentIter << "] : " << optimizer->GetCurrentMetricValue() << " : " << optimizer->GetMetric()->GetParameters() ; //<< " : " << optimizer->GetScales(); } void Execute(const itk::Object * object, const itk::EventObject & event) { } }; #endif // MITKPYRAMIDREGISTRATIONMETHODHELPER_H