Orfeo Toolbox  3.16
itkRelabelComponentImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkRelabelComponentImageFilter.txx,v $
5  Language: C++
6  Date: $Date: 2009-04-27 22:58:48 $
7  Version: $Revision: 1.18 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #ifndef __itkRelabelComponentImageFilter_txx
18 #define __itkRelabelComponentImageFilter_txx
19 
21 #include "itkImageRegionIterator.h"
23 #include "itkNumericTraits.h"
24 #include "itkProgressReporter.h"
25 #include "itk_hash_map.h"
26 #include <map>
27 
28 namespace itk
29 {
30 
31 template< class TInputImage, class TOutputImage >
32 void
35 {
36  // call the superclass' implementation of this method
37  Superclass::GenerateInputRequestedRegion();
38 
39  // We need all the input.
40  InputImagePointer input = const_cast<InputImageType *>(this->GetInput());
41  if( input )
42  {
43  input->SetRequestedRegion( input->GetLargestPossibleRegion() );
44  }
45 }
46 
47 
48 template< class TInputImage, class TOutputImage >
49 void
52 {
53  unsigned long i;
54 
55  // Use a map to keep track of the size of each object. Object
56  // number -> ObjectType (which has Object number and the two sizes)
58  MapType sizeMap;
59  typename MapType::iterator mapIt;
60  typedef typename MapType::value_type MapValueType;
61 
62  // Get the input and the output
63  typename TInputImage::ConstPointer input = this->GetInput();
64  typename TOutputImage::Pointer output = this->GetOutput();
65 
66  // Setup a progress reporter. We have 2 stages to the algorithm so
67  // use the total number of pixels accessed. We walk the entire input
68  // in the first pass, then walk just the output requested region in
69  // the second pass.
70  ProgressReporter progress(this, 0,
71  input->GetRequestedRegion().GetNumberOfPixels() +
72  output->GetRequestedRegion().GetNumberOfPixels());
73 
74 
75  // Calculate the size of pixel
76  float physicalPixelSize = 1.0;
77  for (i=0; i < TInputImage::ImageDimension; ++i)
78  {
79  physicalPixelSize *= input->GetSpacing()[i];
80  }
81 
82  RelabelComponentObjectType initialSize;
83  initialSize.m_SizeInPixels = 1;
84  initialSize.m_SizeInPhysicalUnits = physicalPixelSize;
85 
86  // First pass: walk the entire input image and determine what
87  // labels are used and the number of pixels used in each label.
88  //
89 
90  // walk the input
91  ImageRegionConstIterator<InputImageType> it(input, input->GetRequestedRegion());
92  it.GoToBegin();
93 
94  while (!it.IsAtEnd())
95  {
96  // Get the input pixel value
97  const LabelType inputValue = static_cast< LabelType>( it.Get() );
98 
99  // if the input pixel is not the background
100  if (inputValue != NumericTraits<LabelType>::Zero)
101  {
102  // Does this label already exist
103  mapIt = sizeMap.find( inputValue );
104  if ( mapIt == sizeMap.end() )
105  {
106  // label is not currently in the map
107  initialSize.m_ObjectNumber = inputValue;
108  sizeMap.insert( MapValueType( inputValue, initialSize ) );
109  }
110  else
111  {
112  // label is already in the map, update the values
113  (*mapIt).second.m_SizeInPixels++;
114  (*mapIt).second.m_SizeInPhysicalUnits += physicalPixelSize;
115  }
116  }
117 
118  // increment the iterators
119  ++it;
120  progress.CompletedPixel();
121  }
122 
123  // Now we need to reorder the labels. Use the m_ObjectSortingOrder
124  // to determine how to sort the objects. Define a map for converting
125  // input labels to output labels.
126  //
127  typedef std::vector<RelabelComponentObjectType> VectorType;
128  VectorType sizeVector;
129  typename VectorType::iterator vit;
130 
131  typedef std::map< LabelType, LabelType > RelabelMapType;
132  RelabelMapType relabelMap;
133 
134  // copy the original object map to a vector so we can sort it
135  for (mapIt = sizeMap.begin(); mapIt != sizeMap.end(); ++mapIt)
136  {
137  sizeVector.push_back( (*mapIt).second );
138  }
139 
140  // sort the objects by size and define the map to use to relabel the image
141  std::sort(sizeVector.begin(), sizeVector.end(), RelabelComponentSizeInPixelsComparator() );
142 
143  // create a lookup table to map the input label to the output label.
144  // cache the object sizes for later access by the user
145  m_NumberOfObjects = sizeVector.size();
146  m_OriginalNumberOfObjects = sizeVector.size();
147  m_SizeOfObjectsInPixels.clear();
148  m_SizeOfObjectsInPixels.resize(m_NumberOfObjects);
149  m_SizeOfObjectsInPhysicalUnits.clear();
150  m_SizeOfObjectsInPhysicalUnits.resize(m_NumberOfObjects);
151  int NumberOfObjectsRemoved = 0;
152  for (i=0, vit = sizeVector.begin(); vit != sizeVector.end(); ++vit, ++i)
153  {
154 
155  // if we find an object smaller than the minimum size, we
156  // terminate the loop.
157  if (m_MinimumObjectSize > 0 && (*vit).m_SizeInPixels < m_MinimumObjectSize)
158  {
159  // map small objects to the background
160  NumberOfObjectsRemoved++;
161  relabelMap.insert(RelabelMapType::value_type( (*vit).m_ObjectNumber, 0));
162  }
163  else
164  {
165  // map for input labels to output labels (Note we use i+1 in the
166  // map since index 0 is the background)
167  relabelMap.insert(RelabelMapType::value_type( (*vit).m_ObjectNumber, i+1));
168 
169  // cache object sizes for later access by the user
170  m_SizeOfObjectsInPixels[i] = (*vit).m_SizeInPixels;
171  m_SizeOfObjectsInPhysicalUnits[i] = (*vit).m_SizeInPhysicalUnits;
172  }
173 
174  }
175 
176  // update number of objects and resize cache vectors if we have removed small objects
177  m_NumberOfObjects -= NumberOfObjectsRemoved;
178  if (NumberOfObjectsRemoved > 0)
179  {
180  m_SizeOfObjectsInPixels.resize(m_NumberOfObjects);
181  m_SizeOfObjectsInPhysicalUnits.resize(m_NumberOfObjects);
182  }
183 
184  // Second pass: walk just the output requested region and relabel
185  // the necessary pixels.
186  //
187 
188  // Allocate the output
189  this->AllocateOutputs();
190 
191  // Remap the labels. Note we only walk the region of the output
192  // that was requested. This may be a subset of the input image.
193  OutputPixelType outputValue;
196  output->GetRequestedRegion());
198  output->GetRequestedRegion());
199 
200  it.GoToBegin();
201  oit.GoToBegin();
202  while ( !oit.IsAtEnd() )
203  {
204  const LabelType inputValue = static_cast< LabelType>( it.Get() );
205 
206  if (inputValue != NumericTraits<LabelType>::Zero)
207  {
208 
209  // lookup the mapped label
210  outputValue = static_cast<OutputPixelType>(relabelMap[inputValue]);
211  oit.Set( outputValue );
212  }
213  else
214  {
215  oit.Set( inputValue );
216  }
217 
218  // increment the iterators
219  ++it;
220  ++oit;
221  progress.CompletedPixel();
222  }
223 }
224 
225 
226 template< class TInputImage, class TOutputImage >
227 void
229 ::PrintSelf(std::ostream& os, Indent indent) const
230 {
231  Superclass::PrintSelf(os, indent);
232 
233  os << indent << "NumberOfObjects: " << m_NumberOfObjects << std::endl;
234  os << indent << "OriginalNumberOfObjects: " << m_OriginalNumberOfObjects << std::endl;
235  os << indent << "NumberOfObjectsToPrint: "
236  << m_NumberOfObjectsToPrint << std::endl;
237  os << indent << "MinimumObjectSizez: " << m_MinimumObjectSize << std::endl;
238 
239  std::vector<ObjectSizeType>::const_iterator it;
240  std::vector<float>::const_iterator fit;
241  LabelType i;
242 
243  // limit the number of objects to print
244  LabelType numPrint = m_NumberOfObjectsToPrint;
245  if (numPrint > m_SizeOfObjectsInPixels.size())
246  {
247  numPrint = m_SizeOfObjectsInPixels.size();
248  }
249 
250 
251  for (i=0, it = m_SizeOfObjectsInPixels.begin(),
252  fit = m_SizeOfObjectsInPhysicalUnits.begin();
253  i < numPrint; ++it, ++fit, ++i)
254  {
255  os << indent << "Object #" << i+1 << ": " << *it << " pixels, "
256  << *fit << " physical units" << std::endl;
257  }
258  if (numPrint < m_SizeOfObjectsInPixels.size())
259  {
260  os << indent << "..." << std::endl;
261  }
262 }
263 
264 } // end namespace itk
265 
266 #endif

Generated at Sun May 19 2013 00:03:59 for Orfeo Toolbox with doxygen 1.8.3.1