1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkSparseFieldFourthOrderLevelSetImageFilter_h
19 #define itkSparseFieldFourthOrderLevelSetImageFilter_h
20 
21 #include "itkNormalVectorDiffusionFunction.h"
22 #include "itkImplicitManifoldNormalVectorFilter.h"
23 #include "itkLevelSetFunctionWithRefitTerm.h"
24 #include "itkSparseFieldLevelSetImageFilter.h"
25 #include <cmath>
26 
27 namespace itk
28 {
29 /**
30  * \class NormalBandNode
31  *
32  * \brief This is a data storage class that can is used as the node type for
33  * the SparseImage class.
34  *
35  * \ingroup ITKLevelSets
36  */
37 template< typename TImageType >
38 class ITK_TEMPLATE_EXPORT NormalBandNode
39 {
40 public:
41   /** The scalar image type. */
42   using LevelSetImageType = TImageType;
43 
44   /** The pixel type of the scalar image. Expected to be float or double. */
45   using NodeValueType = typename LevelSetImageType::PixelType;
46 
47   /** The index type for the scalar image. */
48   using IndexType = typename LevelSetImageType::IndexType;
49 
50   /** The definition for the normal vector type of the scalar image. */
51   using NodeDataType = Vector< NodeValueType,
52                    TImageType ::ImageDimension >;
53 
54   /** Container for output data (normal vectors). */
55   NodeDataType m_Data;
56 
57   /** Container for a copy of normal vectors before processing. */
58   NodeDataType m_InputData;
59 
60   /** Container for storing update vectors. */
61   NodeDataType m_Update;
62 
63   /** Container for the manifold normal vector. These are computed once at
64       initialization and later used for computing intrinsic derivatives. */
65   NodeDataType
66     m_ManifoldNormal[TImageType::ImageDimension];
67 
68   /** Intermediate flux computations used in computing the update. */
69   NodeDataType m_Flux[TImageType::ImageDimension];
70 
71   /** Curvature computed from the output normal vectors. Used by
72       LevelSetFunctionWithRefitTerm for its propagation term. */
73   NodeValueType m_Curvature;
74 
75   /** This flag is true if the curvature value at this node is valid, false
76       otherwise. */
77   bool m_CurvatureFlag;
78 
79   /** The position of this node in the sparse image. */
80   IndexType m_Index;
81 
82   /** Pointers to previous and next nodes in the list. */
83   NormalBandNode *Next;
84   NormalBandNode *Previous;
85 };
86 
87 /**
88  * \class SparseFieldFourthOrderLevelSetImageFilter
89  *
90  * \brief This class implements the fourth order level set PDE framework.
91  *
92  * \par
93  * This class adds a ProcessNormals method to SparseFieldLevelSetImageFilter
94  * class. The ProcessNormals method uses the
95  * ImplicitManifoldNormalDiffusionFilter class to generate a SparseImage of
96  * filtered normal vectors. We make a copy of the current state of the output
97  * image (also referred to as level set image) for this class and pass it to
98  * ImplicitManifoldNormalDiffusionFilter. That class computes the normal
99  * vectors to the level set image and filters them. The output is in the form
100  * of a sparse image templated with the NormalBandNode type. We then compute
101  * curvatures from that output and store them in the SparseImage as well. This
102  * SparseImage is passed onto the LevelSetFunctionWithRefitTerm filter class to
103  * be used as a target in the propagation term.
104  *
105  * \par INPUT and OUTPUT
106  * Same as SparseFieldLevelSetImageFilter
107  *
108  * \par PARAMETERS
109  * MaxRefitIteration sets the maximum number of allowable iterations between
110  * calls to ProcessNormals. The decision of when to call the ProcessNormals
111  * method is made in InitializeIteration according to a few criteria one of
112  * which is this maximum number of iterations.
113  *
114  * \par
115  * MaxNormalIteration sets the maximum number of diffusion iterations on the
116  * normals to be performed by the ImplicitManifoldNormalDiffusionFilter
117  * class. Please read the documentation for that class.
118  *
119  * \par
120  * CurvatureBandWidth determines the width of the band to be processed in
121  * ImplicitManifoldNormalDiffusionFilter.
122  *
123  * \par
124  * RMSChangeNormalProcessTrigger provides another mechanism in
125  * InitializeIteration for calling the ProcessNormals method. Whenever the RMS
126  * change reported by SparseFieldLevelSetImageFilter falls below this parameter
127  * ProcessNormals is called regardless of whether MaxRefitIteration has been
128  * reached. This parameter could be used to speed up the algorithm; however, it
129  * can also effect the results. Use with caution. Default is 0 which does
130  * nothing.
131  *
132  * \par IMPORTANT
133  * Defaults for above parameters are set in the
134  * constructor. Users should not change these unless they have a good
135  * understanding of the algorithm.
136  *
137  * \par OTHER PARAMETERS
138  * NormalProcessType tells ImplicitManifoldNormalVectorFilter whether to use
139  * isotropic or anisotropic diffusion. A value of 0 means isotropic whereas a
140  * value of 1 means anisotropic diffusion. If this parameter is set to 1,
141  * NormalProcessConductance determines the level of detail preservation. Please
142  * read the documentation for ImplicitManifoldNormalVectorFilter and
143  * AnisotropicFourthOrderLevelSetImageFilter.
144  *
145  * \par
146  * NormalProcessUnsharpFlag turns unsharp masking on/off. If this parameter is
147  * turned on, then NormalProcessUnsharpWeight should be set. Please read the
148  * documentation for ImplicitManifoldNormalVectorFilter.
149  *
150  * \par IMPORTANT
151  * Users of this class must define the Halt function.
152  * \ingroup ITKLevelSets
153  */
154 template< typename TInputImage, typename TOutputImage >
155 class ITK_TEMPLATE_EXPORT SparseFieldFourthOrderLevelSetImageFilter:
156   public SparseFieldLevelSetImageFilter< TInputImage, TOutputImage >
157 {
158 public:
159   ITK_DISALLOW_COPY_AND_ASSIGN(SparseFieldFourthOrderLevelSetImageFilter);
160 
161   /** Standard class type aliases */
162   using Self = SparseFieldFourthOrderLevelSetImageFilter;
163   using Superclass = SparseFieldLevelSetImageFilter< TInputImage, TOutputImage >;
164   using Pointer = SmartPointer< Self >;
165   using ConstPointer = SmartPointer< const Self >;
166 
167   /** Run-time type information (and related methods) */
168   itkTypeMacro(SparseFieldFourthOrderLevelSetImageFilter,
169                SparseFieldLevelSetImageFilter);
170 
171   /** Standard image dimension macro. */
172   static constexpr unsigned int ImageDimension = Superclass::ImageDimension;
173 
174   /** Typedefs derived from the superclass. */
175   using OutputImageType = typename Superclass::OutputImageType;
176   using ValueType = typename Superclass::ValueType;
177   using IndexType = typename Superclass::IndexType;
178   using LayerType = typename Superclass::LayerType;
179   using RadiusType = typename Superclass::RadiusType;
180   using NeighborhoodScalesType = typename Superclass::NeighborhoodScalesType;
181 
182   /** The storage class used as the node type for the sparse normal vector
183       image. */
184   using NodeType = NormalBandNode< OutputImageType >;
185 
186   /** The sparse image type used for processing the normal vectors. */
187   using SparseImageType = SparseImage< NodeType,
188                        Self::ImageDimension >;
189 
190   /** The normal vector type. */
191   using NormalVectorType = typename NodeType::NodeDataType;
192 
193   /** The iterator type for the sparse image. */
194   using SparseImageIteratorType = NeighborhoodIterator< SparseImageType >;
195 
196   /** The filter type for processing the normal vectors of the level set. */
197   using NormalVectorFilterType =
198       ImplicitManifoldNormalVectorFilter< OutputImageType, SparseImageType >;
199 
200   /** The function type for processing the normal vector neighborhood. */
201   using NormalVectorFunctionType = NormalVectorDiffusionFunction<SparseImageType>;
202 
203   /** The radius type derived from the normal vector function. */
204   //using RadiusType = typename NormalVectorFunctionType::RadiusType;
205 
206   /** The level set function with refitting term type. */
207   using LevelSetFunctionType = LevelSetFunctionWithRefitTerm< OutputImageType,
208                                          SparseImageType >;
209 
210   itkGetConstReferenceMacro(MaxRefitIteration, unsigned int);
211   itkSetMacro(MaxRefitIteration, unsigned int);
212   itkGetConstReferenceMacro(MaxNormalIteration, unsigned int);
213   itkSetMacro(MaxNormalIteration, unsigned int);
214   itkGetConstReferenceMacro(CurvatureBandWidth, ValueType);
215   itkSetMacro(CurvatureBandWidth, ValueType);
216   itkGetConstReferenceMacro(RMSChangeNormalProcessTrigger, ValueType);
217   itkSetMacro(RMSChangeNormalProcessTrigger, ValueType);
218   itkGetConstReferenceMacro(NormalProcessType, int);
219   itkSetMacro(NormalProcessType, int);
220   itkGetConstReferenceMacro(NormalProcessConductance, ValueType);
221   itkSetMacro(NormalProcessConductance, ValueType);
222   itkSetMacro(NormalProcessUnsharpFlag, bool);
223   itkGetConstReferenceMacro(NormalProcessUnsharpFlag, bool);
224   itkSetMacro(NormalProcessUnsharpWeight, ValueType);
225   itkGetConstReferenceMacro(NormalProcessUnsharpWeight, ValueType);
226 
227   /** Set the level set function. Must LevelSetFunctionWithRefitTerm or a
228       subclass. */
229   void SetLevelSetFunction(LevelSetFunctionType *lsf);
230 
231   /** Compute the number of layers that must be used in
232       SparseFieldLevelSetImageFilter to accommodate the desired normal
233       processing band. */
GetMinimumNumberOfLayers()234   unsigned int GetMinimumNumberOfLayers() const
235   {
236     return (int)std::ceil( m_CurvatureBandWidth
237                           + Self::ImageDimension );
238   }
239 
240   /** This overrides SparseFieldLevelSetImageFilter's SetNumberOfLayers to make
241       sure we have enough layers to do what we need. */
SetNumberOfLayers(const unsigned int n)242   void SetNumberOfLayers(const unsigned int n) override
243   {
244     unsigned int nm = std::max (this->GetMinimumNumberOfLayers (), n);
245 
246     if ( nm != this->GetNumberOfLayers() )
247       {
248       Superclass::SetNumberOfLayers (nm);
249       this->Modified();
250       }
251   }
252 
253   /** This method first calls the Superclass InitializeIteration method. Then
254       it determines whether ProcessNormals should be called. */
InitializeIteration()255   void InitializeIteration() override
256   {
257     Superclass::InitializeIteration();
258     ValueType rmschange = this->GetRMSChange();
259 
260     if ( ( this->GetElapsedIterations() == 0 )
261          || ( m_RefitIteration == m_MaxRefitIteration )
262          || ( rmschange <= m_RMSChangeNormalProcessTrigger )
263          || ( this->ActiveLayerCheckBand() ) )
264       {
265       if ( ( this->GetElapsedIterations() != 0 )
266            && ( rmschange <= m_RMSChangeNormalProcessTrigger )
267            && ( m_RefitIteration <= 1 ) )
268         {
269         m_ConvergenceFlag = true;
270         }
271 
272       m_RefitIteration = 0;
273       ProcessNormals();
274       }
275 
276     m_RefitIteration++;
277   }
278 
279 #ifdef ITK_USE_CONCEPT_CHECKING
280   // Begin concept checking
281   itkConceptMacro( OutputHasNumericTraitsCheck,
282                    ( Concept::HasNumericTraits< ValueType > ) );
283   // End concept checking
284 #endif
285 
286 protected:
287   SparseFieldFourthOrderLevelSetImageFilter();
288   ~SparseFieldFourthOrderLevelSetImageFilter() override = default;
289   void PrintSelf(std::ostream & os, Indent indent) const override;
290 
291   /** This method computes curvature from normal vectors stored in a sparse
292       image neighborhood. */
293   ValueType ComputeCurvatureFromSparseImageNeighborhood
294     (SparseImageIteratorType & neighborhood) const;
295 
296   /** This method computes curvature from the processed normal vectors over
297    *  the region specified by the CurvatureBandWidth parameter. The
298    *  curvatures are stored in the sparse image. */
299   void ComputeCurvatureTarget(const OutputImageType *distanceImage,
300                               SparseImageType *sparseImage) const;
301 
302   /** The method for processing the normal vectors. */
303   void ProcessNormals();
304 
305   /** This method checks whether the level set front is touching the edges of
306    * the band where curvature from the processed normal vectors has been
307    * computed. This is one of the conditions for triggering the ProcessNormals
308    * method. */
309   bool ActiveLayerCheckBand() const;
310 
311 private:
312   /** This is a iteration counter that gets reset to 0 every time
313       ProcessNormals method is called. */
314   unsigned int m_RefitIteration;
315 
316   /** This parameter determines the maximum number of
317       SparseFieldLevelSetImageFilter iterations that will be executed between
318       calls to ProcessNormals. */
319   unsigned int m_MaxRefitIteration;
320 
321   /** This parameter is used to set the corresponding parameter in
322       ImplicitManifoldNormalDiffusionfFilter. */
323   unsigned int m_MaxNormalIteration;
324 
325   /** This is used to trigger a call to the ProcessNormals method
326       before m_RefitIteration reaches m_MaxRefitIteration if the RMSChange falls
327       below this parameter. */
328   ValueType m_RMSChangeNormalProcessTrigger;
329 
330   /** This flag is set to true to signal final convergence. It can be used by
331       subclasses that define a Halt method. */
332   bool m_ConvergenceFlag;
333 
334   /** The level set function with the term for refitting the level set to the
335       processed normal vectors. */
336   LevelSetFunctionType *m_LevelSetFunction;
337 
338   /** This parameter determines the width of the band where we compute
339    * curvature from the processed normals. The wider the band, the more level set
340    * iterations that can be performed between calls to ProcessNormals. It is
341    * qsuggested that this value is left at its default. */
342   ValueType m_CurvatureBandWidth;
343 
344   /** The parameter that chooses between isotropic/anisotropic filtering of the
345       normal vectors. */
346   int m_NormalProcessType;
347 
348   /** The conductance parameter used if anisotropic filtering of the normal
349       vectors is chosen. */
350   ValueType m_NormalProcessConductance;
351 
352   /** The parameter that turns on/off the unsharp mask enhancement of the
353       normals. */
354   bool m_NormalProcessUnsharpFlag;
355 
356   /** The weight that controls the extent of enhancement if the
357       NormalProcessUnsharpFlag is ON. */
358   ValueType m_NormalProcessUnsharpWeight;
359 
360   /** Constants used in the computations. */
361   static const SizeValueType  m_NumVertex;
362   static const ValueType      m_DimConst;
363 
364 };
365 } // end namespace itk
366 
367 #ifndef ITK_MANUAL_INSTANTIATION
368 #include "itkSparseFieldFourthOrderLevelSetImageFilter.hxx"
369 #endif
370 
371 #endif
372