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