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 itkImageRandomNonRepeatingConstIteratorWithIndex_h
19 #define itkImageRandomNonRepeatingConstIteratorWithIndex_h
20 
21 #include "itkImageConstIteratorWithIndex.h"
22 #include <algorithm>
23 #include <iostream>
24 #include "itkMersenneTwisterRandomVariateGenerator.h"
25 
26 namespace itk
27 {
28 /** \class NodeOfPermutation
29  *  \brief A node to be used when computing permutations.
30  *
31  * The itk::ImageRandomNonRepeatingIterator works by creating a random
32  * permutation of the image pixels and then using that to control the
33  * order in which it accesses them.  The classes NodeOfPermutation and
34  * RandomPermutation are used to support that.  RandomPermutation is
35  * basically container which holds NodeOfPermutation objects.  The
36  * node class overloads the < operator, which allows the sort algorithm
37  * from the STL to be used on it.
38  * \ingroup ITKCommon
39  */
40 class NodeOfPermutation
41 {
42 public:
43   SizeValueType m_Priority;
44   SizeValueType m_Index;
45   double        m_Value;
46 
NodeOfPermutation()47   NodeOfPermutation ()
48   {
49     m_Priority = 0;
50     m_Index = 0;
51     m_Value = 0.0;
52   }
53 
54   bool operator<(const NodeOfPermutation & b) const
55   {
56     if ( m_Priority == b.m_Priority )
57       {
58       return m_Value < b.m_Value;
59       }
60     else
61       {
62       return m_Priority < b.m_Priority;
63       }
64   }
65 };
66 
67 /** \class RandomPermutation
68  * \brief Produce a random permutation of a collection.
69  * \ingroup ITKCommon
70  */
71 class RandomPermutation
72 {
73 public:
74   using GeneratorPointer = typename Statistics::MersenneTwisterRandomVariateGenerator::Pointer;
75   NodeOfPermutation *m_Permutation;
76   GeneratorPointer   m_Generator;
77   SizeValueType      m_Size;
78 
RandomPermutation(SizeValueType sz)79   RandomPermutation(SizeValueType sz)
80   {
81     m_Size = sz;
82     m_Permutation = new NodeOfPermutation[m_Size];
83     m_Generator = Statistics::MersenneTwisterRandomVariateGenerator::New();
84     this->Shuffle();
85   }
86 
87   RandomPermutation &operator=(const RandomPermutation &it)
88     {
89       delete[] m_Permutation;
90       m_Size = it.m_Size;
91       m_Permutation = new NodeOfPermutation[m_Size];
92       m_Generator = it.m_Generator;
93       return *this;
94     }
95 
SetPriority(SizeValueType i,SizeValueType priority)96   void SetPriority(SizeValueType i, SizeValueType priority)
97   {
98     if ( i > m_Size )
99       {
100       std::ostringstream ostrm;
101       ostrm << "Error: RandomPermuation does not have " << i << " elements" << std::endl;
102       throw std::runtime_error(ostrm.str());
103       }
104     else
105       {
106       m_Permutation[i].m_Priority = priority;
107       }
108   }
109 
Shuffle()110   void Shuffle()
111   {
112     for ( SizeValueType i = 0; i < m_Size; i++ )
113       {
114       m_Permutation[i].m_Value = m_Generator->GetVariateWithClosedRange (1.0);
115       m_Permutation[i].m_Index = i;
116       }
117     std::sort(m_Permutation, m_Permutation + m_Size);
118   }
119 
120   SizeValueType operator[](SizeValueType i)
121   {
122     return m_Permutation[i].m_Index;
123   }
124 
~RandomPermutation()125   ~RandomPermutation()
126   {
127     delete[] m_Permutation;
128   }
129 
130   /** Reinitialize the seed of the random number generator */
ReinitializeSeed()131   void ReinitializeSeed()
132   {
133     m_Generator->Initialize();
134   }
135 
ReinitializeSeed(unsigned int seed)136   void ReinitializeSeed(unsigned int seed)
137   {
138     m_Generator->SetSeed (seed);
139   }
140 };
141 
142 /** \class ImageRandomNonRepeatingConstIteratorWithIndex
143  * \brief A multi-dimensional image iterator that visits a random set of pixels
144  * within an image region.  All pixels in the image will be visited before any
145  * are repeated.  A priority image may be passed to the interator which
146  * will cause it to select certain sets of pixels (those with lower priority
147  * values) before others.
148  *
149  *  This class was contributed by Rupert Brooks, McGill Centre for Intelligent
150  *  Machines, Montreal, Canada.  It is heavily based on the
151  *  ImageRandomIterator class.
152  *
153  * ImageRandomNonRepeatingConstIteratorWithIndex is a multi-dimensional
154  * iterator class that
155  * is templated over image type.  ImageRandomNonRepeatingConstIteratorWithIndex
156  * is constrained to walk only within the specified region. When first
157  * instantiated, it creates (and stores) a random permutation of the image
158  * pixels.  It then visits each pixel in the order specified by the
159  * permutation.  Thus, iterator++ followed by iterator-- will end up leaving
160  * the iterator pointing at the same pixel.  Furthermore, iterating from
161  * beginning to end will cover each pixel in the region exactly once.
162  *
163  * This iterator can be passed an image the same size as the region, which
164  * specifies a priority for the pixels.  Within areas of this priority image
165  * that have the same value, the pixel selection will be random.  Otherwise
166  * the pixel selection will be in the order of the priority image.  In the
167  * extreme, this allows the order of the pixel selection to be completely
168  * specified.
169  *
170  * ImageRandomNonRepeatingConstIteratorWithIndex assumes a particular layout
171  * of the image data. The is arranged in a 1D array as if it were
172  * [][][][slice][row][col] with
173  * Index[0] = col, Index[1] = row, Index[2] = slice, etc.
174  *
175  * \par MORE INFORMATION
176  * For a complete description of the ITK Image Iterators and their API, please
177  * see the Iterators chapter in the ITK Software Guide.  The ITK Software Guide
178  * is available in print and as a free .pdf download from https://www.itk.org.
179  *
180  * \author Rupert Brooks, McGill Centre for Intelligent Machines. Canada
181  *
182  * \ingroup ImageIterators
183  *
184  * \sa ImageConstIterator \sa ConditionalConstIterator
185  * \sa ConstNeighborhoodIterator \sa ConstShapedNeighborhoodIterator
186  * \sa ConstSliceIterator  \sa CorrespondenceDataStructureIterator
187  * \sa FloodFilledFunctionConditionalConstIterator
188  * \sa FloodFilledImageFunctionConditionalConstIterator
189  * \sa FloodFilledImageFunctionConditionalIterator
190  * \sa FloodFilledSpatialFunctionConditionalConstIterator
191  * \sa FloodFilledSpatialFunctionConditionalIterator
192  * \sa ImageConstIterator \sa ImageConstIteratorWithIndex
193  * \sa ImageIterator \sa ImageIteratorWithIndex
194  * \sa ImageLinearConstIteratorWithIndex  \sa ImageLinearIteratorWithIndex
195  * \sa ImageRandomNonRepeatingConstIteratorWithIndex  \sa ImageRandomIteratorWithIndex
196  * \sa ImageRegionConstIterator \sa ImageRegionConstIteratorWithIndex
197  * \sa ImageRegionExclusionConstIteratorWithIndex
198  * \sa ImageRegionExclusionIteratorWithIndex
199  * \sa ImageRegionIterator  \sa ImageRegionIteratorWithIndex
200  * \sa ImageRegionReverseConstIterator  \sa ImageRegionReverseIterator
201  * \sa ImageReverseConstIterator  \sa ImageReverseIterator
202  * \sa ImageSliceConstIteratorWithIndex  \sa ImageSliceIteratorWithIndex
203  * \sa NeighborhoodIterator \sa PathConstIterator  \sa PathIterator
204  * \sa ShapedNeighborhoodIterator  \sa SliceIterator
205  * \sa ImageConstIteratorWithIndex
206  *
207  * \ingroup ITKCommon
208  *
209  * \wiki
210  * \wikiexample{Iterators/ImageRandomNonRepeatingConstIteratorWithIndex,Randomly select pixels from a region of an image without replacement}
211  * \wikiexample{Utilities/RandomPermutation,Permute a sequence of indices}
212  * \endwiki
213  */
214 template< typename TImage >
215 class ITK_TEMPLATE_EXPORT ImageRandomNonRepeatingConstIteratorWithIndex:public ImageConstIteratorWithIndex< TImage >
216 {
217 public:
218   /** Standard class type aliases. */
219   using Self = ImageRandomNonRepeatingConstIteratorWithIndex;
220   using Superclass = ImageConstIteratorWithIndex< TImage >;
221 
222   /** Inherit types from the superclass */
223   using IndexType = typename Superclass::IndexType;
224   using SizeType = typename Superclass::SizeType;
225   using OffsetType = typename Superclass::OffsetType;
226   using RegionType = typename Superclass::RegionType;
227   using ImageType = typename Superclass::ImageType;
228   using PixelContainer = typename Superclass::PixelContainer;
229   using PixelContainerPointer = typename Superclass::PixelContainerPointer;
230   using InternalPixelType = typename Superclass::InternalPixelType;
231   using PixelType = typename Superclass::PixelType;
232   using AccessorType = typename Superclass::AccessorType;
233   using IndexValueType = typename Superclass::IndexValueType;
234   using OffsetValueType = typename Superclass::OffsetValueType;
235   using SizeValueType = typename Superclass::SizeValueType;
236 
237   /** Default constructor. Needed since we provide a cast constructor. */
238   ImageRandomNonRepeatingConstIteratorWithIndex();
~ImageRandomNonRepeatingConstIteratorWithIndex()239   ~ImageRandomNonRepeatingConstIteratorWithIndex() override
240   {
241     delete m_Permutation;
242   }
243 
244   /** Constructor establishes an iterator to walk a particular image and a
245    * particular region of that image. */
246   ImageRandomNonRepeatingConstIteratorWithIndex(const ImageType *ptr, const RegionType & region);
247 
248   /** Constructor that can be used to cast from an ImageIterator to an
249    * ImageRandomNonRepeatingConstIteratorWithIndex. Many routines return an ImageIterator but for a
250    * particular task, you may want an ImageRandomNonRepeatingConstIteratorWithIndex.  Rather than
251    * provide overloaded APIs that return different types of Iterators, itk
252    * returns ImageIterators and uses constructors to cast from an
253    * ImageIterator to a ImageRandomNonRepeatingConstIteratorWithIndex. */
ImageRandomNonRepeatingConstIteratorWithIndex(const ImageConstIteratorWithIndex<TImage> & it)254   ImageRandomNonRepeatingConstIteratorWithIndex(const ImageConstIteratorWithIndex< TImage > & it)
255   {
256     this->ImageConstIteratorWithIndex< TImage >::operator=(it);
257 
258     m_Permutation = nullptr;
259   }
260 
261   /** operator= is provided to deep copy m_Permutation. */
262   Self & operator=(const Self & it);
263 
264   /** Move an iterator to the beginning of the region. */
GoToBegin()265   void GoToBegin()
266   {
267     m_NumberOfSamplesDone = 0L;
268     this->UpdatePosition();
269   }
270 
271   /** Move an iterator to one position past the End of the region. */
GoToEnd()272   void GoToEnd()
273   {
274     m_NumberOfSamplesDone = m_NumberOfSamplesRequested;
275     this->UpdatePosition();
276   }
277 
278   /** Is the iterator at the beginning of the region? */
IsAtBegin()279   bool IsAtBegin() const
280   {
281     return ( m_NumberOfSamplesDone == 0L );
282   }
283 
284   /** Is the iterator at the end of the region? */
IsAtEnd()285   bool IsAtEnd() const
286   {
287     return ( m_NumberOfSamplesDone >= m_NumberOfSamplesRequested );
288   }
289 
290   /** The moving image dimension. */
291   static constexpr unsigned int ImageDimension = TImage::ImageDimension;
292 
293   /** Image with priorities */
294   using PriorityImageType = itk::Image< SizeValueType, Self::ImageDimension >;
295 
296   /** Set the priority image.  The priority image controls the order
297       of the random selection.  Pixels of the same priority will be
298       ordered randomly, but pixels of lower priority value will be
299       selected first.
300    */
301   void SetPriorityImage(const PriorityImageType *priorityImage);
302 
303   /** Increment (prefix) the selected dimension.
304    * No bounds checking is performed. \sa GetIndex \sa operator-- */
305   Self & operator++()
306   {
307     m_NumberOfSamplesDone++;
308     this->UpdatePosition();
309     return *this;
310   }
311 
312   /** Decrement (prefix) the selected dimension.
313    * No bounds checking is performed. \sa GetIndex \sa operator++ */
314   Self & operator--()
315   {
316     m_NumberOfSamplesDone--;
317     this->UpdatePosition();
318     return *this;
319   }
320 
321   /** Set/Get number of random samples to get from the image region */
322   void SetNumberOfSamples(SizeValueType number);
323 
324   SizeValueType GetNumberOfSamples() const;
325 
326   /** Reinitialize the seed of the random number generator  */
327   void ReinitializeSeed();
328 
329   /** Reinitialize the seed of the random number generator with
330    *  a specific value */
331   void ReinitializeSeed(int);
332 
333 private:
334   void UpdatePosition();
335 
336   SizeValueType      m_NumberOfSamplesRequested;
337   SizeValueType      m_NumberOfSamplesDone;
338   SizeValueType      m_NumberOfPixelsInRegion;
339   RandomPermutation *m_Permutation;
340 };
341 } // end namespace itk
342 
343 #ifndef ITK_MANUAL_INSTANTIATION
344 #include "itkImageRandomNonRepeatingConstIteratorWithIndex.hxx"
345 #endif
346 
347 #endif
348