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