ITK  4.2.0
Insight Segmentation and Registration Toolkit
itkContourExtractor2DImageFilter.h
Go to the documentation of this file.
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 __itkContourExtractor2DImageFilter_h
19 #define __itkContourExtractor2DImageFilter_h
20 
21 #include "itkImageToPathFilter.h"
23 #include "itkConceptChecking.h"
24 #include "itksys/hash_map.hxx"
25 #include "vcl_deque.h"
26 #include "vcl_list.h"
27 
28 namespace itk
29 {
95 template< class TInputImage >
97  public ImageToPathFilter< TInputImage, PolyLineParametricPath< 2 > >
98 {
99 public:
101  itkStaticConstMacro(InputImageDimension, unsigned int,
102  TInputImage::ImageDimension);
103 
105  typedef TInputImage InputImageType;
107 
113 
115  itkNewMacro(Self);
116 
119 
121  typedef typename InputImageType::Pointer InputImagePointer;
122  typedef typename InputImageType::PixelType InputPixelType;
123  typedef typename InputImageType::IndexType InputIndexType;
124  typedef typename InputImageType::OffsetType InputOffsetType;
125  typedef typename InputImageType::RegionType InputRegionType;
129 
132 
133  typedef typename VertexListType::ConstPointer
137  itkSetMacro(ReverseContourOrientation, bool);
138  itkGetConstReferenceMacro(ReverseContourOrientation, bool);
139  itkBooleanMacro(ReverseContourOrientation);
141 
145  itkSetMacro(VertexConnectHighPixels, bool);
146  itkGetConstReferenceMacro(VertexConnectHighPixels, bool);
147  itkBooleanMacro(VertexConnectHighPixels);
149 
152  void SetRequestedRegion(const InputRegionType region);
153 
154  itkGetConstReferenceMacro(RequestedRegion, InputRegionType);
155  void ClearRequestedRegion();
156 
159  itkSetMacro(ContourValue, InputRealType);
160  itkGetConstReferenceMacro(ContourValue, InputRealType);
162 
163 #ifdef ITK_USE_CONCEPT_CHECKING
164 
165  itkConceptMacro( DimensionShouldBe2,
166  ( Concept::SameDimension< itkGetStaticConstMacro(InputImageDimension), 2 > ) );
167  itkConceptMacro( InputPixelTypeComparable,
169  itkConceptMacro( InputHasPixelTraitsCheck,
171  itkConceptMacro( InputHasNumericTraitsCheck,
173 
175 #endif
176 protected:
177 
180  void PrintSelf(std::ostream & os, Indent indent) const;
181 
182  void GenerateData();
183 
187  virtual void GenerateInputRequestedRegion()
189 
190 private:
191  VertexType InterpolateContourPosition(InputPixelType fromValue,
192  InputPixelType toValue,
193  InputIndexType fromIndex,
194  InputOffsetType toOffset);
195 
196  void AddSegment(const VertexType from, const VertexType to);
197 
198  void FillOutputs();
199 
200  ContourExtractor2DImageFilter(const Self &); //purposely not implemented
201  void operator=(const Self &); //purposely not implemented
202 
203  InputRealType m_ContourValue;
204  bool m_ReverseContourOrientation;
205  bool m_VertexConnectHighPixels;
206  bool m_UseCustomRegion;
207  InputRegionType m_RequestedRegion;
208  unsigned int m_NumberOfContoursCreated;
209 
210  // Represent each contour as deque of vertices to facilitate addition of
211  // nodes at beginning or end. At the end of the processing, we will copy
212  // the contour into a PolyLineParametricPath.
213  // We subclass the deque to store an additional bit of information: an
214  // identification number for each growing contour. We use this number so
215  // that when it becomes necessary to merge two growing contours, we can
216  // merge the newer one into the older one. This helps because then we can
217  // guarantee that the output contour list is ordered from left to right,
218  // top to bottom (in terms of the first pixel of the contour encountered
219  // by the marching squares). Currently we make no guarantees that this
220  // pixel is the first pixel in the contour list, just that the contours
221  // are so ordered in the output. Ensuring this latter condition (first
222  // pixel traversed = first pixel in contour) would be possible by either
223  // changing the merging rules, which would make the contouring operation
224  //slower, or by storing additional data as to which pixel was first.
225  class ContourType:public vcl_deque< VertexType >
226  {
227 public:
228  unsigned int m_ContourNumber;
229  };
230 
231  // Store all the growing contours in a list. We may need to delete contours
232  // from anywhere in the sequence (when we merge them together), so we need to
233  // use a list instead of a vector or similar.
234  typedef vcl_list< ContourType > ContourContainer;
235  typedef typename ContourContainer::iterator ContourRef;
236 
237  // declare the hash function we are using for the hash_map.
238  struct VertexHash {
240  inline SizeValueType operator()(const VertexType & k) const
241  {
242  // Xor the hashes of the vertices together, after multiplying the
243  // first by some number, so that identical (x,y) vertex indices
244  // don't all hash to the same bucket. This is a decent if not
245  // optimal hash.
246  const SizeValueType hashVertex1 = this->float_hash(k[0] * 0xbeef);
247  const SizeValueType hashVertex2 = this->float_hash(k[1]);
248  const SizeValueType hashValue = hashVertex1 ^ hashVertex2;
249 
250  return hashValue;
251  }
252 
253  // Define hash function for floats. Based on method from
254  // http://www.brpreiss.com/books/opus4/html/page217.html
255  inline SizeValueType float_hash(const CoordinateType & k) const
256  {
257  if ( k == 0 )
258  {
259  return 0;
260  }
261  int exponent;
262  CoordinateType mantissa = vcl_frexp(k, &exponent);
263  SizeValueType value = static_cast< SizeValueType >( vcl_fabs(mantissa) );
264  value = ( 2 * value - 1 ) * ~0U;
265  return value;
266  }
267  };
268 
269  // We use a hash to associate the endpoints of each contour with the
270  // contour itself. This makes it easy to look up which contour we should add
271  // a new arc to.
272  // We can't store the contours themselves in the hashtable because we
273  // need to have two tables (one to hash from beginpoint -> contour and one
274  // for endpoint -> contour), and sometimes will remove a contour from the
275  // tables (if it has been closed or merged with another contour). So in the
276  // hash table we store a reference to the contour. Because sometimes we will
277  // need to merge contours, we need to be able to quickly remove contours
278  // from our list when they have been merged into another. Thus, we store
279  // an iterator pointing to the contour in the list.
280 
281  typedef itksys::hash_map< VertexType, ContourRef, VertexHash > VertexToContourMap;
282  typedef typename VertexToContourMap::iterator VertexMapIterator;
283  typedef typename VertexToContourMap::value_type VertexContourRefPair;
284 
285  // The contours we find in the image are stored here
287 
288  // And indexed by their beginning and ending points here
291 };
292 } // end namespace itk
293 
294 #ifndef ITK_MANUAL_INSTANTIATION
295 #include "itkContourExtractor2DImageFilter.hxx"
296 #endif
297 
298 #endif
299