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 itkDerivativeOperator_h
19 #define itkDerivativeOperator_h
20 
21 #include "itkNeighborhoodOperator.h"
22 
23 namespace itk
24 {
25 /**
26  * \class DerivativeOperator
27  * \brief A NeighborhoodOperator for taking an n-th order derivative
28  * at a pixel
29  *
30  * DerivativeOperator's coefficients are a tightest-fitting convolution
31  * kernel for calculating the n-th order directional derivative at a pixel.
32  * DerivativeOperator is a directional NeighborhoodOperator that should be
33  * applied to a Neighborhood or NeighborhoodPointer using the inner product
34  * method.
35  *
36  * An example operator to compute X derivatives of a 2D image can be
37  * created with:
38    \code
39          using DerivativeOperatorType = itk::DerivativeOperator<float, 2>;
40          DerivativeOperatorType derivativeOperator;
41          derivativeOperator.SetDirection(0); // X dimension
42          itk::Size<2> radius;
43          radius.Fill(1); // A radius of 1 in both dimensions is a 3x3 operator
44          derivativeOperator.CreateToRadius(radius);
45    \endcode
46  * and creates a kernel that looks like:
47    \code
48          0        0 0
49          0.5  0   -0.5
50          0    0   0
51    \endcode
52  *
53  * \sa NeighborhoodOperator
54  * \sa Neighborhood
55  * \sa ForwardDifferenceOperator
56  * \sa BackwardDifferenceOperator
57  *
58  * \ingroup Operators
59  * \ingroup ITKCommon
60  *
61  * \wiki
62  * \wikiexample{Operators/DerivativeOperator,Create a derivative kernel}
63  * \endwiki
64  */
65 template< typename TPixel, unsigned int VDimension = 2,
66           typename TAllocator = NeighborhoodAllocator< TPixel > >
67 class ITK_TEMPLATE_EXPORT DerivativeOperator:
68   public NeighborhoodOperator< TPixel, VDimension, TAllocator >
69 {
70 public:
71   /** Standard class type aliases. */
72   using Self = DerivativeOperator;
73   using Superclass = NeighborhoodOperator<
74     TPixel, VDimension, TAllocator >;
75 
76   using PixelType = typename Superclass::PixelType;
77   using PixelRealType = typename Superclass::PixelRealType;
78 
79   /** Constructor. */
DerivativeOperator()80   DerivativeOperator() {}
81 
82   /** Copy constructor. */
DerivativeOperator(const Self & other)83   DerivativeOperator(const Self & other):
84     NeighborhoodOperator< TPixel, VDimension, TAllocator >(other)
85   { m_Order = other.m_Order;  }
86 
87   /** Assignment operator */
88   Self & operator=(const Self & other)
89   {
90     if(this != &other)
91       {
92       Superclass::operator=(other);
93       m_Order = other.m_Order;
94       }
95     return *this;
96   }
97 
98   /** Sets the order of the derivative. */
SetOrder(const unsigned int & order)99   void SetOrder(const unsigned int & order)
100   {
101     this->m_Order = order;
102   }
103 
104   /** Returns the order of the derivative. */
GetOrder()105   unsigned int GetOrder() const { return m_Order; }
106 
107   /** Prints some debugging information */
PrintSelf(std::ostream & os,Indent i)108   void PrintSelf(std::ostream & os, Indent i) const override
109   {
110     os << i << "DerivativeOperator { this=" << this
111        << ", m_Order = " << m_Order << "}" << std::endl;
112     Superclass::PrintSelf( os, i.GetNextIndent() );
113   }
114 
115 protected:
116   /** Typedef support for coefficient vector type.  Necessary to
117    * work around compiler bug on VC++. */
118   using CoefficientVector = typename Superclass::CoefficientVector;
119 
120   /** Calculates operator coefficients. */
121   CoefficientVector GenerateCoefficients() override;
122 
123   /** Arranges coefficients spatially in the memory buffer. */
Fill(const CoefficientVector & coeff)124   void Fill(const CoefficientVector & coeff) override
125   {   Superclass::FillCenteredDirectional(coeff);  }
126 
127 private:
128   /** Order of the derivative. */
129   unsigned int m_Order{1};
130 };
131 } // namespace itk
132 
133 #ifndef ITK_MANUAL_INSTANTIATION
134 #include "itkDerivativeOperator.hxx"
135 #endif
136 
137 #endif
138