/*========================================================================= * * 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 itkNormalVectorDiffusionFunction_h #define itkNormalVectorDiffusionFunction_h #include "itkNormalVectorFunctionBase.h" #include "itkNumericTraits.h" #include namespace itk { /** * \class NormalVectorDiffusionFunction * * \brief This class defines all the necessary functionality for performing * isotropic and anisotropic diffusion operations on vector neighborhoods from * a sparse image. * * \par * This class implements the actual computations for performing isotropic and * anisotropic diffusion operations on a neighborhood of unit length * vectors. Moreover, this processing is intrinsic to a manifold as specified * by the ManifoldNormal member variables in the nodes of the sparse image. * * \par * Since the only difference between isotropic and anisotropic diffusion is the * execution of 1 extra line of code, we have implemented both in this class * and made the choice between the two depend on a parameter (see below). * \par PARAMETERS * The choice between is isotropic/anisotropic diffusion is made by the * parameter NormalProcessType. A value of 0 corresponds to isotropic diffusion * whereas a value of 1 corresponds to anisotropic diffusion. If anisotropic * diffusion is chosen, the parameter ConductanceParameter should be set. This * conductance parameter determines the level of feature preservation. * * \par IMPORTANT * This class works on SparseImage neighborhoods. Before using this class * please read the documentation for SparseImage. Also the documentation for * ImplicitManifoldNormalVectorField class will be helpful in understanding how * to use this class as a function object. * \ingroup ITKLevelSets */ template class ITK_TEMPLATE_EXPORT NormalVectorDiffusionFunction : public NormalVectorFunctionBase { public: ITK_DISALLOW_COPY_AND_MOVE(NormalVectorDiffusionFunction); /** Standard class type alias. */ using Self = NormalVectorDiffusionFunction; using Superclass = NormalVectorFunctionBase; using Pointer = SmartPointer; using ConstPointer = SmartPointer; /** \see LightObject::GetNameOfClass() */ itkOverrideGetNameOfClassMacro(NormalVectorDiffusionFunction); /** Image dimension derived from the superclass. */ static constexpr unsigned int ImageDimension = Superclass::ImageDimension; /** Standard New macro. */ itkNewMacro(Self); /** Typedefs from the superclass. */ using typename Superclass::TimeStepType; using typename Superclass::RadiusType; using typename Superclass::NeighborhoodType; using typename Superclass::NeighborhoodScalesType; using typename Superclass::FloatOffsetType; using typename Superclass::IndexType; using typename Superclass::SparseImageType; using typename Superclass::NodeType; using typename Superclass::NodeValueType; using typename Superclass::NormalVectorType; /** This method is used to choose between isotropic/anisotropic filtering. A parameter value of 0 indicates isotropic diffusion and is the default. Parameter value 1 is anisotropic diffusion. When using anisotropic diffusion the conductance parameter should also be set. */ void SetNormalProcessType(int npt) { m_NormalProcessType = npt; } /** This method returns the isotropic/anisotropic filtering parameter. */ int GetNormalProcessType() const { return m_NormalProcessType; } /** This method sets the conductance parameter used in anisotropic * filtering. Useful values for processing 2D and 3D shapes are between * 0.1 and 0.25. Lower values preserve more shape features, higher values * smooth more. As the conductance parameter large, the processing becomes * isotropic. Default is 0. */ void SetConductanceParameter(NodeValueType cp) { m_ConductanceParameter = cp + static_cast(0.001); // we add a minimum conductance to avoid divide by zero // can make this a parameter. m_FluxStopConstant = static_cast(-1.0 / (m_ConductanceParameter * m_ConductanceParameter)); } /** This method returns the conductance parameter. */ NodeValueType GetConductanceParameter() const { return m_ConductanceParameter; } /** This method returns the internal variable FluxStopConstant. */ NodeValueType GetFluxStopConstant() const { return m_FluxStopConstant; } /** This function is called from LevelSetNormalImageFilter for all of the * nodes to compute and store the flux vectors (first derivatives of the * normal vectors. ComputeUpdateNormal then takes derivatives of the flux * vectors. This way we avoid repeating the same flux computations. */ void PrecomputeSparseUpdate(NeighborhoodType & it) const override; /** The actual update rule for the normal vectors. */ NormalVectorType ComputeSparseUpdate(NeighborhoodType & it, void * globalData, const FloatOffsetType & offset) const override; protected: NormalVectorDiffusionFunction(); ~NormalVectorDiffusionFunction() override = default; void PrintSelf(std::ostream & os, Indent indent) const override; /** The method called in anisotropic diffusion to inhibit diffusion across areas with large curvature. */ NodeValueType FluxStopFunction(const NodeValueType v) const { // the slow exp function could be replaced with a lookup table if (v <= 0.0) { return NumericTraits::OneValue(); } else { return static_cast(std::exp(m_FluxStopConstant * v)); } } private: /** The conductance parameter used for anisotropic diffusion. */ NodeValueType m_ConductanceParameter{}; /** The internal variable used in the FluxStopFunction. It is computed from * ConductanceParameter. */ NodeValueType m_FluxStopConstant{}; /** The isotropic/anisotropic filtering choice parameter. */ int m_NormalProcessType{}; }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION # include "itkNormalVectorDiffusionFunction.hxx" #endif #endif