Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
itkContourExtractor2DImageFilter.h
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 /*===================================================================
18 
19 This file is based heavily on a corresponding ITK filter.
20 
21 ===================================================================*/
22 
23 #ifndef __itkContourExtractor2DImageFilter_h
24 #define __itkContourExtractor2DImageFilter_h
25 
26 #include "itkConceptChecking.h"
27 #include "itkImageToPathFilter.h"
28 #include "itkNumericTraits.h"
29 #include "itkPolyLineParametricPath.h"
30 #include "vcl_deque.h"
31 #include "vcl_list.h"
32 #include <itksys/hash_map.hxx>
33 
34 namespace itk
35 {
96  template <class TInputImage>
97  class ITK_EXPORT ContourExtractor2DImageFilter : public ImageToPathFilter<TInputImage, PolyLineParametricPath<2>>
98  {
99  public:
101  itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension);
102 
104  typedef TInputImage InputImageType;
105  typedef PolyLineParametricPath<2> OutputPathType;
106 
112 
114  itkFactorylessNewMacro(Self) itkCloneMacro(Self)
115 
118 
120  typedef typename InputImageType::Pointer InputImagePointer;
121  typedef typename InputImageType::PixelType InputPixelType;
122  typedef typename InputImageType::IndexType InputIndexType;
123  typedef typename InputImageType::OffsetType InputOffsetType;
124  typedef typename InputImageType::RegionType InputRegionType;
125  typedef typename OutputPathType::Pointer OutputPathPointer;
126  typedef typename OutputPathType::VertexType VertexType;
127  typedef typename OutputPathType::VertexListType VertexListType;
128 
130  typedef typename NumericTraits<InputPixelType>::RealType InputRealType;
131 
132  typedef typename VertexListType::ConstPointer VertexListConstPointer;
135  itkSetMacro(ReverseContourOrientation, bool);
136  itkGetConstReferenceMacro(ReverseContourOrientation, bool);
137  itkBooleanMacro(ReverseContourOrientation);
138 
142  itkSetMacro(VertexConnectHighPixels, bool);
143  itkGetConstReferenceMacro(VertexConnectHighPixels, bool);
144  itkBooleanMacro(VertexConnectHighPixels);
145 
148  void SetRequestedRegion(const InputRegionType region);
149  itkGetConstReferenceMacro(RequestedRegion, InputRegionType);
150  void ClearRequestedRegion();
151 
154  itkSetMacro(ContourValue, InputRealType);
155  itkGetConstReferenceMacro(ContourValue, InputRealType);
156 
157 #ifdef ITK_USE_CONCEPT_CHECKING
158 
159  itkConceptMacro(DimensionShouldBe2, (Concept::SameDimension<itkGetStaticConstMacro(InputImageDimension), 2>));
160  itkConceptMacro(InputPixelTypeComparable, (Concept::Comparable<InputPixelType>));
161  itkConceptMacro(InputHasPixelTraitsCheck, (Concept::HasPixelTraits<InputPixelType>));
162  itkConceptMacro(InputHasNumericTraitsCheck, (Concept::HasNumericTraits<InputPixelType>));
164 #endif
165 
166  protected:
167  ContourExtractor2DImageFilter();
168  virtual ~ContourExtractor2DImageFilter();
169  void PrintSelf(std::ostream &os, Indent indent) const;
170 
171  void GenerateData();
172 
176  virtual void GenerateInputRequestedRegion() throw(InvalidRequestedRegionError);
177 
178  private:
179  VertexType InterpolateContourPosition(InputPixelType fromValue,
180  InputPixelType toValue,
181  InputIndexType fromIndex,
182  InputOffsetType toOffset);
183  void AddSegment(const VertexType from, const VertexType to);
184  void FillOutputs();
185  ContourExtractor2DImageFilter(const Self &); // purposely not implemented
186  void operator=(const Self &); // purposely not implemented
187 
188  InputRealType m_ContourValue;
189  bool m_ReverseContourOrientation;
190  bool m_VertexConnectHighPixels;
191  bool m_UseCustomRegion;
192  InputRegionType m_RequestedRegion;
193  unsigned int m_NumberOfContoursCreated;
194 
195  // Represent each contour as deque of vertices to facilitate addition of
196  // nodes at beginning or end. At the end of the processing, we will copy
197  // the contour into a PolyLineParametricPath.
198  // We subclass the deque to store an additional bit of information: an
199  // identification number for each growing contour. We use this number so
200  // that when it becomes necessary to merge two growing contours, we can
201  // merge the newer one into the older one. This helps because then we can
202  // guarantee that the output contour list is ordered from left to right,
203  // top to bottom (in terms of the first pixel of the contour encountered
204  // by the marching squares). Currently we make no guarantees that this
205  // pixel is the first pixel in the contour list, just that the contours
206  // are so ordered in the output. Ensuring this latter condition (first
207  // pixel traversed = first pixel in contour) would be possible by either
208  // changing the merging rules, which would make the contouring operation
209  // slower, or by storing additional data as to which pixel was first.
210  class ContourType : public vcl_deque<VertexType>
211  {
212  public:
213  unsigned int m_ContourNumber;
214  };
215 
216  // Store all the growing contours in a list. We may need to delete contours
217  // from anywhere in the sequence (when we merge them together), so we need to
218  // use a list instead of a vector or similar.
219  typedef vcl_list<ContourType> ContourContainer;
220  typedef typename ContourContainer::iterator ContourRef;
221 
222  // declare the hash function we are using for the hash_map.
223  struct VertexHash
224  {
225  typedef typename VertexType::CoordRepType CoordinateType;
226  inline size_t operator()(const VertexType &k) const
227  {
228  // Xor the hashes of the vertices together, after multiplying the
229  // first by some number, so that identical (x,y) vertex indices
230  // don't all hash to the same bucket. This is a decent if not
231  // optimal hash.
232  const size_t hashVertex1 = this->float_hash(k[0] * 0xbeef);
233  const size_t hashVertex2 = this->float_hash(k[1]);
234  const size_t hashValue = hashVertex1 ^ hashVertex2;
235  return hashValue;
236  }
237 
238  // Define hash function for floats. Based on method from
239  // http://www.brpreiss.com/books/opus4/html/page217.html
240  inline size_t float_hash(const CoordinateType &k) const
241  {
242  if (k == 0)
243  {
244  return 0;
245  }
246  int exponent;
247  CoordinateType mantissa = vcl_frexp(k, &exponent);
248  size_t value = static_cast<size_t>(vcl_fabs(mantissa));
249  value = (2 * value - 1) * ~0U;
250  return value;
251  }
252  };
253 
254  // We use a hash to associate the endpoints of each contour with the
255  // contour itself. This makes it easy to look up which contour we should add
256  // a new arc to.
257  // We can't store the contours themselves in the hashtable because we
258  // need to have two tables (one to hash from beginpoint -> contour and one
259  // for endpoint -> contour), and sometimes will remove a contour from the
260  // tables (if it has been closed or merged with another contour). So in the
261  // hash table we store a reference to the contour. Because sometimes we will
262  // need to merge contours, we need to be able to quickly remove contours
263  // from our list when they have been merged into another. Thus, we store
264  // an iterator pointing to the contour in the list.
265 
266  typedef itksys::hash_map<VertexType, ContourRef, VertexHash> VertexToContourMap;
267  typedef typename VertexToContourMap::iterator VertexMapIterator;
268  typedef typename VertexToContourMap::value_type VertexContourRefPair;
269 
270  // The contours we find in the image are stored here
271  ContourContainer m_Contours;
272 
273  // And indexed by their beginning and ending points here
274  VertexToContourMap m_ContourStarts;
275  VertexToContourMap m_ContourEnds;
276  };
277 
278 } // end namespace itk
279 
280 #ifndef ITK_MANUAL_INSTANTIATION
282 #endif
283 
284 #endif
Base class for filters that take an image as input and produce an path as output. ...
ImageToPathFilter< InputImageType, OutputPathType > Superclass
unsigned short PixelType
Computes a list of PolyLineParametricPath objects from the contours in a 2D image.
NumericTraits< InputPixelType >::RealType InputRealType