Orfeo Toolbox  3.16
itkLabelStatisticsImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: itkLabelStatisticsImageFilter.txx,v $
5 Language: C++
6 Date: $Date: 2009-05-08 16:17:51 $
7 Version: $Revision: 1.25 $
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 __itkLabelStatisticsImageFilter_txx
18 #define __itkLabelStatisticsImageFilter_txx
20 
21 #include "itkImageRegionIterator.h"
24 #include "itkNumericTraits.h"
25 #include "itkProgressReporter.h"
26 
27 namespace itk {
28 #if defined(__GNUC__) && (__GNUC__ <= 2) //NOTE: This class needs a mutex for gnu 2.95
29 
30 #define LOCK_HASHMAP this->m_Mutex.Lock()
31 #define UNLOCK_HASHMAP this->m_Mutex.Unlock()
32 #else
33 #define LOCK_HASHMAP
34 #define UNLOCK_HASHMAP
35 #endif
36 
37 template<class TInputImage, class TLabelImage>
40 {
41  this->SetNumberOfRequiredInputs(2);
42  m_UseHistograms = false;
43 #ifdef ITK_USE_REVIEW_STATISTICS
44  m_NumBins.SetSize(1);
45 #endif
46  m_NumBins[0] = 20;
47  m_LowerBound = static_cast<RealType>( NumericTraits<PixelType>::NonpositiveMin() );
48  m_UpperBound = static_cast<RealType>( NumericTraits<PixelType>::max() );
49 }
50 
51 
52 template<class TInputImage, class TLabelImage>
53 void
56 {
57  Superclass::GenerateInputRequestedRegion();
58  if ( this->GetInput() )
59  {
60  InputImagePointer image =
61  const_cast< typename Superclass::InputImageType * >( this->GetInput() );
62  if (image)
63  {
64  image->SetRequestedRegionToLargestPossibleRegion();
65  }
66  }
67  if ( this->GetLabelInput() )
68  {
69  LabelImagePointer label =
70  const_cast< TLabelImage * >( this->GetLabelInput() );
71  label->SetRequestedRegionToLargestPossibleRegion();
72  }
73 }
74 
75 template<class TInputImage, class TLabelImage>
76 void
79 {
80  Superclass::EnlargeOutputRequestedRegion(data);
82 }
83 
84 
85 template<class TInputImage, class TLabelImage>
86 void
89 {
90  // Pass the input through as the output
91  InputImagePointer image =
92  const_cast< TInputImage * >( this->GetInput() );
93  this->GraftOutput( image );
94 
95  // Nothing that needs to be allocated for the remaining outputs
96 }
97 
98 template<class TInputImage, class TLabelImage>
99 void
101 ::SetHistogramParameters(const int numBins, RealType lowerBound, RealType upperBound)
102 {
103  m_NumBins[0] = numBins;
104  m_LowerBound = lowerBound;
105  m_UpperBound = upperBound;
106  m_UseHistograms = true;
107 }
108 
109 template<class TInputImage, class TLabelImage>
110 void
113 {
114  int numberOfThreads = this->GetNumberOfThreads();
115 
116  // Resize the thread temporaries
117  m_LabelStatisticsPerThread.resize(numberOfThreads);
118 
119  // Initialize the temporaries
120  for (int i=0; i < numberOfThreads; ++i)
121  {
122  m_LabelStatisticsPerThread[i].clear();
123  }
124 
125  // Initialize the final map
126  m_LabelStatistics.clear();
127 }
128 
129 template<class TInputImage, class TLabelImage>
130 void
133 {
134  MapIterator mapIt;
135  MapConstIterator threadIt;
136  int i;
137  int numberOfThreads = this->GetNumberOfThreads();
138 
139  // Run through the map for each thread and accumulate the count,
140  // sum, and sumofsquares
141  for (i = 0; i < numberOfThreads; i++)
142  {
143  // iterate over the map for this thread
144  for (threadIt = m_LabelStatisticsPerThread[i].begin();
145  threadIt != m_LabelStatisticsPerThread[i].end();
146  ++threadIt)
147  {
148  // does this label exist in the cumulative stucture yet?
149  mapIt = m_LabelStatistics.find( (*threadIt).first );
150  if (mapIt == m_LabelStatistics.end())
151  {
152  // create a new entry
153  typedef typename MapType::value_type MapValueType;
154  if (m_UseHistograms)
155  {
156  mapIt = m_LabelStatistics.insert( MapValueType((*threadIt).first,
157  LabelStatistics(m_NumBins[0], m_LowerBound, m_UpperBound)) ).first;
158  }
159  else
160  {
161  mapIt = m_LabelStatistics.insert( MapValueType((*threadIt).first,
162  LabelStatistics()) ).first;
163  }
164  }
165 
166  // accumulate the information from this thread
167  (*mapIt).second.m_Count += (*threadIt).second.m_Count;
168  (*mapIt).second.m_Sum += (*threadIt).second.m_Sum;
169  (*mapIt).second.m_SumOfSquares += (*threadIt).second.m_SumOfSquares;
170 
171  if ((*mapIt).second.m_Minimum > (*threadIt).second.m_Minimum)
172  {
173  (*mapIt).second.m_Minimum = (*threadIt).second.m_Minimum;
174  }
175  if ((*mapIt).second.m_Maximum < (*threadIt).second.m_Maximum)
176  {
177  (*mapIt).second.m_Maximum = (*threadIt).second.m_Maximum;
178  }
179 
180  //bounding box is min,max pairs
181  int dimension = (*mapIt).second.m_BoundingBox.size() / 2;
182  for (int ii = 0; ii < (dimension * 2); ii += 2 )
183  {
184  if ((*mapIt).second.m_BoundingBox[ii] > (*threadIt).second.m_BoundingBox[ii])
185  {
186  (*mapIt).second.m_BoundingBox[ii] = (*threadIt).second.m_BoundingBox[ii];
187  }
188  if ((*mapIt).second.m_BoundingBox[ii + 1] < (*threadIt).second.m_BoundingBox[ii + 1])
189  {
190  (*mapIt).second.m_BoundingBox[ii + 1] = (*threadIt).second.m_BoundingBox[ii + 1];
191  }
192  }
193 
194  // if enabled, update the histogram for this label
195  if (m_UseHistograms)
196  {
197  typename HistogramType::IndexType index;
198 #ifdef ITK_USE_REVIEW_STATISTICS
199  index.SetSize(1);
200 #endif
201  for (unsigned int bin=0; bin<m_NumBins[0]; bin++)
202  {
203  index[0] = bin;
204  (*mapIt).second.m_Histogram->IncreaseFrequency(bin, (*threadIt).second.m_Histogram->GetFrequency(bin));
205  }
206  }
207  } // end of thread map iterator loop
208  } // end of thread loop
209 
210  // compute the remainder of the statistics
211  for (mapIt = m_LabelStatistics.begin();
212  mapIt != m_LabelStatistics.end();
213  ++mapIt)
214  {
215  // mean
216  (*mapIt).second.m_Mean = (*mapIt).second.m_Sum /
217  static_cast<RealType>( (*mapIt).second.m_Count );
218 
219 
220  // variance
221  if ((*mapIt).second.m_Count > 1)
222  {
223  // unbiased estimate of variance
224  LabelStatistics & ls = mapIt->second;
225  const RealType sumSquared = ls.m_Sum * ls.m_Sum;
226  const RealType count = static_cast< RealType >( ls.m_Count );
227 
228  ls.m_Variance = ( ls.m_SumOfSquares - sumSquared / count ) / ( count - 1.0 );
229  }
230  else
231  {
232  (*mapIt).second.m_Variance = NumericTraits<RealType>::Zero;
233  }
234 
235  // sigma
236  (*mapIt).second.m_Sigma = vcl_sqrt((*mapIt).second.m_Variance);
237  }
238 
239 }
240 
241 template<class TInputImage, class TLabelImage>
242 void
244 ::ThreadedGenerateData(const RegionType& outputRegionForThread,
245  int threadId)
246 {
247  RealType value;
248  LabelPixelType label;
250  outputRegionForThread);
251  ImageRegionConstIterator<TLabelImage> labelIt (this->GetLabelInput(),
252  outputRegionForThread);
253  MapIterator mapIt;
254 
255  // support progress methods/callbacks
256  ProgressReporter progress(this, threadId,
257  outputRegionForThread.GetNumberOfPixels());
258 
259  // do the work
260  while (!it.IsAtEnd())
261  {
262  value = static_cast<RealType>(it.Get());
263  label = labelIt.Get();
264 
265  // is the label already in this thread?
266  mapIt = m_LabelStatisticsPerThread[threadId].find( label );
267  if (mapIt == m_LabelStatisticsPerThread[threadId].end())
268  {
269  // create a new statistics object
270  typedef typename MapType::value_type MapValueType;
271  LOCK_HASHMAP;
272  if (m_UseHistograms)
273  {
274  mapIt = m_LabelStatisticsPerThread[threadId].insert( MapValueType(label,
275  LabelStatistics(m_NumBins[0], m_LowerBound, m_UpperBound)) ).first;
276  }
277  else
278  {
279  mapIt = m_LabelStatisticsPerThread[threadId].insert( MapValueType(label,
280  LabelStatistics()) ).first;
281  }
283  }
284 
285  // update the values for this label and this thread
286  if (value < (*mapIt).second.m_Minimum)
287  {
288  (*mapIt).second.m_Minimum = value;
289  }
290  if (value > (*mapIt).second.m_Maximum)
291  {
292  (*mapIt).second.m_Maximum = value;
293  }
294 
295  // bounding box is min,max pairs
296  for( unsigned int i = 0; i < ( 2 * it.GetImageDimension()); i += 2 )
297  {
299  if ((*mapIt).second.m_BoundingBox[i] > index[i/2])
300  {
301  (*mapIt).second.m_BoundingBox[i] = index[i/2];
302  }
303  if ((*mapIt).second.m_BoundingBox[i + 1] < index[i/2])
304  {
305  (*mapIt).second.m_BoundingBox[i + 1] = index[i/2];
306  }
307  }
308 
309  (*mapIt).second.m_Sum += value;
310  (*mapIt).second.m_SumOfSquares += (value * value);
311  (*mapIt).second.m_Count++;
312 
313  // if enabled, update the histogram for this label
314  if (m_UseHistograms)
315  {
317 #ifdef ITK_USE_REVIEW_STATISTICS
318  meas.SetSize(1);
319 #endif
320  meas[0] = value;
321 #ifdef ITK_USE_REVIEW_STATISTICS
322  (*mapIt).second.m_Histogram->IncreaseFrequency(meas, 1);
323 #else
324  (*mapIt).second.m_Histogram->IncreaseFrequency(meas, 1.0F);
325 #endif
326  }
327 
328  ++it;
329  ++labelIt;
330  progress.CompletedPixel();
331  }
332 }
333 
334 template<class TInputImage, class TLabelImage>
338 {
339  MapConstIterator mapIt;
340  mapIt = m_LabelStatistics.find( label );
341  if ( mapIt == m_LabelStatistics.end() )
342  {
343  // label does not exist, return a default value
344  return NumericTraits<PixelType>::max();
345  }
346  else
347  {
348  return (*mapIt).second.m_Minimum;
349  }
350 }
351 
352 template<class TInputImage, class TLabelImage>
356 {
357  MapConstIterator mapIt;
358  mapIt = m_LabelStatistics.find( label );
359  if ( mapIt == m_LabelStatistics.end() )
360  {
361  // label does not exist, return a default value
362  return NumericTraits<PixelType>::NonpositiveMin();
363  }
364  else
365  {
366  return (*mapIt).second.m_Maximum;
367  }
368 }
369 
370 template<class TInputImage, class TLabelImage>
374 {
375  MapConstIterator mapIt;
376  mapIt = m_LabelStatistics.find( label );
377  if ( mapIt == m_LabelStatistics.end() )
378  {
379  // label does not exist, return a default value
380  return NumericTraits<PixelType>::Zero;
381  }
382  else
383  {
384  return (*mapIt).second.m_Mean;
385  }
386 }
387 
388 template<class TInputImage, class TLabelImage>
392 {
393  MapConstIterator mapIt;
394  mapIt = m_LabelStatistics.find( label );
395  if ( mapIt == m_LabelStatistics.end() )
396  {
397  // label does not exist, return a default value
398  return NumericTraits<PixelType>::Zero;
399  }
400  else
401  {
402  return (*mapIt).second.m_Sum;
403  }
404 }
405 
406 template<class TInputImage, class TLabelImage>
410 {
411  MapConstIterator mapIt;
412  mapIt = m_LabelStatistics.find( label );
413  if ( mapIt == m_LabelStatistics.end() )
414  {
415  // label does not exist, return a default value
416  return NumericTraits<PixelType>::Zero;
417  }
418  else
419  {
420  return (*mapIt).second.m_Sigma;
421  }
422 }
423 
424 template<class TInputImage, class TLabelImage>
428 {
429  MapConstIterator mapIt;
430  mapIt = m_LabelStatistics.find( label );
431  if ( mapIt == m_LabelStatistics.end() )
432  {
433  // label does not exist, return a default value
434  return NumericTraits<PixelType>::Zero;
435  }
436  else
437  {
438  return (*mapIt).second.m_Variance;
439  }
440 }
441 
442 template<class TInputImage, class TLabelImage>
446 {
447 
448  MapConstIterator mapIt;
449  mapIt = m_LabelStatistics.find( label );
450  if ( mapIt == m_LabelStatistics.end() )
451  {
452  BoundingBoxType emptyBox;
453  // label does not exist, return a default value
454  return emptyBox;
455  }
456  else
457  {
458  return (*mapIt).second.m_BoundingBox;
459  }
460 }
461 
462 template<class TInputImage, class TLabelImage>
466 {
467  MapConstIterator mapIt;
468  mapIt = m_LabelStatistics.find( label );
469 
470  if ( mapIt == m_LabelStatistics.end() )
471  {
472  RegionType emptyRegion;
473  // label does not exist, return a default value
474  return emptyRegion;
475  }
476  else
477  {
478  BoundingBoxType bbox = this->GetBoundingBox( label );
479  IndexType index;
480  SizeType size;
481 
482  unsigned int dimension = bbox.size() / 2;
483 
484  for (unsigned int i = 0; i < dimension; i++)
485  {
486  index[i] = bbox[2*i];
487  size[i] = bbox[2*i+1] - bbox[2*i] + 1;
488  }
489  RegionType region;
490  region.SetSize(size);
491  region.SetIndex(index);
492 
493  return region;
494  }
495 }
496 
497 template<class TInputImage, class TLabelImage>
498 unsigned long
501 {
502  MapConstIterator mapIt;
503  mapIt = m_LabelStatistics.find( label );
504  if ( mapIt == m_LabelStatistics.end() )
505  {
506  // label does not exist, return a default value
507  return 0;
508  }
509  else
510  {
511  return (*mapIt).second.m_Count;
512  }
513 }
514 
515 template<class TInputImage, class TLabelImage>
519 {
520  RealType median = 0.0;
521  MapConstIterator mapIt;
522  mapIt = m_LabelStatistics.find( label );
523  if ( mapIt == m_LabelStatistics.end() || !m_UseHistograms)
524  {
525  // label does not exist OR histograms not enabled, return a default value
526  return median;
527  }
528  else
529  {
530 
531 #ifdef ITK_USE_REVIEW_STATISTICS
532  typename HistogramType::SizeValueType bin = 0;
533 #else
535 #endif
536 
537  typename HistogramType::IndexType index;
538 #ifdef ITK_USE_REVIEW_STATISTICS
539  index.SetSize(1);
540 #endif
541  RealType total = 0;
542 
543  // count bins until just over half the distribution is counted
544  while (total <= ((*mapIt).second.m_Count/ 2) && (bin < m_NumBins[0]))
545  {
546  index[0] = bin;
547  total += (*mapIt).second.m_Histogram->GetFrequency(index);
548  bin++;
549  }
550  bin--;
551  index[0] = bin;
552 
553  // return center of bin range
554  RealType lowRange = (*mapIt).second.m_Histogram->GetBinMin(0, bin);
555  RealType highRange = (*mapIt).second.m_Histogram->GetBinMax(0, bin);
556  median = lowRange + (highRange - lowRange) / 2;
557  return median;
558  }
559 }
560 
561 template<class TInputImage, class TLabelImage>
565 {
566  MapConstIterator mapIt;
567  mapIt = m_LabelStatistics.find( label );
568  if ( mapIt == m_LabelStatistics.end())
569  {
570  // label does not exist, return a default value
571  return 0;
572  }
573  else
574  {
575  // this will be zero if histograms have not been enabled
576  return (*mapIt).second.m_Histogram;
577  }
578 }
579 
580 template <class TImage, class TLabelImage>
581 void
583 ::PrintSelf(std::ostream& os, Indent indent) const
584 {
585  Superclass::PrintSelf(os,indent);
586 
587  os << indent << "Number of labels: " << m_LabelStatistics.size()
588  << std::endl;
589  os << indent << "Use Histograms: " << m_UseHistograms
590  << std::endl;
591  os << indent << "Histogram Lower Bound: " << m_LowerBound
592  << std::endl;
593  os << indent << "Histogram Upper Bound: " << m_UpperBound
594  << std::endl;
595 }
596 
597 
598 }// end namespace itk
599 #endif

Generated at Sat Feb 2 2013 23:50:17 for Orfeo Toolbox with doxygen 1.8.1.1