/*========================================================================= * * 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 itkThresholdSegmentationLevelSetFunction_h #define itkThresholdSegmentationLevelSetFunction_h #include "itkSegmentationLevelSetFunction.h" #include "itkNumericTraits.h" namespace itk { /** \class ThresholdSegmentationLevelSetFunction * * \brief This function is used in ThresholdSegmentationLevelSetImageFilter to * segment structures in images based on intensity values. * * \par SegmentationLevelSetFunction is a subclass of the generic LevelSetFunction. * It is useful for segmentations based on intensity values in an image. It works * by constructing a speed term (feature image) with positive values inside an * intensity window (between a low and high threshold) and negative values * outside that intensity window. The evolving level set front will lock onto * regions that are at the edges of the intensity window. * * You may optionally add a Laplacian calculation on the image to the * threshold-based speed term by setting the EdgeWeight parameter to a * non-zero value. The Laplacian term will cause the evolving surface to * be more strongly attracted to image edges. Several parameters control a * preprocessing FeatureImage smoothing stage applied only to the Laplacian * calculation. * * \par * Image \f$ f \f$ is thresholded pixel by pixel using upper threshold * \f$ U \f$ and lower threshold \f$ L \f$ according to the following formula. * * \par * \f$ f(x) = \left\{ \begin{array}{ll} g(x) - L & \mbox{if $(g)x < (U-L)/2 + L$} \\ U - g(x) & \mbox{otherwise} * \end{array} \right. \f$ * * \sa SegmentationLevelSetImageFunction * \sa ThresholdSegmentationLevelSetImageFilter * \ingroup ITKLevelSets */ template class ITK_TEMPLATE_EXPORT ThresholdSegmentationLevelSetFunction : public SegmentationLevelSetFunction { public: ITK_DISALLOW_COPY_AND_MOVE(ThresholdSegmentationLevelSetFunction); /** Standard class type aliases. */ using Self = ThresholdSegmentationLevelSetFunction; using Superclass = SegmentationLevelSetFunction; using Pointer = SmartPointer; using ConstPointer = SmartPointer; using FeatureImageType = TFeatureImageType; /** Method for creation through the object factory. */ itkNewMacro(Self); /** \see LightObject::GetNameOfClass() */ itkOverrideGetNameOfClassMacro(ThresholdSegmentationLevelSetFunction); /** Extract some parameters from the superclass. */ using typename Superclass::ImageType; using typename Superclass::ScalarValueType; using typename Superclass::FeatureScalarType; using typename Superclass::RadiusType; /** Extract some parameters from the superclass. */ static constexpr unsigned int ImageDimension = Superclass::ImageDimension; /** Set/Get threshold values */ void SetUpperThreshold(FeatureScalarType f) { m_UpperThreshold = f; } FeatureScalarType GetUpperThreshold() const { return m_UpperThreshold; } void SetLowerThreshold(FeatureScalarType f) { m_LowerThreshold = f; } FeatureScalarType GetLowerThreshold() const { return m_LowerThreshold; } void CalculateSpeedImage() override; void Initialize(const RadiusType & r) override { Superclass::Initialize(r); this->SetAdvectionWeight(ScalarValueType{}); this->SetPropagationWeight(-1.0 * NumericTraits::OneValue()); this->SetCurvatureWeight(NumericTraits::OneValue()); } /** Set/Get the weight applied to the edge (Laplacian) attractor in the speed * term function. Zero will turn this term off. */ void SetEdgeWeight(const ScalarValueType p) { m_EdgeWeight = p; } ScalarValueType GetEdgeWeight() const { return m_EdgeWeight; } /** Anisotropic diffusion is applied to the FeatureImage before calculating * the Laplacian (edge) term. This method sets/gets the smoothing * conductance. */ void SetSmoothingConductance(const ScalarValueType p) { m_SmoothingConductance = p; } ScalarValueType GetSmoothingConductance() const { return m_SmoothingConductance; } /** Anisotropic diffusion is applied to the FeatureImage before calculating * the Laplacian (edge) term. This method sets/gets the number of diffusion * iterations. */ void SetSmoothingIterations(const int p) { m_SmoothingIterations = p; } int GetSmoothingIterations() const { return m_SmoothingIterations; } /** Anisotropic diffusion is applied to the FeatureImage before calculating * the Laplacian (edge) term. This method sets/gets the diffusion time * step. */ void SetSmoothingTimeStep(const ScalarValueType i) { m_SmoothingTimeStep = i; } ScalarValueType GetSmoothingTimeStep() const { return m_SmoothingTimeStep; } protected: ThresholdSegmentationLevelSetFunction() { m_UpperThreshold = NumericTraits::max(); m_LowerThreshold = NumericTraits::NonpositiveMin(); this->SetAdvectionWeight(0.0); this->SetPropagationWeight(1.0); this->SetCurvatureWeight(1.0); this->SetSmoothingIterations(5); this->SetSmoothingConductance(0.8); this->SetSmoothingTimeStep(0.1); this->SetEdgeWeight(0.0); } ~ThresholdSegmentationLevelSetFunction() override = default; void PrintSelf(std::ostream & os, Indent indent) const override { Superclass::PrintSelf(os, indent); os << indent << "UpperThreshold: " << m_UpperThreshold << std::endl; os << indent << "LowerThreshold: " << m_LowerThreshold << std::endl; os << indent << "EdgeWeight: " << m_EdgeWeight << std::endl; os << indent << "SmoothingTimeStep: " << m_SmoothingTimeStep << std::endl; os << indent << "SmoothingIterations: " << m_SmoothingIterations << std::endl; os << indent << "SmoothingConductance: " << m_SmoothingConductance << std::endl; } FeatureScalarType m_UpperThreshold{}; FeatureScalarType m_LowerThreshold{}; ScalarValueType m_EdgeWeight{}; ScalarValueType m_SmoothingConductance{}; int m_SmoothingIterations{}; ScalarValueType m_SmoothingTimeStep{}; }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION # include "itkThresholdSegmentationLevelSetFunction.hxx" #endif #endif