17 #ifndef __itkLabelStatisticsImageFilter_txx
18 #define __itkLabelStatisticsImageFilter_txx
24 #include "itkNumericTraits.h"
28 #if defined(__GNUC__) && (__GNUC__ <= 2) //NOTE: This class needs a mutex for gnu 2.95
30 #define LOCK_HASHMAP this->m_Mutex.Lock()
31 #define UNLOCK_HASHMAP this->m_Mutex.Unlock()
34 #define UNLOCK_HASHMAP
37 template<
class TInputImage,
class TLabelImage>
41 this->SetNumberOfRequiredInputs(2);
42 m_UseHistograms =
false;
43 #ifdef ITK_USE_REVIEW_STATISTICS
47 m_LowerBound =
static_cast<RealType>( NumericTraits<PixelType>::NonpositiveMin() );
48 m_UpperBound =
static_cast<RealType>( NumericTraits<PixelType>::max() );
52 template<
class TInputImage,
class TLabelImage>
57 Superclass::GenerateInputRequestedRegion();
58 if ( this->GetInput() )
64 image->SetRequestedRegionToLargestPossibleRegion();
67 if ( this->GetLabelInput() )
70 const_cast< TLabelImage *
>( this->GetLabelInput() );
71 label->SetRequestedRegionToLargestPossibleRegion();
75 template<
class TInputImage,
class TLabelImage>
80 Superclass::EnlargeOutputRequestedRegion(data);
85 template<
class TInputImage,
class TLabelImage>
92 const_cast< TInputImage *
>( this->GetInput() );
93 this->GraftOutput( image );
98 template<
class TInputImage,
class TLabelImage>
103 m_NumBins[0] = numBins;
104 m_LowerBound = lowerBound;
105 m_UpperBound = upperBound;
106 m_UseHistograms =
true;
109 template<
class TInputImage,
class TLabelImage>
114 int numberOfThreads = this->GetNumberOfThreads();
117 m_LabelStatisticsPerThread.resize(numberOfThreads);
120 for (
int i=0; i < numberOfThreads; ++i)
122 m_LabelStatisticsPerThread[i].clear();
126 m_LabelStatistics.clear();
129 template<
class TInputImage,
class TLabelImage>
137 int numberOfThreads = this->GetNumberOfThreads();
141 for (i = 0; i < numberOfThreads; i++)
144 for (threadIt = m_LabelStatisticsPerThread[i].begin();
145 threadIt != m_LabelStatisticsPerThread[i].end();
149 mapIt = m_LabelStatistics.find( (*threadIt).first );
150 if (mapIt == m_LabelStatistics.end())
156 mapIt = m_LabelStatistics.insert( MapValueType((*threadIt).first,
161 mapIt = m_LabelStatistics.insert( MapValueType((*threadIt).first,
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;
171 if ((*mapIt).second.m_Minimum > (*threadIt).second.m_Minimum)
173 (*mapIt).second.m_Minimum = (*threadIt).second.m_Minimum;
175 if ((*mapIt).second.m_Maximum < (*threadIt).second.m_Maximum)
177 (*mapIt).second.m_Maximum = (*threadIt).second.m_Maximum;
181 int dimension = (*mapIt).second.m_BoundingBox.size() / 2;
182 for (
int ii = 0; ii < (dimension * 2); ii += 2 )
184 if ((*mapIt).second.m_BoundingBox[ii] > (*threadIt).second.m_BoundingBox[ii])
186 (*mapIt).second.m_BoundingBox[ii] = (*threadIt).second.m_BoundingBox[ii];
188 if ((*mapIt).second.m_BoundingBox[ii + 1] < (*threadIt).second.m_BoundingBox[ii + 1])
190 (*mapIt).second.m_BoundingBox[ii + 1] = (*threadIt).second.m_BoundingBox[ii + 1];
198 #ifdef ITK_USE_REVIEW_STATISTICS
201 for (
unsigned int bin=0; bin<m_NumBins[0]; bin++)
204 (*mapIt).second.m_Histogram->IncreaseFrequency(bin, (*threadIt).second.m_Histogram->GetFrequency(bin));
211 for (mapIt = m_LabelStatistics.begin();
212 mapIt != m_LabelStatistics.end();
216 (*mapIt).second.m_Mean = (*mapIt).second.m_Sum /
217 static_cast<RealType>( (*mapIt).second.m_Count );
221 if ((*mapIt).second.m_Count > 1)
232 (*mapIt).second.m_Variance = NumericTraits<RealType>::Zero;
236 (*mapIt).second.m_Sigma = vcl_sqrt((*mapIt).second.m_Variance);
241 template<
class TInputImage,
class TLabelImage>
250 outputRegionForThread);
252 outputRegionForThread);
257 outputRegionForThread.GetNumberOfPixels());
263 label = labelIt.
Get();
266 mapIt = m_LabelStatisticsPerThread[threadId].find( label );
267 if (mapIt == m_LabelStatisticsPerThread[threadId].end())
274 mapIt = m_LabelStatisticsPerThread[threadId].insert( MapValueType(label,
279 mapIt = m_LabelStatisticsPerThread[threadId].insert( MapValueType(label,
286 if (value < (*mapIt).second.m_Minimum)
288 (*mapIt).second.m_Minimum = value;
290 if (value > (*mapIt).second.m_Maximum)
292 (*mapIt).second.m_Maximum = value;
299 if ((*mapIt).second.m_BoundingBox[i] > index[i/2])
301 (*mapIt).second.m_BoundingBox[i] = index[i/2];
303 if ((*mapIt).second.m_BoundingBox[i + 1] < index[i/2])
305 (*mapIt).second.m_BoundingBox[i + 1] = index[i/2];
309 (*mapIt).second.m_Sum += value;
310 (*mapIt).second.m_SumOfSquares += (value * value);
311 (*mapIt).second.m_Count++;
317 #ifdef ITK_USE_REVIEW_STATISTICS
321 #ifdef ITK_USE_REVIEW_STATISTICS
322 (*mapIt).second.m_Histogram->IncreaseFrequency(meas, 1);
324 (*mapIt).second.m_Histogram->IncreaseFrequency(meas, 1.0F);
330 progress.CompletedPixel();
334 template<
class TInputImage,
class TLabelImage>
340 mapIt = m_LabelStatistics.find( label );
341 if ( mapIt == m_LabelStatistics.end() )
344 return NumericTraits<PixelType>::max();
348 return (*mapIt).second.m_Minimum;
352 template<
class TInputImage,
class TLabelImage>
358 mapIt = m_LabelStatistics.find( label );
359 if ( mapIt == m_LabelStatistics.end() )
362 return NumericTraits<PixelType>::NonpositiveMin();
366 return (*mapIt).second.m_Maximum;
370 template<
class TInputImage,
class TLabelImage>
376 mapIt = m_LabelStatistics.find( label );
377 if ( mapIt == m_LabelStatistics.end() )
380 return NumericTraits<PixelType>::Zero;
384 return (*mapIt).second.m_Mean;
388 template<
class TInputImage,
class TLabelImage>
394 mapIt = m_LabelStatistics.find( label );
395 if ( mapIt == m_LabelStatistics.end() )
398 return NumericTraits<PixelType>::Zero;
402 return (*mapIt).second.m_Sum;
406 template<
class TInputImage,
class TLabelImage>
412 mapIt = m_LabelStatistics.find( label );
413 if ( mapIt == m_LabelStatistics.end() )
416 return NumericTraits<PixelType>::Zero;
420 return (*mapIt).second.m_Sigma;
424 template<
class TInputImage,
class TLabelImage>
430 mapIt = m_LabelStatistics.find( label );
431 if ( mapIt == m_LabelStatistics.end() )
434 return NumericTraits<PixelType>::Zero;
438 return (*mapIt).second.m_Variance;
442 template<
class TInputImage,
class TLabelImage>
449 mapIt = m_LabelStatistics.find( label );
450 if ( mapIt == m_LabelStatistics.end() )
458 return (*mapIt).second.m_BoundingBox;
462 template<
class TInputImage,
class TLabelImage>
468 mapIt = m_LabelStatistics.find( label );
470 if ( mapIt == m_LabelStatistics.end() )
482 unsigned int dimension = bbox.size() / 2;
484 for (
unsigned int i = 0; i < dimension; i++)
486 index[i] = bbox[2*i];
487 size[i] = bbox[2*i+1] - bbox[2*i] + 1;
490 region.SetSize(size);
491 region.SetIndex(index);
497 template<
class TInputImage,
class TLabelImage>
503 mapIt = m_LabelStatistics.find( label );
504 if ( mapIt == m_LabelStatistics.end() )
511 return (*mapIt).second.m_Count;
515 template<
class TInputImage,
class TLabelImage>
522 mapIt = m_LabelStatistics.find( label );
523 if ( mapIt == m_LabelStatistics.end() || !m_UseHistograms)
531 #ifdef ITK_USE_REVIEW_STATISTICS
538 #ifdef ITK_USE_REVIEW_STATISTICS
544 while (total <= ((*mapIt).second.m_Count/ 2) && (bin < m_NumBins[0]))
547 total += (*mapIt).second.m_Histogram->GetFrequency(index);
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;
561 template<
class TInputImage,
class TLabelImage>
567 mapIt = m_LabelStatistics.find( label );
568 if ( mapIt == m_LabelStatistics.end())
576 return (*mapIt).second.m_Histogram;
580 template <
class TImage,
class TLabelImage>
585 Superclass::PrintSelf(os,indent);
587 os << indent <<
"Number of labels: " << m_LabelStatistics.size()
589 os << indent <<
"Use Histograms: " << m_UseHistograms
591 os << indent <<
"Histogram Lower Bound: " << m_LowerBound
593 os << indent <<
"Histogram Upper Bound: " << m_UpperBound