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 itkSobelOperator_h
19 #define itkSobelOperator_h
20 
21 #include "itkNeighborhoodOperator.h"
22 
23 namespace itk
24 {
25 /**
26  * \class SobelOperator
27  *
28  * \brief A NeighborhoodOperator for performing a directional Sobel
29  * edge-detection operation at a pixel location.
30  *
31  * SobelOperator is a directional NeighborhoodOperator that should be
32  * applied a NeighborhoodIterator using the NeighborhoodInnerProduct
33  * method. To create the operator:
34  *
35  * 1) Set the direction by calling  \code SetDirection \endcode
36  * 2) call
37    \code
38    itk::Size<2> radius;
39    radius.Fill(1);
40    sobelOperator.CreateToRadius(radius);
41    \endcode
42  * 3) You may optionally scale the coefficients of this operator using the
43  * \code ScaleCoefficients \endcode method.  This is useful if you
44  * want to take the spacing of the image into account when computing
45  * the edge strength.  Apply the scaling only after calling to
46  * \code CreateToRadius \endcode.
47  *
48  * The Sobel Operator in vertical direction for 2 dimensions is
49  * \verbatim
50  *             -1  -2  -1
51  *             0    0   0
52  *             1    2   1
53  *
54  * \endverbatim
55  * The Sobel Operator in horizonal direction is for 2 dimensions is
56  * \verbatim
57  *             -1   0   1
58  *             -2   0   2
59  *             -1   0   1
60  * \endverbatim
61  *
62  * The current implementation of the Sobel operator is for 2 and 3 dimensions only.
63  * The ND version is planned for future releases.
64  *
65  * The extension to 3D is from the publication
66  *  "Irwin Sobel. An Isotropic 3x3x3 Volume Gradient Operator.
67  * Technical report, Hewlett-Packard Laboratories, April 1995."
68  *
69  * The Sobel operator in 3D has the kernel
70  *
71  * \verbatim
72  * -1 -3 -1   0 0 0  1 3 1
73  * -3 -6 -3   0 0 0  3 6 3
74  * -1 -3 -1   0 0 0  1 3 1
75  *
76  *    x-1       x     x+1
77  * \endverbatim
78  *
79  * The \c x kernel is just rotated as required to obtain the kernel in the
80  * \c y and \c z directions.
81  *
82  * \sa NeighborhoodOperator
83  * \sa Neighborhood
84  * \sa ForwardDifferenceOperator
85  * \sa BackwardDifferenceOperator
86  *
87  * \ingroup Operators
88  * \ingroup ITKCommon
89  *
90  * \wiki
91  * \wikiexample{Operators/SobelOperator,Create the Sobel kernel}
92  * \endwiki
93  */
94 template< typename TPixel, unsigned int VDimension = 2,
95           typename TAllocator = NeighborhoodAllocator< TPixel > >
96 class ITK_TEMPLATE_EXPORT SobelOperator:
97   public NeighborhoodOperator< TPixel, VDimension, TAllocator >
98 {
99 public:
100   /** Standard type alias */
101   using Self = SobelOperator;
102   using Superclass = NeighborhoodOperator< TPixel, VDimension, TAllocator >;
103 
104   itkTypeMacro(SobelOperator, NeighborhoodOperator);
105 
106   SobelOperator() = default;
SobelOperator(const Self & other)107   SobelOperator(const Self & other):
108     NeighborhoodOperator< TPixel, VDimension, TAllocator >(other)
109   {}
110 
111   /** Creates the operator with length only in the specified direction.  For
112    * the Sobel operator, this
113    * The radius of the operator will be 0 except along the axis on which
114    * the operator will work.
115    * \sa CreateToRadius \sa FillCenteredDirectional \sa SetDirection() \sa GetDirection() */
CreateDirectional()116   void CreateDirectional() override
117   {
118     this->CreateToRadius(1);
119   }
120 
121   /** Creates the operator with a specified radius ("square", same length
122    * on each side). The spatial location of the coefficients within the
123    * operator is defined by the subclass implementation of the Fill method.
124    * \sa CreateDirectional \sa Fill */
125   // virtual void CreateToRadius(const unsigned long);
126   /**
127    * Assignment operator
128    */
129   Self & operator=(const Self & other)
130   {
131     Superclass::operator=(other);
132     return *this;
133   }
134 
135   /**
136    * Prints some debugging information
137    */
PrintSelf(std::ostream & os,Indent i)138   void PrintSelf(std::ostream & os, Indent i) const override
139   {
140     os << i << "SobelOperator { this=" << this  << "}" << std::endl;
141     Superclass::PrintSelf( os, i.GetNextIndent() );
142   }
143 
144 protected:
145   /**
146    * Typedef support for coefficient vector type.  Necessary to
147    * work around compiler bug on VC++.
148    */
149   using CoefficientVector = typename Superclass::CoefficientVector;
150   using PixelType = typename Superclass::PixelType;
151 
152   /**
153    * Calculates operator coefficients.
154    */
155   CoefficientVector GenerateCoefficients() override;
156 
157   /**
158    * Arranges coefficients spatially in the memory buffer.
159    */
160   void Fill(const CoefficientVector & c) override;
161 };
162 } // namespace itk
163 
164 #ifndef ITK_MANUAL_INSTANTIATION
165 #include "itkSobelOperator.hxx"
166 #endif
167 
168 #endif
169