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 itkNeighborhoodOperator_h
19 #define itkNeighborhoodOperator_h
20 
21 #include "itkNeighborhood.h"
22 #include "itkNumericTraits.h"
23 #include <vector>
24 
25 namespace itk
26 {
27 /** \class NeighborhoodOperator
28  * \brief Virtual class that defines a common interface to all
29  *        neighborhood operator subtypes.
30  *
31  * A NeighborhoodOperator is a set of pixel values that can be applied to a
32  * Neighborhood to perform a user-defined operation (i.e. convolution kernel,
33  * morphological structuring element).  A NeighborhoodOperator is itself a
34  * specialized Neighborhood, with functionality to generate its coefficients
35  * according to user-defined parameters.  Because the operator is a subclass
36  * of Neighborhood, it is a valid operand in any of the operations
37  * defined on the Neighborhood object (convolution, inner product, etc.).
38  *
39  * NeighborhoodOperator is a pure virtual object that must be
40  * subclassed to be used.  A user's subclass must implement two methods:
41  *
42  * (1) GenerateCoefficients -- the algorithm that computes the scalar
43  *   coefficients of the operator.
44  *
45  * (2) Fill -- the algorithm that places the scalar coefficients into
46  *   the memory buffer of the operator (arranges them spatially in the
47  *   neighborhood).
48  *
49  * NeighborhoodOperator supports the concept of a "directional operator."
50  * A directional operator is defined in this context to be an operator
51  * that is applied along a single dimension.  Examples of this type of
52  * operator are directional derivatives and the individual, directional
53  * components of separable processes such as Gaussian smoothing.
54  *
55  * How a NeighborhoodOperator is applied to data is up to the user who
56  * defines it.  One possible use of an operator would be to take its
57  * inner product with a neighborhood of values to produce
58  * a scalar result.  This process effects convolution when applied to
59  * successive neighborhoods across a region of interest in an image.
60  *
61  * \ingroup Operators
62  * \ingroup ITKCommon
63  */
64 template< typename TPixel, unsigned int VDimension,
65           typename TAllocator = NeighborhoodAllocator< TPixel > >
66 class ITK_TEMPLATE_EXPORT NeighborhoodOperator:
67   public Neighborhood< TPixel, VDimension, TAllocator >
68 {
69 public:
70   /**  Standard class type aliases. */
71   using Self = NeighborhoodOperator;
72   using Superclass = Neighborhood< TPixel, VDimension, TAllocator >;
73 
74   itkTypeMacro(NeighborhoodOperator, NeighborhoodOperator);
75 
76   /** Size object type alias support */
77   using SizeType = typename Superclass::SizeType;
78 
79   /** External support for pixel type */
80   using PixelType = TPixel;
81 
82   /** Slice iterator type alias support */
83   using SliceIteratorType = SliceIterator< TPixel, Self >;
84 
85   /** Constructor. */
NeighborhoodOperator()86   NeighborhoodOperator()
87   {  m_Direction = 0;  }
88 
89   /** Copy constructor */
NeighborhoodOperator(const Self & orig)90   NeighborhoodOperator(const Self & orig):
91     Neighborhood< TPixel, VDimension, TAllocator >(orig)
92   {   m_Direction = orig.m_Direction;   }
93 
94   /** Assignment operator. */
95   Self & operator=(const Self & orig)
96   {
97     Superclass::operator=(orig);
98     m_Direction = orig.m_Direction;
99     return *this;
100   }
101 
102   /** Sets the dimensional direction of a directional operator. */
SetDirection(const unsigned long & direction)103   void SetDirection(const unsigned long & direction)
104   {  m_Direction = direction;   }
105 
106   /** Returns the direction (dimension number) of a directional operator. */
GetDirection()107   unsigned long GetDirection() const
108   {  return m_Direction;  }
109 
110   /** Creates the operator with length only in the specified direction.
111    * The radius of the operator will be 0 except along the axis on which
112    * the operator will work.
113    * \sa CreateToRadius \sa FillCenteredDirectional \sa SetDirection() \sa GetDirection() */
114   virtual void CreateDirectional();
115 
116   /** Creates the operator with a specified radius.  The spatial location of
117    * the coefficients within the operator is defined by the subclass
118    * implementation of the Fill method.
119    * \sa CreateDirectional \sa Fill */
120   virtual void CreateToRadius(const SizeType &);
121 
122   /** Creates the operator with a specified radius ("square", same length
123    * on each side). The spatial location of the coefficients within the
124    * operator is defined by the subclass implementation of the Fill method.
125    * \sa CreateDirectional \sa Fill */
126   virtual void CreateToRadius(const SizeValueType);
127 
128   /** Reverses the direction of all axes of the operator by reversing the order
129     * of the coefficients. */
130   virtual void FlipAxes();
131 
132   /** Prints some debugging information. */
PrintSelf(std::ostream & os,Indent i)133   void PrintSelf(std::ostream & os, Indent i) const override
134   {
135     os << i << "NeighborhoodOperator { this=" << this
136        << " Direction = " << m_Direction << " }" << std::endl;
137     Superclass::PrintSelf( os, i.GetNextIndent() );
138   }
139 
140   using PixelRealType = typename NumericTraits< TPixel >::RealType;
141 
142   /** Multiplies all of the coefficients of the kernel by a single scalar value.
143     */
144   void ScaleCoefficients(PixelRealType);
145 
146 protected:
147   /** Typedef support  for coefficient vector type.  Necessary
148    * to fix bug in the microsoft VC++ compiler. */
149   using CoefficientVector = std::vector< PixelRealType >;
150 
151   /** A subclass-specific algorithm that computes the coefficients
152    * of the operator. */
153   virtual CoefficientVector GenerateCoefficients() = 0;
154 
155   /** A subclass-specific algorithm that positions the coefficients
156    * spatially in the operator. */
157   virtual void Fill(const CoefficientVector &) = 0;
158 
159   /** A pre-defined Fill function that can be called by a subclass
160    * Fill function to center coefficients along the axis specified
161    * by the SetDirection method.  Useful for creating directional
162    * operators, or centering coefficients in an N-dimensional
163    * neighborhood. */
164   virtual void FillCenteredDirectional(const CoefficientVector &);
165 
166   /** Initializes all the coefficients in the neighborhood to zero values */
InitializeToZero()167   void InitializeToZero()
168   {
169     for ( unsigned int i = 0; i < this->Size(); ++i )
170       {
171       this->operator[](i) = NumericTraits< PixelType >::ZeroValue();
172       }
173   }
174 
175 private:
176   /** Direction (dimension number) of the derivative. */
177   unsigned long m_Direction;
178 };
179 } // namespace itk
180 
181 #ifndef ITK_MANUAL_INSTANTIATION
182 #include "itkNeighborhoodOperator.hxx"
183 #endif
184 
185 /*
186 #ifndef ITK_MANUAL_INSTANTIATION
187 #include "itkNeighborhoodOperator.hxx"
188 #endif
189 */
190 #endif
191