diff --git a/Modules/ImageStatistics/mitkStatisticsImageFilter.hxx b/Modules/ImageStatistics/mitkStatisticsImageFilter.hxx index 215f8983d7..b0ea7f5486 100644 --- a/Modules/ImageStatistics/mitkStatisticsImageFilter.hxx +++ b/Modules/ImageStatistics/mitkStatisticsImageFilter.hxx @@ -1,323 +1,325 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkStatisticsImageFilter_hxx #define mitkStatisticsImageFilter_hxx #include +#include #include template mitk::StatisticsImageFilter::StatisticsImageFilter() : m_CalculateHistogram(false), m_HistogramSize(0), m_HistogramLowerBound(itk::NumericTraits::NonpositiveMin()), m_HistogramUpperBound(itk::NumericTraits::max()), m_Sum(1), m_SumOfPositivePixels(1), m_SumOfSquares(1), m_SumOfCubes(1), m_SumOfQuadruples(1), m_Count(1), m_CountOfPositivePixels(1), m_Min(1), m_Max(1) { this->SetNumberOfRequiredInputs(1); this->SetMinimum(itk::NumericTraits::max()); this->SetMaximum(itk::NumericTraits::NonpositiveMin()); this->SetMean(itk::NumericTraits::max()); this->SetSigma(itk::NumericTraits::max()); this->SetVariance(itk::NumericTraits::max()); this->SetSum(0); this->SetSumOfSquares(0); this->SetSumOfCubes(0); this->SetSumOfQuadruples(0); this->SetSkewness(0); this->SetKurtosis(0); this->SetMPP(0); this->SetEntropy(-1.0); this->SetUniformity(0); this->SetUPP(0); this->SetMedian(0); } template mitk::StatisticsImageFilter::~StatisticsImageFilter() { } template typename mitk::StatisticsImageFilter::DataObjectPointer mitk::StatisticsImageFilter::MakeOutput(const DataObjectIdentifierType& name) { if (name == "Minimum" || name == "Maximum") { return PixelObjectType::New(); } if (name == "Mean" || name == "Sigma" || name == "Variance" || name == "Sum" || name == "SumOfSquares" || name == "SumOfCubes" || name == "SumOfQuadruples" || name == "Skewness" || name == "Kurtosis" || name == "MPP" || name == "Entropy" || name == "Uniformity" || name == "UPP" || name == "Median") { return RealObjectType::New(); } if (name == "Histogram") { return HistogramType::New(); } return Superclass::MakeOutput(name); } template void mitk::StatisticsImageFilter::SetHistogramParameters(unsigned int size, RealType lowerBound, RealType upperBound) { bool modified = false; if (m_HistogramSize != size) { m_HistogramSize = size; modified = true; } if (m_HistogramLowerBound != lowerBound) { m_HistogramLowerBound = lowerBound; modified = true; } if (m_HistogramUpperBound != upperBound) { m_HistogramUpperBound = upperBound; modified = true; } m_CalculateHistogram = true; if (modified) this->Modified(); } template auto mitk::StatisticsImageFilter::CreateInitializedHistogram() const -> HistogramPointer { typename HistogramType::SizeType size; size.SetSize(1); - size[0] = m_HistogramSize; + size.Fill(m_HistogramSize); typename HistogramType::MeasurementVectorType lowerBound; lowerBound.SetSize(1); - lowerBound[0] = m_HistogramLowerBound; + lowerBound.Fill(m_HistogramLowerBound); typename HistogramType::MeasurementVectorType upperBound; upperBound.SetSize(1); - upperBound.[0] = m_HistogramUpperBound; + upperBound.Fill(m_HistogramUpperBound); auto histogram = HistogramType::New(); + histogram->SetMeasurementVectorSize(1); histogram->Initialize(size, lowerBound, upperBound); return histogram; } template void mitk::StatisticsImageFilter::BeforeStreamedGenerateData() { Superclass::BeforeStreamedGenerateData(); m_Sum = 0; m_SumOfPositivePixels = 0; m_SumOfSquares = 0; m_SumOfCubes = 0; m_SumOfQuadruples = 0; m_Count = 0; m_CountOfPositivePixels = 0; m_Min = itk::NumericTraits::max(); m_Max = itk::NumericTraits::NonpositiveMin(); if (m_CalculateHistogram) m_Histogram = this->CreateInitializedHistogram(); } template void mitk::StatisticsImageFilter::ThreadedStreamedGenerateData(const RegionType& regionForThread) { itk::CompensatedSummation sum = 0; itk::CompensatedSummation sumOfPositivePixels = 0; itk::CompensatedSummation sumOfSquares = 0; itk::CompensatedSummation sumOfCubes = 0; itk::CompensatedSummation sumOfQuadruples = 0; itk::SizeValueType count = 0; itk::SizeValueType countOfPositivePixels = 0; auto min = itk::NumericTraits::max(); auto max = itk::NumericTraits::NonpositiveMin(); RealType realValue = 0; RealType squareValue = 0; HistogramPointer histogram; typename HistogramType::MeasurementVectorType histogramMeasurement; typename HistogramType::IndexType histogramIndex; if (m_CalculateHistogram) // Initialize histogram { histogram = this->CreateInitializedHistogram(); histogramMeasurement.SetSize(1); } itk::ImageScanlineConstIterator it(this->GetInput(), regionForThread); while (!it.IsAtEnd()) { while (!it.IsAtEndOfLine()) { const auto& value = it.Get(); realValue = static_cast(value); if (m_CalculateHistogram) // Compute histogram { histogramMeasurement[0] = realValue; histogram->GetIndex(histogramMeasurement, histogramIndex); histogram->IncreaseFrequencyOfIndex(histogramIndex, 1); } min = std::min(min, value); max = std::max(max, value); squareValue = realValue * realValue; sum += realValue; sumOfSquares += squareValue; sumOfCubes += squareValue * realValue; sumOfQuadruples += squareValue * squareValue; ++count; if (0 < realValue) { sumOfPositivePixels += realValue; ++countOfPositivePixels; } ++it; } it.NextLine(); } std::lock_guard mutexHolder(m_Mutex); if (m_CalculateHistogram) // Merge histograms { typename HistogramType::ConstIterator histogramIt = histogram->Begin(); typename HistogramType::ConstIterator histogramEnd = histogram->End(); while (histogramIt != histogramEnd) { m_Histogram->GetIndex(histogramIt.GetMeasurementVector(), histogramIndex); m_Histogram->IncreaseFrequencyOfIndex(histogramIndex, histogramIt.GetFrequency()); ++histogramIt; } } m_Sum += sum; m_SumOfPositivePixels += sumOfPositivePixels; m_SumOfSquares += sumOfSquares; m_SumOfCubes += sumOfCubes; m_SumOfQuadruples += sumOfQuadruples; m_Count += count; m_CountOfPositivePixels += countOfPositivePixels; m_Min = std::min(min, m_Min); m_Max = std::max(max, m_Max); } template void mitk::StatisticsImageFilter::AfterStreamedGenerateData() { Superclass::AfterStreamedGenerateData(); const RealType sum = m_Sum.GetSum(); const RealType sumOfPositivePixels = m_SumOfPositivePixels.GetSum(); const RealType sumOfSquares = m_SumOfSquares.GetSum(); const RealType sumOfCubes = m_SumOfCubes.GetSum(); const RealType sumOfQuadruples = m_SumOfQuadruples.GetSum(); const itk::SizeValueType count = m_Count; const itk::SizeValueType countOfPositivePixels = m_CountOfPositivePixels; const PixelType minimum = m_Min; const PixelType maximum = m_Max; const RealType mean = sum / static_cast(count); const RealType variance = (sumOfSquares - (sum * sum / static_cast(count))) / (static_cast(count) - 1); const RealType sigma = std::sqrt(variance); const RealType secondMoment = sumOfSquares / static_cast(count); const RealType thirdMoment = sumOfCubes / static_cast(count); const RealType fourthMoment = sumOfQuadruples / static_cast(count); const RealType skewness = (thirdMoment - 3 * secondMoment * mean + 2 * std::pow(mean, 3)) / std::pow(secondMoment - std::pow(mean, 2), 1.5); const RealType kurtosis = (fourthMoment - 4 * thirdMoment * mean + 6 * secondMoment * std::pow(mean, 2) - 3 * std::pow(mean, 4)) / std::pow(secondMoment - std::pow(mean, 2), 2); const RealType meanOfPositivePixels = sumOfPositivePixels / static_cast(countOfPositivePixels); this->SetMinimum(minimum); this->SetMaximum(maximum); this->SetMean(mean); this->SetSigma(sigma); this->SetVariance(variance); this->SetSum(sum); this->SetSumOfSquares(sumOfSquares); this->SetSumOfCubes(sumOfCubes); this->SetSumOfQuadruples(sumOfQuadruples); this->SetSkewness(skewness); this->SetKurtosis(kurtosis); this->SetMPP(meanOfPositivePixels); if (m_CalculateHistogram) { this->SetHistogram(m_Histogram); mitk::HistogramStatisticsCalculator histogramStatisticsCalculator; histogramStatisticsCalculator.SetHistogram(m_Histogram); histogramStatisticsCalculator.CalculateStatistics(); this->SetEntropy(histogramStatisticsCalculator.GetEntropy()); this->SetUniformity(histogramStatisticsCalculator.GetUniformity()); this->SetUPP(histogramStatisticsCalculator.GetUPP()); this->SetMedian(histogramStatisticsCalculator.GetMedian()); } } template void mitk::StatisticsImageFilter::PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "SumOfCubes: " << this->GetSumOfCubes() << std::endl; os << indent << "SumOfQuadruples: " << this->GetSumOfQuadruples() << std::endl; os << indent << "Skewness: " << this->GetSkewness() << std::endl; os << indent << "Kurtosis: " << this->GetKurtosis() << std::endl; os << indent << "MPP: " << this->GetMPP() << std::endl; os << indent << "Entropy: " << this->GetEntropy() << std::endl; os << indent << "Uniformity: " << this->GetUniformity() << std::endl; os << indent << "UPP: " << this->GetUPP() << std::endl; os << indent << "Median: " << this->GetMedian() << std::endl; } #endif