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 itkWarpHarmonicEnergyCalculator_h
19 #define itkWarpHarmonicEnergyCalculator_h
20 
21 #include "itkObject.h"
22 #include "itkObjectFactory.h"
23 #include "itkConstNeighborhoodIterator.h"
24 #include "itkVector.h"
25 
26 namespace itk
27 {
28 /** \class WarpHarmonicEnergyCalculator
29  *
30  * \brief Compute the harmonic energy of a deformation field.
31  *
32  * This class computes the harmonic energy of a deformation
33  * field which is a measure inversely related to the smoothness
34  * of the deformation field.
35  *
36  * \author Tom Vercauteren, INRIA & Mauna Kea Technologies
37  *
38  * This implementation was taken from the Insight Journal paper:
39  * https://hdl.handle.net/1926/510
40  *
41  * \ingroup Operators
42  * \ingroup ITKReview
43  */
44 template< typename TInputImage >
45 class ITK_TEMPLATE_EXPORT WarpHarmonicEnergyCalculator:public Object
46 {
47 public:
48   ITK_DISALLOW_COPY_AND_ASSIGN(WarpHarmonicEnergyCalculator);
49 
50   /** Standard class type aliases. */
51   using Self = WarpHarmonicEnergyCalculator;
52   using Superclass = Object;
53   using Pointer = SmartPointer< Self >;
54   using ConstPointer = SmartPointer< const Self >;
55 
56   /** Method for creation through the object factory. */
57   itkNewMacro(Self);
58 
59   /** Run-time type information (and related methods). */
60   itkTypeMacro(WarpHarmonicEnergyCalculator, Object);
61 
62   /** Type definition for the input image. */
63   using ImageType = TInputImage;
64 
65   /** Pointer type for the image. */
66   using ImagePointer = typename TInputImage::Pointer;
67 
68   /** Const Pointer type for the image. */
69   using ImageConstPointer = typename TInputImage::ConstPointer;
70 
71   /** Type definition for the input image pixel type. */
72   using PixelType = typename TInputImage::PixelType;
73 
74   /** Type definition for the input image index type. */
75   using IndexType = typename TInputImage::IndexType;
76 
77   /** Type definition for the input image region type. */
78   using RegionType = typename TInputImage::RegionType;
79 
80   /** The dimensionality of the input image. */
81   static constexpr unsigned int ImageDimension = TInputImage::ImageDimension;
82 
83   /** Length of the vector pixel type of the input image. */
84   static constexpr unsigned int VectorDimension = PixelType::Dimension;
85 
86   /** Type of the iterator that will be used to move through the image.  Also
87       the type which will be passed to the evaluate function */
88   using ConstNeighborhoodIteratorType = ConstNeighborhoodIterator< ImageType >;
89   using RadiusType = typename ConstNeighborhoodIteratorType::RadiusType;
90 
91   /** Set/Get whether or not the filter will use the spacing of the input
92    *  image in its calculations.
93    *  When set to "On", the derivative weights according to the spacing of the
94    *  input image (1/spacing). Use this option if you want to calculate the
95    *  Jacobian determinant in the space in which the data was acquired.
96    *  Setting the value to "Off" resets the derivative weights to ignore image
97    *  spacing. Use this option if you want to calculate the Jacobian
98    *  determinant in the image space.
99    *  Default value is "On". */
100   void SetUseImageSpacing(bool);
101   itkGetConstMacro(UseImageSpacing, bool);
102   itkBooleanMacro(UseImageSpacing);
103 
104   using WeightsType = FixedArray< double, ImageDimension >;
105 
106   /** Set/Get the array of weights used to scale partial derivatives in the
107    *  gradient calculations.
108    *  Note that calling UseImageSpacingOn will clobber these values. */
109   itkSetMacro(DerivativeWeights, WeightsType);
110   itkGetConstReferenceMacro(DerivativeWeights, WeightsType);
111 
112   /** Set the input image. */
113   itkSetConstObjectMacro(Image, ImageType);
114 
115   /** Compute the minimum and maximum values of intensity of the input image. */
116   void Compute();
117 
118   /** Return the smoothness value. */
119   itkGetConstMacro(HarmonicEnergy, double);
120 
121   /** Set the region over which the values will be computed */
122   void SetRegion(const RegionType & region);
123 
124 protected:
125   WarpHarmonicEnergyCalculator();
~WarpHarmonicEnergyCalculator()126   ~WarpHarmonicEnergyCalculator() override {}
127   void PrintSelf(std::ostream & os, Indent indent) const override;
128 
129   /** Get/Set the neighborhood radius used for gradient computation */
130   itkGetConstReferenceMacro(NeighborhoodRadius, RadiusType);
131   itkSetMacro(NeighborhoodRadius, RadiusType);
132 
133   double EvaluateAtNeighborhood(ConstNeighborhoodIteratorType & it) const;
134 
135 private:
136   double            m_HarmonicEnergy;
137   ImageConstPointer m_Image;
138 
139   RegionType m_Region;
140   bool       m_RegionSetByUser;
141 
142   bool m_UseImageSpacing;
143 
144   WeightsType m_DerivativeWeights;
145 
146   RadiusType m_NeighborhoodRadius;
147 };
148 } // end namespace itk
149 
150 #ifndef ITK_MANUAL_INSTANTIATION
151 #include "itkWarpHarmonicEnergyCalculator.hxx"
152 #endif
153 
154 #endif /* itkWarpHarmonicEnergyCalculator_h */
155