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 itkNeighborhoodIterator_h
19 #define itkNeighborhoodIterator_h
20 
21 #include <vector>
22 #include <cstring>
23 #include <iostream>
24 #include "itkConstNeighborhoodIterator.h"
25 
26 namespace itk
27 {
28 /**
29  * \class NeighborhoodIterator
30  *
31  * \brief Defines iteration of a local N-dimensional neighborhood of pixels
32  * across an itk::Image.
33  *
34  * This class is a loose extension of the Standard Template Library (STL)
35  * bi-directional iterator concept to \em masks of pixel neighborhoods within
36  * itk::Image objects.  This NeighborhoodIterator base class defines simple
37  * forward and reverse iteration of an N-dimensional neighborhood mask
38  * across an image.  Elements within the mask can be accessed like elements
39  * within an array.
40  *
41  * NeighborhoodIterators are designed to encapsulate some of the complexity of
42  * working with image neighborhoods, complexity that would otherwise have to be
43  * managed at the algorithmic level.  Use NeighborhoodIterators to simplify
44  * writing algorithms that perform geometrically localized operations on images
45  * (for example, convolution and morphological operations).
46  *
47  * To motivate the discussion of NeighborhoodIterators and their use in
48  * Itk, consider the following code that takes directional derivatives at each
49  * point in an image.
50  *
51 \code
52 itk::NeighborhoodInnerProduct<ImageType> innerProduct;
53 
54 itk::DerivativeOperator<ImageType> operator;
55  operator->SetOrder(1);
56  operator->SetDirection(0);
57  operator->CreateDirectional();
58 
59 itk::NeighborhoodIterator<ImageType>
60   iterator(operator->GetRadius(), myImage, myImage->GetRequestedRegion());
61 
62 iterator.SetToBegin();
63 while ( ! iterator.IsAtEnd() )
64 {
65   std::cout << "Derivative at index " << iterator.GetIndex() << is <<
66     innerProduct(iterator, operator) << std::endl;
67   ++iterator;
68 }
69 \endcode
70  *
71  * Most of the work for the programmer in the code above is in setting up for
72  * the iteration.  There are three steps.  First an inner product function
73  * object is created which will be used to effect convolution with the
74  * derivative kernel.  Setting up the derivative kernel, DerivativeOperator,
75  * involves setting the order and direction of the derivative.  Finally, we
76  * create an iterator over the RequestedRegion of the itk::Image (see Image)
77  * using the radius of the derivative kernel as the size.
78  *
79  * Itk iterators only loosely follow STL conventions.  Notice that instead of
80  * asking myImage for myImage.begin() and myImage.end(), iterator.SetToBegin()
81  * and iterator.IsAtEnd() are called.  Itk iterators are typically more complex
82  * objects than traditional, pointer-style STL iterators, and the increased
83  * overhead required to conform to the complete STL API is not always
84  * justified.
85  *
86  * The API for creating and manipulating a NeighborhoodIterator mimics
87  * that of the itk::ImageIterators.  Like the itk::ImageIterator, a
88  * ConstNeighborhoodIterator is defined on a region of interest in an itk::Image.
89  * Iteration is constrained within that region of interest.
90  *
91  * A NeighborhoodIterator is constructed as a container of pointers (offsets)
92  * to a geometric neighborhood of image pixels.  As the central pixel position
93  * in the mask is moved around the image, the neighboring pixel pointers
94  * (offsets) are moved accordingly.
95  *
96  * A \em pixel \em neighborhood is defined as a central pixel location and an
97  * N-dimensional radius extending outward from that location.
98  *
99  * Pixels in a neighborhood can be accessed through a NeighborhoodIterator
100  * like elements in an array.  For example, a 2D neighborhood with radius 2x1
101  * has indices:
102  *
103 \code
104 0  1  2  3  4
105 5  6  7  8  9
106 10 11 12 13 14
107 \endcode
108  *
109  * Now suppose a NeighborhoodIterator with the above dimensions is constructed
110  * and positioned over a neighborhood of values in an Image:
111  *
112 \code
113 1.2 1.3 1.8 1.4 1.1
114 1.8 1.1 0.7 1.0 1.0
115 2.1 1.9 1.7 1.4 2.0
116 \endcode
117  *
118  * Shown below is some sample pixel access code and the values that it returns.
119  *
120 \code
121 SizeValueType c = (SizeValueType) (iterator.Size() / 2); // get offset of center pixel
122 SizeValueType s = iterator.GetStride(1);            // y-dimension step size
123 
124 std::cout << iterator.GetPixel(7)      << std::endl;
125 std::cout << iterator.GetCenterPixel() << std::endl;
126 std::cout << iterator.GetPixel(c)      << std::endl;
127 std::cout << iterator.GetPixel(c-1)    << std::endl;
128 std::cout << iterator.GetPixel(c-s)    << std::endl;
129 std::cout << iterator.GetPixel(c-s-1)  << std::endl;
130 std::cout << *iterator[c]              << std::endl;
131 \endcode
132  *
133  * Results:
134  *
135 \code
136 0.7
137 0.7
138 0.7
139 1.1
140 1.8
141 1.3
142 0.7
143 \endcode
144  *
145  * Use of GetPixel() is preferred over the *iterator[] form, and can be used
146  * without loss of efficiency in most cases. Some variations (subclasses) of
147  * NeighborhoodIterators may exist which do not support the latter
148  * API. Corresponding SetPixel() methods exist to modify pixel values in
149  * non-const NeighborhoodIterators.
150  *
151  * NeighborhoodIterators are "bidirectional iterators". They move only in two
152  * directions through the data set.  These directions correspond to the layout
153  * of the image data in memory and not to spatial directions of the
154  * N-dimensional itk::Image.  Iteration always proceeds along the fastest
155  * increasing dimension (as defined by the layout of the image data).  For
156  * itk::Image this is the first dimension specified (i.e. for 3-dimensional
157  * (x,y,z) NeighborhoodIterator proceeds along the x-dimension) (For random
158  * access iteration through N-dimensional indices, use
159  * RandomAccessNeighborhoodIterator).
160  *
161  * Each subclass of a ConstNeighborhoodIterator may also define its own
162  * mechanism for iteration through an image.  In general, the Iterator does not
163  * directly keep track of its spatial location in the image, but uses a set of
164  * internal loop variables and offsets to trigger wraps at itk::Image region
165  * boundaries, and to identify the end of the itk::Image region.
166  *
167  * \todo Better support for regions with negative indices.
168  * \todo Add Begin() and End() methods?
169  *
170  * \sa DerivativeOperator \sa NeighborhoodInnerProduct
171  *
172  * \par MORE INFORMATION
173  * For a complete description of the ITK Image Iterators and their API, please
174  * see the Iterators chapter in the ITK Software Guide.  The ITK Software Guide
175  * is available in print and as a free .pdf download from https://www.itk.org.
176  *
177  * \ingroup ImageIterators
178  *
179  * \sa ImageConstIterator \sa ConditionalConstIterator
180  * \sa ConstNeighborhoodIterator \sa ConstShapedNeighborhoodIterator
181  * \sa ConstSliceIterator  \sa CorrespondenceDataStructureIterator
182  * \sa FloodFilledFunctionConditionalConstIterator
183  * \sa FloodFilledImageFunctionConditionalConstIterator
184  * \sa FloodFilledImageFunctionConditionalIterator
185  * \sa FloodFilledSpatialFunctionConditionalConstIterator
186  * \sa FloodFilledSpatialFunctionConditionalIterator
187  * \sa ImageConstIterator \sa ImageConstIteratorWithIndex
188  * \sa ImageIterator \sa ImageIteratorWithIndex
189  * \sa ImageLinearConstIteratorWithIndex  \sa ImageLinearIteratorWithIndex
190  * \sa ImageRandomConstIteratorWithIndex  \sa ImageRandomIteratorWithIndex
191  * \sa ImageRegionConstIterator \sa ImageRegionConstIteratorWithIndex
192  * \sa ImageRegionExclusionConstIteratorWithIndex
193  * \sa ImageRegionExclusionIteratorWithIndex
194  * \sa ImageRegionIterator  \sa ImageRegionIteratorWithIndex
195  * \sa ImageRegionReverseConstIterator  \sa ImageRegionReverseIterator
196  * \sa ImageReverseConstIterator  \sa ImageReverseIterator
197  * \sa ImageSliceConstIteratorWithIndex  \sa ImageSliceIteratorWithIndex
198  * \sa NeighborhoodIterator \sa PathConstIterator  \sa PathIterator
199  * \sa ShapedNeighborhoodIterator  \sa SliceIterator
200  * \sa ImageConstIteratorWithIndex
201  *
202  * \ingroup Operators
203  * \ingroup ITKCommon
204  *
205  * \wiki
206  * \wikiexample{Iterators/NeighborhoodIterator,Iterate over a region of an image with a neighborhood (with write access)}
207  * \wikiexample{VectorImages/NeighborhoodIterator,NeighborhoodIterator on a VectorImage}
208  * \endwiki
209  */
210 template< typename TImage, typename TBoundaryCondition =
211             ZeroFluxNeumannBoundaryCondition< TImage > >
212 class ITK_TEMPLATE_EXPORT NeighborhoodIterator:
213   public ConstNeighborhoodIterator< TImage, TBoundaryCondition >
214 {
215 public:
216   /** Standard class type aliases. */
217   using Self = NeighborhoodIterator;
218   using Superclass = ConstNeighborhoodIterator< TImage, TBoundaryCondition >;
219 
220   /** Extract type alias from superclass. */
221   using InternalPixelType = typename Superclass::InternalPixelType;
222   using PixelType = typename Superclass::PixelType;
223   using SizeType = typename Superclass::SizeType;
224   using ImageType = typename Superclass::ImageType;
225   using RegionType = typename Superclass::RegionType;
226   using IndexType = typename Superclass::IndexType;
227   using OffsetType = typename Superclass::OffsetType;
228   using RadiusType = typename Superclass::RadiusType;
229   using NeighborhoodType = typename Superclass::NeighborhoodType;
230   using Iterator = typename Superclass::Iterator;
231   using ConstIterator = typename Superclass::ConstIterator;
232   using ImageBoundaryConditionPointerType = typename Superclass::ImageBoundaryConditionPointerType;
233 
234   /** Default constructor. */
NeighborhoodIterator()235   NeighborhoodIterator():Superclass() {}
236 
237   /** Copy constructor */
NeighborhoodIterator(const NeighborhoodIterator & n)238   NeighborhoodIterator(const NeighborhoodIterator & n):Superclass(n) {}
239 
240   /** Assignment operator */
241   Self & operator=(const Self & orig)
242   {
243     Superclass::operator=(orig);
244     return *this;
245   }
246 
247   /** Constructor which establishes the region size, neighborhood, and image
248    * over which to walk. */
NeighborhoodIterator(const SizeType & radius,ImageType * ptr,const RegionType & region)249   NeighborhoodIterator(const SizeType & radius, ImageType *ptr,
250                        const RegionType & region):
251     Superclass(radius, ptr, region) {}
252 
253   /** Standard print method */
254   void PrintSelf(std::ostream &, Indent) const;
255 
256   /** Returns the central memory pointer of the neighborhood. */
GetCenterPointer()257   InternalPixelType * GetCenterPointer()
258   { return ( this->operator[]( ( this->Size() ) >> 1 ) ); }
259 
260   /** Returns the central pixel of the neighborhood. */
SetCenterPixel(const PixelType & p)261   ITK_ITERATOR_VIRTUAL void SetCenterPixel(const PixelType & p) ITK_ITERATOR_FINAL
262   { this->m_NeighborhoodAccessorFunctor.Set(this->operator[]( ( this->Size() ) >> 1 ), p); }
263 
264   /** Virtual function that replaces the pixel values in the image
265    * neighborhood that are pointed to by this NeighborhoodIterator with
266    * the pixel values contained in a Neighborhood. */
267   ITK_ITERATOR_VIRTUAL void SetNeighborhood(const NeighborhoodType &) ITK_ITERATOR_FINAL;
268 
269   /** Special SetPixel method which quietly ignores out-of-bounds attempts.
270    *  Sets status TRUE if pixel has been set, FALSE otherwise.  */
271   ITK_ITERATOR_VIRTUAL void SetPixel(const unsigned i, const PixelType & v,
272                         bool  & status) ITK_ITERATOR_FINAL;
273 
274   /** Set the pixel at the ith location. */
275   ITK_ITERATOR_VIRTUAL void SetPixel(const unsigned i, const PixelType & v) ITK_ITERATOR_FINAL;
276 
277   //  { *(this->operator[](i)) = v; }
278 
279   /** Set the pixel at offset o from the neighborhood center */
SetPixel(const OffsetType o,const PixelType & v)280   ITK_ITERATOR_VIRTUAL void SetPixel(const OffsetType o, const PixelType & v) ITK_ITERATOR_FINAL
281   { this->SetPixel(this->GetNeighborhoodIndex(o), v); }
282   //  { *(this->operator[](o)) = v; }
283 
284   /** Sets the pixel value located i pixels distant from the neighborhood center in
285       the positive specified "axis" direction. No bounds checking is done on
286       the size of the neighborhood. */
SetNext(const unsigned axis,const unsigned i,const PixelType & v)287   ITK_ITERATOR_VIRTUAL void SetNext(const unsigned axis, const unsigned i,
288                        const PixelType & v) ITK_ITERATOR_FINAL
289   {
290     this->SetPixel(this->GetCenterNeighborhoodIndex()
291                    + ( i * this->GetStride(axis) ), v);
292   }
293 
294   /** Sets the pixel value located one pixel distant from the neighborhood center in
295       the specifed positive axis direction. No bounds checking is done on the
296       size of the neighborhood. */
SetNext(const unsigned axis,const PixelType & v)297   ITK_ITERATOR_VIRTUAL void SetNext(const unsigned axis, const PixelType & v) ITK_ITERATOR_FINAL
298   {
299     this->SetPixel(this->GetCenterNeighborhoodIndex()
300                    + this->GetStride(axis), v);
301   }
302 
303   /** Sets the pixel value located i pixels distant from the neighborhood center in
304       the negative specified "axis" direction. No bounds checking is done on
305       the size of the neighborhood. */
SetPrevious(const unsigned axis,const unsigned i,const PixelType & v)306   ITK_ITERATOR_VIRTUAL void SetPrevious(const unsigned axis, const unsigned i,
307                            const PixelType & v) ITK_ITERATOR_FINAL
308   {
309     this->SetPixel(this->GetCenterNeighborhoodIndex()
310                    - ( i * this->GetStride(axis) ), v);
311   }
312 
313   /** Sets the pixel value located one pixel distant from the neighborhood center in
314       the specifed negative axis direction. No bounds checking is done on the
315       size of the neighborhood. */
SetPrevious(const unsigned axis,const PixelType & v)316   ITK_ITERATOR_VIRTUAL void SetPrevious(const unsigned axis,
317                            const PixelType & v) ITK_ITERATOR_FINAL
318   {
319     this->SetPixel(this->GetCenterNeighborhoodIndex()
320                    - this->GetStride(axis), v);
321   }
322 };
323 } // namespace itk
324 
325 #ifndef ITK_MANUAL_INSTANTIATION
326 #include "itkNeighborhoodIterator.hxx"
327 #endif
328 
329 #endif
330