/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkMatchCardinalityImageToImageMetric_h #define itkMatchCardinalityImageToImageMetric_h /** * TODO: This class needs to be more tightly integrated with the new * multi-threaded ImageToImageMetric. */ #include "itkImageToImageMetric.h" #include "itkPoint.h" #include namespace itk { /** \class MatchCardinalityImageToImageMetric * \brief Computes similarity between two objects to be registered * * This Class is templated over the type of the fixed and moving * images to be compared. * * This metric computes cardinality of the set of pixels that match * exactly between the moving and fixed images. The spatial * correspondence between both images is established through a * Transform. Pixel values are taken from the Moving image. Their * positions are mapped to the Fixed image and result in general in * non-grid position on it. Values at these non-grid position of the * Fixed image are interpolated using a user-selected Interpolator. * * This metric is designed for matching label maps. All pixel * mismatches are considered equal whether they are between label 1 * and label 2 or between label 1 and label 500. In other words, the * magnitude of an individual label mismatch is not relevant, or the * occurrence of a label mismatch is important. * * Given the nature of label maps, a nearest neighbor interpolator is * the preferred interpolator. * * The metric measure can measure the number of pixel matches (pixels * with exactly the same label) or pixel mismatches (pixels with * different labels). The returned metric value is the number of pixel * matches (or mismatches) normalized by the number of pixels * considered. The number of pixel considered is a function of the * number of pixels in the overlap of the fixed and moving image * buffers conditional on any assigned masks. * * \ingroup RegistrationMetrics * \ingroup ITKRegistrationCommon */ template class ITK_TEMPLATE_EXPORT MatchCardinalityImageToImageMetric : public ImageToImageMetric { public: ITK_DISALLOW_COPY_AND_MOVE(MatchCardinalityImageToImageMetric); /** Standard class type aliases. */ using Self = MatchCardinalityImageToImageMetric; using Superclass = ImageToImageMetric; using Pointer = SmartPointer; using ConstPointer = SmartPointer; /** Method for creation through the object factory. */ itkNewMacro(Self); /** \see LightObject::GetNameOfClass() */ itkOverrideGetNameOfClassMacro(MatchCardinalityImageToImageMetric); /** Types transferred from the base class */ using typename Superclass::RealType; using typename Superclass::TransformType; using typename Superclass::TransformPointer; using typename Superclass::TransformParametersType; using typename Superclass::TransformJacobianType; using typename Superclass::GradientPixelType; using typename Superclass::MeasureType; using typename Superclass::DerivativeType; using typename Superclass::FixedImageType; using typename Superclass::MovingImageType; using typename Superclass::FixedImageConstPointer; using typename Superclass::MovingImageConstPointer; using typename Superclass::FixedImageRegionType; /** Get the derivatives of the match measure. */ void GetDerivative(const TransformParametersType &, DerivativeType & derivative) const override { itkWarningMacro("This metric does not provide metric derivatives."); derivative.Fill(typename DerivativeType::ValueType{}); } /** Get the value of the metric at a particular parameter * setting. The metric value is the number of pixel matches (or * mismatches, see SetMeasureMatches()) normalized by the number * of pixels under consideration (within the buffer and if * specified within a mask). In other words, the metric measure the * percentage of pixel matches or mismatches. */ MeasureType GetValue(const TransformParametersType & parameters) const override; /** Set/Get whether this metric measures pixel matches or pixel * mismatches. Note the GetValue() returns the number of matches (or * mismatches) normalized by the number of pixels considered. In * other words, the metric measures the percentage of pixel matches * or mismatches. The default is to measure matches * (MeasureMatchesOn). */ itkSetMacro(MeasureMatches, bool); itkBooleanMacro(MeasureMatches); itkGetConstMacro(MeasureMatches, bool); /** Return the multithreader used by this class. */ MultiThreaderBase * GetMultiThreader() { return m_Threader; } protected: MatchCardinalityImageToImageMetric(); ~MatchCardinalityImageToImageMetric() override = default; void PrintSelf(std::ostream & os, Indent indent) const override; /** * Non-const version of GetValue(). This is a hack around various * const issues with trying to spawn threads from the const version * of GetValue(). */ MeasureType GetNonconstValue(const TransformParametersType & parameters); /** * Thread worker routine to calculate the contribution of the a * subregion to the overall metric. Can only be called from * GetValue(). */ virtual void ThreadedGetValue(const FixedImageRegionType & regionForThread, ThreadIdType threadId); /** Split the FixedImageRegion into "num" pieces, returning * region "i" as "splitRegion". This method is called "num" times. The * regions must not overlap. The method returns the number of pieces that * the routine is capable of splitting the FixedImageRegion, * i.e. return value is less than or equal to "num". */ virtual ThreadIdType SplitFixedRegion(ThreadIdType i, int num, FixedImageRegionType & splitRegion); /** Static function used as a "callback" by the MultiThreaderBase. The threading * library will call this routine for each thread, which will delegate the * control to ThreadedGetValue. * * Calls the ThreadedGenerateData method after setting the correct region for this thread. */ static ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION ThreaderCallback(void * arg); /** Internal structure used for passing image data into the threading library */ struct ThreadStruct { Pointer Metric; }; private: // default to measure percentage of pixel matches bool m_MeasureMatches{ true }; std::vector m_ThreadMatches{}; std::vector m_ThreadCounts{}; /** Support processing data in multiple threads. Used by subclasses * (e.g., ImageSource). */ MultiThreaderBase::Pointer m_Threader{ MultiThreaderBase::New() }; }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION # include "itkMatchCardinalityImageToImageMetric.hxx" #endif #endif