From bd2605eeb540ec4b149f9ab1c097ed119471858c Mon Sep 17 00:00:00 2001 From: Pablo Alvarez Date: Tue, 15 Jun 2021 14:52:23 +0200 Subject: [PATCH] ENH: Add support for multiple metrics and regularization In addition to m_NumberOfMetrics, three counters were added to the itkCombinationImageToImageMetric: m_NumberOfImageMetrics, m_NumberOfTransformMetrics and m_NumberOfPointSetMetrics. Casting is used to verify the type of metric and to count metrics independetly. The number of interpolators, images, masks and image pyramids is checked only against m_NumberOfMetrics. The transform and point set metric counters may be useful in the future. resolves #481 --- .../itkCombinationImageToImageMetric.h | 11 ++++++ .../itkCombinationImageToImageMetric.hxx | 30 ++++++++++++++++ ...MultiResolutionImageRegistrationMethod.hxx | 35 +++++++++++-------- 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/Components/Registrations/MultiMetricMultiResolutionRegistration/itkCombinationImageToImageMetric.h b/Components/Registrations/MultiMetricMultiResolutionRegistration/itkCombinationImageToImageMetric.h index 0899dd2d2..ed8183dac 100644 --- a/Components/Registrations/MultiMetricMultiResolutionRegistration/itkCombinationImageToImageMetric.h +++ b/Components/Registrations/MultiMetricMultiResolutionRegistration/itkCombinationImageToImageMetric.h @@ -18,6 +18,7 @@ #ifndef itkCombinationImageToImageMetric_h #define itkCombinationImageToImageMetric_h +#include "itkTransformPenaltyTerm.h" #include "itkAdvancedImageToImageMetric.h" #include "itkSingleValuedPointSetToPointSetMetric.h" @@ -135,6 +136,10 @@ class CombinationImageToImageMetric : public AdvancedImageToImageMetric MovingImageDerivativeScalesType; + /** Typedef for transform penalty metrics. */ + typedef TransformPenaltyTerm TransformMetricType; + typedef typename TransformMetricType::Pointer TransformMetricPointer; + /** Typedef for the PointSetMetric. */ typedef PointSet m_Metrics; std::vector m_MetricWeights; std::vector m_MetricRelativeWeights; diff --git a/Components/Registrations/MultiMetricMultiResolutionRegistration/itkCombinationImageToImageMetric.hxx b/Components/Registrations/MultiMetricMultiResolutionRegistration/itkCombinationImageToImageMetric.hxx index c4884bdb1..8ea1c5b97 100644 --- a/Components/Registrations/MultiMetricMultiResolutionRegistration/itkCombinationImageToImageMetric.hxx +++ b/Components/Registrations/MultiMetricMultiResolutionRegistration/itkCombinationImageToImageMetric.hxx @@ -145,6 +145,9 @@ template CombinationImageToImageMetric::CombinationImageToImageMetric() { this->m_NumberOfMetrics = 0; + this->m_NumberOfImageMetrics = 0; + this->m_NumberOfTransformMetrics = 0; + this->m_NumberOfPointSetMetrics = 0; this->m_UseRelativeWeights = false; this->ComputeGradientOff(); @@ -164,6 +167,9 @@ CombinationImageToImageMetric::PrintSelf(std::ostream /** Add debugging information. */ os << "NumberOfMetrics: " << this->m_NumberOfMetrics << std::endl; + os << "NumberOfImageMetrics: " << this->m_NumberOfImageMetrics << std::endl; + os << "NumberOfTransformMetrics: " << this->m_NumberOfTransformMetrics << std::endl; + os << "NumberOfPointSetMetrics: " << this->m_NumberOfPointSetMetrics << std::endl; for (unsigned int i = 0; i < this->m_NumberOfMetrics; ++i) { os << "Metric " << i << ":\n"; @@ -280,6 +286,30 @@ CombinationImageToImageMetric::SetMetric(SingleValued if (metric != this->m_Metrics[pos]) { + PointSetMetricType * testPtr1 = dynamic_cast(metric); + TransformMetricType * testPtr2 = dynamic_cast(metric); + if (!this->m_Metrics[pos]) // if the metric has not been set + { + // Update numberOfMetric counters + if (testPtr1) + { + this->m_NumberOfPointSetMetrics++; + } + else if (testPtr2) + { + this->m_NumberOfTransformMetrics++; + } + else + { + this->m_NumberOfImageMetrics++; + } + } + else + { + // /TODO: Logic to update numberOfMetric counters if a metric is replaced? + // not needed for elastix exe ... + } + this->m_Metrics[pos] = metric; this->Modified(); } diff --git a/Components/Registrations/MultiMetricMultiResolutionRegistration/itkMultiMetricMultiResolutionImageRegistrationMethod.hxx b/Components/Registrations/MultiMetricMultiResolutionRegistration/itkMultiMetricMultiResolutionImageRegistrationMethod.hxx index 8842346af..def7fc5f2 100644 --- a/Components/Registrations/MultiMetricMultiResolutionRegistration/itkMultiMetricMultiResolutionImageRegistrationMethod.hxx +++ b/Components/Registrations/MultiMetricMultiResolutionRegistration/itkMultiMetricMultiResolutionImageRegistrationMethod.hxx @@ -565,18 +565,18 @@ MultiMetricMultiResolutionImageRegistrationMethod::Ch } /** nrofmetrics >= nrofinterpolators >= nrofpyramids >= nofimages */ - unsigned int nrOfMetrics = this->GetCombinationMetric()->GetNumberOfMetrics(); - if (this->GetNumberOfInterpolators() > nrOfMetrics) + unsigned int nrOfImageMetrics = this->GetCombinationMetric()->GetNumberOfImageMetrics(); + if (this->GetNumberOfInterpolators() > nrOfImageMetrics) { itkExceptionMacro(<< "NumberOfInterpolators can not exceed the " << "NumberOfMetrics in the CombinationMetric!"); } - if (this->GetNumberOfFixedImagePyramids() > nrOfMetrics) + if (this->GetNumberOfFixedImagePyramids() > nrOfImageMetrics) { itkExceptionMacro(<< "NumberOfFixedImagePyramids can not exceed the " << "NumberOfMetrics in the CombinationMetric!"); } - if (this->GetNumberOfMovingImagePyramids() > nrOfMetrics) + if (this->GetNumberOfMovingImagePyramids() > nrOfImageMetrics) { itkExceptionMacro(<< "NumberOfMovingImagePyramids can not exceed the " << "NumberOfMetrics in the CombinationMetric!"); @@ -587,31 +587,36 @@ MultiMetricMultiResolutionImageRegistrationMethod::Ch << "NumberOfInterpolators!"); } - /** For all components: ==nrofmetrics of ==1. */ - if ((this->GetNumberOfInterpolators() != 1) && (this->GetNumberOfInterpolators() != nrOfMetrics)) + /** For all components: ==nrOfImageMetrics or == 1. */ + if ((this->GetNumberOfInterpolators() != 1) && (this->GetNumberOfInterpolators() != nrOfImageMetrics)) { itkExceptionMacro(<< "The NumberOfInterpolators should equal 1 " - << "or equal the NumberOfMetrics"); + << "or equal the NumberOfImageMetrics (" + << nrOfImageMetrics << ")"); } - if ((this->GetNumberOfFixedImagePyramids() != 1) && (this->GetNumberOfFixedImagePyramids() != nrOfMetrics)) + if ((this->GetNumberOfFixedImagePyramids() != 1) && (this->GetNumberOfFixedImagePyramids() != nrOfImageMetrics)) { itkExceptionMacro(<< "The NumberOfFixedImagePyramids should equal 1 " - << "or equal the NumberOfMetrics"); + << "or equal the NumberOfImageMetrics (" + << nrOfImageMetrics << ")"); } - if ((this->GetNumberOfMovingImagePyramids() != 1) && (this->GetNumberOfMovingImagePyramids() != nrOfMetrics)) + if ((this->GetNumberOfMovingImagePyramids() != 1) && (this->GetNumberOfMovingImagePyramids() != nrOfImageMetrics)) { itkExceptionMacro(<< "The NumberOfMovingImagePyramids should equal 1 " - << "or equal the NumberOfMetrics"); + << "or equal the NumberOfImageMetrics (" + << nrOfImageMetrics << ")"); } - if ((this->GetNumberOfFixedImages() != 1) && (this->GetNumberOfFixedImages() != nrOfMetrics)) + if ((this->GetNumberOfFixedImages() != 1) && (this->GetNumberOfFixedImages() != nrOfImageMetrics)) { itkExceptionMacro(<< "The NumberOfFixedImages should equal 1 " - << "or equal the NumberOfMetrics"); + << "or equal the NumberOfImageMetrics (" + << nrOfImageMetrics << ")"); } - if ((this->GetNumberOfMovingImages() != 1) && (this->GetNumberOfMovingImages() != nrOfMetrics)) + if ((this->GetNumberOfMovingImages() != 1) && (this->GetNumberOfMovingImages() != nrOfImageMetrics)) { itkExceptionMacro(<< "The NumberOfMovingImages should equal 1 " - << "or equal the NumberOfMetrics"); + << "or equal the NumberOfImageMetrics (" + << nrOfImageMetrics << ")"); } } // end CheckOnInitialize()