Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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