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 itkImageToListSampleAdaptor_h
19 #define itkImageToListSampleAdaptor_h
20 
21 #include <typeinfo>
22 #include <utility>
23 
24 #include "itkImage.h"
25 #include "itkPixelTraits.h"
26 #include "itkListSample.h"
27 #include "itkSmartPointer.h"
28 #include "itkImageRegionIterator.h"
29 #include "itkMeasurementVectorTraits.h"
30 
31 namespace itk
32 {
33 namespace Statistics
34 {
35 /** \class ImageToListSampleAdaptor
36  *  \brief This class provides ListSample interface to ITK Image
37  *
38  * After calling SetImage( const Image * ) method to plug in the image object,
39  * users can use Sample interfaces to access Image data. The resulting data
40  * are a list of measurement vectors.
41  *
42  * The measurment vector type is determined from the image pixel type. This class
43  * handles images with scalar, fixed array or variable length vector pixel types.
44  *
45  * \sa Sample, ListSample
46  * \ingroup ITKStatistics
47  *
48  * \wiki
49  * \wikiexample{Statistics/ImageToListSampleAdaptor,Create a list of samples from an image without duplicating the data}
50  * \endwiki
51  */
52 
53 template< typename TImage >
54 class ITK_TEMPLATE_EXPORT ImageToListSampleAdaptor:
55   public ListSample< typename MeasurementVectorPixelTraits< typename TImage::PixelType >::MeasurementVectorType >
56 {
57 public:
58   ITK_DISALLOW_COPY_AND_ASSIGN(ImageToListSampleAdaptor);
59 
60   /** Standard class type aliases */
61   using Self = ImageToListSampleAdaptor;
62 
63   using Superclass = ListSample< typename MeasurementVectorPixelTraits<
64                         typename TImage::PixelType >::MeasurementVectorType >;
65 
66   using Pointer = SmartPointer< Self >;
67   using ConstPointer = SmartPointer< const Self >;
68 
69   /** Run-time type information (and related methods). */
70   itkTypeMacro(ImageToListSampleAdaptor, ListSample);
71 
72   /** Method for creation through the object factory. */
73   itkNewMacro(Self);
74 
75   /** Image type alias */
76   using ImageType = TImage;
77   using ImagePointer = typename ImageType::Pointer;
78   using ImageConstPointer = typename ImageType::ConstPointer;
79   using IndexType = typename ImageType::IndexType;
80   using PixelType = typename ImageType::PixelType;
81   using PixelContainerConstPointer = typename ImageType::PixelContainerConstPointer;
82 
83   /** Image Iterator type alias support */
84   using ImageIteratorType = ImageRegionIterator< ImageType >;
85   using ImageConstIteratorType = ImageRegionConstIterator< ImageType >;
86   using PixelTraitsType = PixelTraits< typename TImage::PixelType >;
87 
88 
89   /** Superclass type alias for Measurement vector, measurement,
90    * Instance Identifier, frequency, size, size element value */
91   using MeasurementPixelTraitsType = MeasurementVectorPixelTraits< PixelType >;
92   using MeasurementVectorType = typename MeasurementPixelTraitsType::MeasurementVectorType;
93 
94   using MeasurementVectorTraitsType = MeasurementVectorTraitsTypes< MeasurementVectorType >;
95   using MeasurementType = typename MeasurementVectorTraitsType::ValueType;
96 
97   using AbsoluteFrequencyType = typename Superclass::AbsoluteFrequencyType;
98   using TotalAbsoluteFrequencyType = typename Superclass::TotalAbsoluteFrequencyType;
99   using MeasurementVectorSizeType = typename Superclass::MeasurementVectorSizeType;
100   using InstanceIdentifier = typename Superclass::InstanceIdentifier;
101 
102   using ValueType = MeasurementVectorType;
103 
104   /** Method to set the image */
105   void SetImage(const TImage *image);
106 
107   /** Method to get the image */
108   const TImage * GetImage() const;
109 
110   /** returns the number of measurement vectors in this container */
111   InstanceIdentifier Size() const override;
112 
113   /** method to return measurement vector for a specified id */
114   const MeasurementVectorType & GetMeasurementVector(InstanceIdentifier id) const override;
115 
GetMeasurementVectorSize()116   MeasurementVectorSizeType GetMeasurementVectorSize() const override
117   {
118     // some filter are expected that this method returns something even if the
119     // input is not set. This won't be the right value for a variable length vector
120     // but it's better than an exception.
121     if( m_Image.IsNull() )
122       {
123       return Superclass::GetMeasurementVectorSize();
124       }
125     else
126       {
127       return m_Image->GetNumberOfComponentsPerPixel();
128       }
129   }
130 
131   /** method to return frequency for a specified id */
132   AbsoluteFrequencyType GetFrequency(InstanceIdentifier id) const override;
133 
134   /** method to return the total frequency */
135   TotalAbsoluteFrequencyType GetTotalFrequency() const override;
136 
137   /** \class ConstIterator
138    *  \brief Const Iterator
139    * \ingroup ITKStatistics
140    */
141   class ConstIterator
142   {
143     friend class ImageToListSampleAdaptor;
144 
145   public:
146 
ConstIterator(const ImageToListSampleAdaptor * adaptor)147     ConstIterator(const ImageToListSampleAdaptor *adaptor)
148     {
149       *this = adaptor->Begin();
150     }
151 
ConstIterator(const ConstIterator & iter)152     ConstIterator(const ConstIterator & iter) :
153       m_Iter(iter.m_Iter),
154       m_InstanceIdentifier(iter.m_InstanceIdentifier)
155     {}
156 
157     ConstIterator & operator=(const ConstIterator & iter)
158     {
159       m_Iter = iter.m_Iter;
160       m_InstanceIdentifier = iter.m_InstanceIdentifier;
161       return *this;
162     }
163 
GetFrequency()164     AbsoluteFrequencyType GetFrequency() const
165     {
166       return 1;
167     }
168 
GetMeasurementVector()169     const MeasurementVectorType & GetMeasurementVector() const
170     {
171       MeasurementVectorTraits::Assign( this->m_MeasurementVectorCache, m_Iter.Get() );
172       return this->m_MeasurementVectorCache;
173     }
174 
GetInstanceIdentifier()175     InstanceIdentifier GetInstanceIdentifier() const
176     {
177       return m_InstanceIdentifier;
178     }
179 
180     ConstIterator & operator++()
181     {
182       ++m_Iter;
183       ++m_InstanceIdentifier;
184       return *this;
185     }
186 
187     bool operator!=(const ConstIterator & it)
188     {
189       return ( m_Iter != it.m_Iter );
190     }
191 
192     bool operator==(const ConstIterator & it)
193     {
194       return ( m_Iter == it.m_Iter );
195     }
196 
197   protected:
198     // This method should only be available to the ListSample class
ConstIterator(ImageConstIteratorType iter,InstanceIdentifier iid)199     ConstIterator(ImageConstIteratorType  iter, InstanceIdentifier iid) :
200       m_Iter(std::move(iter)),
201       m_InstanceIdentifier(iid)
202     {}
203 
204   private:
205     ConstIterator() = delete;
206     ImageConstIteratorType        m_Iter;
207     mutable MeasurementVectorType m_MeasurementVectorCache;
208     InstanceIdentifier            m_InstanceIdentifier;
209   };
210 
211   /** \class Iterator
212    *  \brief Iterator
213    * \ingroup ITKStatistics
214    */
215   class Iterator:
216     public ConstIterator
217   {
218     friend class ImageToListSampleAdaptor;
219 
220   public:
221 
Iterator(Self * adaptor)222     Iterator(Self *adaptor) :
223       ConstIterator(adaptor)
224     {}
225 
Iterator(const Iterator & iter)226     Iterator(const Iterator & iter):
227       ConstIterator(iter)
228     {}
229 
230     Iterator & operator=(const Iterator & iter)
231     {
232       this->ConstIterator::operator=(iter);
233       return *this;
234     }
235 
236   protected:
Iterator(const ImageIteratorType & iter,InstanceIdentifier iid)237     Iterator(const ImageIteratorType & iter, InstanceIdentifier iid) :
238       ConstIterator(iter, iid)
239     {}
240 
241   private:
242     // To ensure const-correctness these method must not be in the public API.
243     // The are purposly not implemented, since they should never be called.
244     Iterator() = delete;
245     Iterator(const Self *adaptor) = delete;
246     Iterator(const ImageConstIteratorType & iter, InstanceIdentifier iid) = delete;
247     Iterator(const ConstIterator & it) = delete;
248     ConstIterator & operator=(const ConstIterator & it) = delete;
249   };
250 
251   /** returns an iterator that points to the beginning of the container */
Begin()252   Iterator Begin()
253   {
254     ImagePointer           nonConstImage = const_cast< ImageType * >( m_Image.GetPointer() );
255     ImageIteratorType imageIterator( nonConstImage, nonConstImage->GetLargestPossibleRegion() );
256     imageIterator.GoToBegin();
257     Iterator               iter(imageIterator, 0);
258     return iter;
259   }
260 
261   /** returns an iterator that points to the end of the container */
End()262   Iterator End()
263   {
264     ImagePointer           nonConstImage = const_cast< ImageType * >( m_Image.GetPointer() );
265     const typename ImageType::RegionType & largestRegion = nonConstImage->GetLargestPossibleRegion();
266     ImageIteratorType imageIterator( nonConstImage, largestRegion );
267     imageIterator.GoToEnd();
268     Iterator          iter( imageIterator, largestRegion.GetNumberOfPixels() );
269 
270     return iter;
271   }
272 
273   /** returns an iterator that points to the beginning of the container */
Begin()274   ConstIterator Begin() const
275   {
276     ImageConstIteratorType imageConstIterator( m_Image, m_Image->GetLargestPossibleRegion() );
277     imageConstIterator.GoToBegin();
278     ConstIterator          iter(imageConstIterator, 0);
279 
280     return iter;
281   }
282 
283   /** returns an iterator that points to the end of the container */
End()284   ConstIterator End() const
285   {
286     const typename ImageType::RegionType & largestRegion = m_Image->GetLargestPossibleRegion();
287     ImageConstIteratorType imageConstIterator( m_Image, largestRegion );
288     imageConstIterator.GoToEnd();
289     ConstIterator          iter( imageConstIterator, largestRegion.GetNumberOfPixels() );
290 
291     return iter;
292   }
293 
294 protected:
295   ImageToListSampleAdaptor();
296   ~ImageToListSampleAdaptor() override = default;
297   void PrintSelf(std::ostream & os, Indent indent) const override;
298 
299 private:
300   ImageConstPointer             m_Image;
301   mutable MeasurementVectorType m_MeasurementVectorInternal;
302 
303 };  // end of class ImageToListSampleAdaptor
304 } // end of namespace Statistics
305 } // end of namespace itk
306 
307 #ifndef ITK_MANUAL_INSTANTIATION
308 #include "itkImageToListSampleAdaptor.hxx"
309 #endif
310 
311 #endif
312