5 #include <itkImageToHistogramFilter.h>
6 #include <itkMaskedImageToHistogramFilter.h>
7 #include <itkHistogram.h>
8 #include <itkExtractImageFilter.h>
9 #include <itkImageRegionConstIterator.h>
10 #include <itkChangeInformationImageFilter.h>
11 #include <itkMinimumMaximumImageCalculator.h>
12 #include <itkMinimumMaximumImageFilter.h>
13 #include <itkMaskImageFilter.h>
14 #include <itkExceptionObject.h>
33 #include "itkImageFileWriter.h"
43 m_StatisticsByTimeStep.resize(m_Image->GetTimeSteps());
44 m_StatisticsUpdateTimePerTimeStep.resize(m_Image->GetTimeSteps());
45 std::fill(m_StatisticsUpdateTimePerTimeStep.begin(), m_StatisticsUpdateTimePerTimeStep.end(), 0);
53 if (mask != m_MaskGenerator)
55 m_MaskGenerator = mask;
64 if (mask != m_SecondaryMaskGenerator)
66 m_SecondaryMaskGenerator = mask;
75 if (nBins != m_nBinsForHistogramStatistics)
77 m_nBinsForHistogramStatistics = nBins;
79 this->m_UseBinSizeOverNBins =
false;
81 if (m_UseBinSizeOverNBins)
84 this->m_UseBinSizeOverNBins =
false;
90 return m_nBinsForHistogramStatistics;
95 if (binSize != m_binSizeForHistogramStatistics)
97 m_binSizeForHistogramStatistics = binSize;
99 this->m_UseBinSizeOverNBins =
true;
101 if (!m_UseBinSizeOverNBins)
104 this->m_UseBinSizeOverNBins =
true;
110 return m_binSizeForHistogramStatistics;
116 if (timeStep >= m_StatisticsByTimeStep.size())
118 mitkThrow() <<
"invalid timeStep in ImageStatisticsCalculator_v2::GetStatistics";
121 if (m_Image.IsNull())
126 if (!m_Image->IsInitialized())
131 if (IsUpdateRequired(timeStep))
133 if (m_MaskGenerator.IsNotNull())
135 m_MaskGenerator->SetTimeStep(timeStep);
136 m_InternalMask = m_MaskGenerator->GetMask();
137 if (m_MaskGenerator->GetReferenceImage().IsNotNull())
139 m_InternalImageForStatistics = m_MaskGenerator->GetReferenceImage();
143 m_InternalImageForStatistics = m_Image;
148 m_InternalImageForStatistics = m_Image;
151 if (m_SecondaryMaskGenerator.IsNotNull())
153 m_SecondaryMaskGenerator->SetTimeStep(timeStep);
154 m_SecondaryMask = m_SecondaryMaskGenerator->GetMask();
158 imgTimeSel->SetInput(m_InternalImageForStatistics);
159 imgTimeSel->SetTimeNr(timeStep);
160 imgTimeSel->UpdateLargestPossibleRegion();
161 m_ImageTimeSlice = imgTimeSel->GetOutput();
165 if (m_MaskGenerator.IsNull() && m_SecondaryMaskGenerator.IsNull())
168 AccessByItk_1(m_ImageTimeSlice, InternalCalculateStatisticsUnmasked, timeStep)
174 AccessByItk_1(m_ImageTimeSlice, InternalCalculateStatisticsMasked, timeStep)
181 m_StatisticsUpdateTimePerTimeStep[timeStep] = m_StatisticsByTimeStep[timeStep][m_StatisticsByTimeStep[timeStep].size()-1]->GetMTime();
183 for (std::vector<StatisticsContainer::Pointer>::iterator it = m_StatisticsByTimeStep[timeStep].begin(); it != m_StatisticsByTimeStep[timeStep].end(); ++it)
186 if (statCont->GetLabel() == label)
188 return statCont->Clone();
193 MITK_WARN <<
"Invalid label: " << label <<
" in time step: " << timeStep;
197 template <
typename TPixel,
unsigned int VImageDimension >
void ImageStatisticsCalculator::InternalCalculateStatisticsUnmasked(
198 typename itk::Image< TPixel, VImageDimension >* image,
unsigned int timeStep)
200 typedef typename itk::Image< TPixel, VImageDimension >
ImageType;
207 statisticsFilter->SetInput(image);
208 statisticsFilter->SetCoordinateTolerance(0.001);
209 statisticsFilter->SetDirectionTolerance(0.001);
215 vnl_vector<int> minIndex, maxIndex;
218 minMaxFilter->SetInput(image);
219 minMaxFilter->UpdateLargestPossibleRegion();
223 typename ImageType::IndexType tmpMinIndex = minMaxFilter->GetMinIndex();
224 typename ImageType::IndexType tmpMaxIndex = minMaxFilter->GetMaxIndex();
229 minIndex.set_size(tmpMaxIndex.GetIndexDimension());
230 maxIndex.set_size(tmpMaxIndex.GetIndexDimension());
232 for (
unsigned int i=0; i < tmpMaxIndex.GetIndexDimension(); i++)
234 minIndex[i] = tmpMinIndex[i];
235 maxIndex[i] = tmpMaxIndex[i];
238 statisticsResult->SetMinIndex(minIndex);
239 statisticsResult->SetMaxIndex(maxIndex);
242 unsigned int nBinsForHistogram;
243 if (m_UseBinSizeOverNBins)
245 nBinsForHistogram =
std::max(static_cast<double>(std::ceil(maxval - minval)) / m_binSizeForHistogramStatistics, 10.);
249 nBinsForHistogram = m_nBinsForHistogramStatistics;
252 statisticsFilter->SetHistogramParameters(nBinsForHistogram, minval, maxval);
256 statisticsFilter->Update();
258 catch (
const itk::ExceptionObject& e)
260 mitkThrow() <<
"Image statistics calculation failed due to following ITK Exception: \n " << e.what();
264 m_StatisticsByTimeStep[timeStep].resize(1);
265 statisticsResult->SetLabel(1);
266 statisticsResult->SetN(image->GetLargestPossibleRegion().GetNumberOfPixels());
267 statisticsResult->SetMean(statisticsFilter->GetMean());
268 statisticsResult->SetMin(statisticsFilter->GetMinimum());
269 statisticsResult->SetMax(statisticsFilter->GetMaximum());
270 statisticsResult->SetVariance(statisticsFilter->GetVariance());
271 statisticsResult->SetStd(statisticsFilter->GetSigma());
272 statisticsResult->SetSkewness(statisticsFilter->GetSkewness());
273 statisticsResult->SetKurtosis(statisticsFilter->GetKurtosis());
274 statisticsResult->SetRMS(std::sqrt(std::pow(statisticsFilter->GetMean(), 2.) + statisticsFilter->GetVariance()));
275 statisticsResult->SetMPP(statisticsFilter->GetMPP());
277 statisticsResult->SetEntropy(statisticsFilter->GetEntropy());
278 statisticsResult->SetMedian(statisticsFilter->GetMedian());
279 statisticsResult->SetUniformity(statisticsFilter->GetUniformity());
280 statisticsResult->SetUPP(statisticsFilter->GetUPP());
281 statisticsResult->SetHistogram(statisticsFilter->GetHistogram());
283 m_StatisticsByTimeStep[timeStep][0] = statisticsResult;
287 template <
typename TPixel,
unsigned int VImageDimension >
void ImageStatisticsCalculator::InternalCalculateStatisticsMasked(
288 typename itk::Image< TPixel, VImageDimension >* image,
289 unsigned int timeStep)
291 typedef itk::Image< TPixel, VImageDimension >
ImageType;
292 typedef itk::Image< MaskPixelType, VImageDimension > MaskType;
295 typedef MaskUtilities< TPixel, VImageDimension > MaskUtilType;
301 bool swapMasks =
false;
302 if (m_SecondaryMask.IsNotNull() && m_InternalMask.IsNull())
304 m_InternalMask = m_SecondaryMask;
305 m_SecondaryMask =
nullptr;
313 maskImage = ImageToItkImage< MaskPixelType, VImageDimension >(m_InternalMask);
315 catch (itk::ExceptionObject & e)
323 if (m_SecondaryMask.IsNotNull())
326 if (m_InternalMask->GetDimension() == 2 && (m_SecondaryMask->GetDimension() == 3 || m_SecondaryMask->GetDimension() == 4))
329 m_SecondaryMaskGenerator->SetInputImage(m_MaskGenerator->GetReferenceImage());
330 m_SecondaryMask = m_SecondaryMaskGenerator->GetMask();
331 m_SecondaryMaskGenerator->SetInputImage(old_img);
334 secondaryMaskImage = ImageToItkImage< MaskPixelType, VImageDimension >(m_SecondaryMask);
338 secondaryMaskMaskUtil->SetImage(secondaryMaskImage.GetPointer());
339 secondaryMaskMaskUtil->SetMask(maskImage.GetPointer());
340 typename MaskType::Pointer adaptedSecondaryMaskImage = secondaryMaskMaskUtil->ExtractMaskImageRegion();
343 maskFilter->SetInput1(maskImage);
344 maskFilter->SetInput2(adaptedSecondaryMaskImage);
345 maskFilter->SetMaskingValue(1);
346 maskFilter->UpdateLargestPossibleRegion();
347 maskImage = maskFilter->GetOutput();
351 maskUtil->SetImage(image);
352 maskUtil->SetMask(maskImage.GetPointer());
357 adaptedImage = maskUtil->ExtractMaskImageRegion();
361 minMaxFilter->SetInput(adaptedImage);
362 minMaxFilter->SetLabelInput(maskImage);
363 minMaxFilter->UpdateLargestPossibleRegion();
366 typedef typename std::map<LabelPixelType, InputImgPixelType> MapType;
367 typedef typename std::pair<LabelPixelType, InputImgPixelType> PairType;
369 std::vector<LabelPixelType> relevantLabels = minMaxFilter->GetRelevantLabels();
372 std::map<LabelPixelType, unsigned int> nBins;
374 for (LabelPixelType label:relevantLabels)
376 minVals.insert(PairType(label, minMaxFilter->GetMin(label)));
377 maxVals.insert(PairType(label, minMaxFilter->GetMax(label)));
379 unsigned int nBinsForHistogram;
380 if (m_UseBinSizeOverNBins)
382 nBinsForHistogram =
std::max(static_cast<double>(std::ceil(minMaxFilter->GetMax(label) - minMaxFilter->GetMin(label))) / m_binSizeForHistogramStatistics, 10.);
386 nBinsForHistogram = m_nBinsForHistogramStatistics;
389 nBins.insert(
typename std::pair<LabelPixelType, unsigned int>(label, nBinsForHistogram));
393 imageStatisticsFilter->SetDirectionTolerance(0.001);
394 imageStatisticsFilter->SetCoordinateTolerance(0.001);
395 imageStatisticsFilter->SetInput(adaptedImage);
396 imageStatisticsFilter->SetLabelInput(maskImage);
397 imageStatisticsFilter->SetHistogramParametersForLabels(nBins, minVals, maxVals);
398 imageStatisticsFilter->Update();
400 std::list<int> labels = imageStatisticsFilter->GetRelevantLabels();
401 std::list<int>::iterator it = labels.begin();
402 m_StatisticsByTimeStep[timeStep].resize(0);
404 while(it != labels.end())
411 vnl_vector<int> minIndex, maxIndex;
416 m_InternalImageForStatistics->GetGeometry()->IndexToWorld(minMaxFilter->GetMinIndex(*it), worldCoordinateMin);
417 m_InternalImageForStatistics->GetGeometry()->IndexToWorld(minMaxFilter->GetMaxIndex(*it), worldCoordinateMax);
418 m_Image->GetGeometry()->WorldToIndex(worldCoordinateMin, indexCoordinateMin);
419 m_Image->GetGeometry()->WorldToIndex(worldCoordinateMax, indexCoordinateMax);
426 minIndex.set_size(3);
427 maxIndex.set_size(3);
430 for (
unsigned int i=0; i < 3; i++)
434 minIndex[i] = indexCoordinateMin[i];
435 maxIndex[i] = indexCoordinateMax[i];
438 statisticsResult->SetMinIndex(minIndex);
439 statisticsResult->SetMaxIndex(maxIndex);
442 TPixel min_Filter = minMaxFilter->GetMin(*it);
443 TPixel max_Filter = minMaxFilter->GetMax(*it);
444 TPixel min_Itk = imageStatisticsFilter->GetMinimum(*it);
445 TPixel max_Itk = imageStatisticsFilter->GetMaximum(*it);
447 assert(abs(minMaxFilter->GetMax(*it) - imageStatisticsFilter->GetMaximum(*it)) <
mitk::eps);
448 assert(abs(minMaxFilter->GetMin(*it) - imageStatisticsFilter->GetMinimum(*it)) <
mitk::eps);
451 statisticsResult->SetN(imageStatisticsFilter->GetSum(*it) / (double) imageStatisticsFilter->GetMean(*it));
452 statisticsResult->SetMean(imageStatisticsFilter->GetMean(*it));
453 statisticsResult->SetMin(imageStatisticsFilter->GetMinimum(*it));
454 statisticsResult->SetMax(imageStatisticsFilter->GetMaximum(*it));
455 statisticsResult->SetVariance(imageStatisticsFilter->GetVariance(*it));
456 statisticsResult->SetStd(imageStatisticsFilter->GetSigma(*it));
457 statisticsResult->SetSkewness(imageStatisticsFilter->GetSkewness(*it));
458 statisticsResult->SetKurtosis(imageStatisticsFilter->GetKurtosis(*it));
459 statisticsResult->SetRMS(std::sqrt(std::pow(imageStatisticsFilter->GetMean(*it), 2.) + imageStatisticsFilter->GetVariance(*it)));
460 statisticsResult->SetMPP(imageStatisticsFilter->GetMPP(*it));
461 statisticsResult->SetLabel(*it);
463 statisticsResult->SetEntropy(imageStatisticsFilter->GetEntropy(*it));
464 statisticsResult->SetMedian(imageStatisticsFilter->GetMedian(*it));
465 statisticsResult->SetUniformity(imageStatisticsFilter->GetUniformity(*it));
466 statisticsResult->SetUPP(imageStatisticsFilter->GetUPP(*it));
467 statisticsResult->SetHistogram(imageStatisticsFilter->GetHistogram(*it));
469 m_StatisticsByTimeStep[timeStep].push_back(statisticsResult);
476 m_SecondaryMask = m_InternalMask;
477 m_InternalMask =
nullptr;
481 bool ImageStatisticsCalculator::IsUpdateRequired(
unsigned int timeStep)
const
483 unsigned long thisClassTimeStamp = this->GetMTime();
484 unsigned long inputImageTimeStamp = m_Image->GetMTime();
485 unsigned long statisticsTimeStamp = m_StatisticsUpdateTimePerTimeStep[timeStep];
487 if (thisClassTimeStamp > statisticsTimeStamp)
492 if (inputImageTimeStamp > statisticsTimeStamp)
497 if (m_MaskGenerator.IsNotNull())
499 unsigned long maskGeneratorTimeStamp = m_MaskGenerator->GetMTime();
500 if (maskGeneratorTimeStamp > statisticsTimeStamp)
506 if (m_SecondaryMaskGenerator.IsNotNull())
508 unsigned long maskGeneratorTimeStamp = m_SecondaryMaskGenerator->GetMTime();
509 if (maskGeneratorTimeStamp > statisticsTimeStamp)
531 m_Uniformity(nan(
"")),
535 m_minIndex.set_size(0);
536 m_maxIndex.set_size(0);
543 statisticsAsMap[
"N"] = m_N;
544 statisticsAsMap[
"Mean"] = m_Mean;
545 statisticsAsMap[
"Min"] = m_Min;
546 statisticsAsMap[
"Max"] = m_Max;
547 statisticsAsMap[
"StandardDeviation"] = m_Std;
548 statisticsAsMap[
"Variance"] = m_Variance;
549 statisticsAsMap[
"Skewness"] = m_Skewness;
550 statisticsAsMap[
"Kurtosis"] = m_Kurtosis;
551 statisticsAsMap[
"RMS"] = m_RMS;
552 statisticsAsMap[
"MPP"] = m_MPP;
553 statisticsAsMap[
"Median"] = m_Median;
554 statisticsAsMap[
"Uniformity"] = m_Uniformity;
555 statisticsAsMap[
"UPP"] = m_UPP;
556 statisticsAsMap[
"Entropy"] = m_Entropy;
557 statisticsAsMap[
"Label"] = m_Label;
559 return statisticsAsMap;
570 m_Variance = nan(
"");
571 m_Skewness = nan(
"");
572 m_Kurtosis = nan(
"");
576 m_Uniformity = nan(
"");
580 m_minIndex.set_size(0);
581 m_maxIndex.set_size(0);
590 for (
auto it = statMap.begin(); it != statMap.end(); ++it)
592 std::cout << it->first <<
": " << it->second << std::endl;
596 std::cout <<
"Min Index:" << std::endl;
597 for (
auto it = this->GetMinIndex().begin(); it != this->GetMinIndex().end(); ++it)
599 std::cout << *it <<
" ";
601 std::cout << std::endl;
604 std::cout <<
"Max Index:" << std::endl;
605 for (
auto it = this->GetMaxIndex().begin(); it != this->GetMaxIndex().end(); ++it)
607 std::cout << *it <<
" ";
609 std::cout << std::endl;
614 std::string res =
"";
618 for (
auto it = statMap.begin(); it != statMap.end(); ++it)
620 res += std::string(it->first) +
": " + std::to_string(it->second) +
"\n";
624 res +=
"Min Index:" + std::string(
"\n");
625 for (
auto it = this->GetMinIndex().begin(); it != this->GetMinIndex().end(); it++)
627 res += std::to_string(*it) + std::string(
" ");
632 res +=
"Max Index:" + std::string(
"\n");
633 for (
auto it = this->GetMaxIndex().begin(); it != this->GetMaxIndex().end(); it++)
635 res += std::to_string(*it) +
" ";
itk::SmartPointer< Self > Pointer
statisticsMapType GetStatisticsAsMap()
Returns a std::map containing all real valued statisti...
Extension of the itkLabelStatisticsImageFilter that also calculates the Skewness,Kurtosis,Entropy,Uniformity.
DataCollection - Class to facilitate loading/accessing structured data.
itk::SmartPointer< Self > Pointer
StatisticsContainer::Pointer GetStatistics(unsigned int timeStep=0, unsigned int label=1)
Returns the statistics for label label and timeStep timeStep. If these requested statistics are not c...
unsigned int GetNBinsForHistogramStatistics() const
Retrieve the number of bins used for histogram statistics. Careful: The return value does not indicat...
#define AccessByItk_1(mitkImage, itkImageTypeFunction, arg1)
void SetInputImage(mitk::Image::Pointer image)
Set the image for which the statistics are to be computed.
void SetNBinsForHistogramStatistics(unsigned int nBins)
Set number of bins to be used for histogram statistics. If Bin size is set after number of bins...
map::core::discrete::Elements< 3 >::InternalImageType ImageType
void SetSecondaryMask(mitk::MaskGenerator::Pointer mask)
Set this if more than one mask should be applied (for instance if a IgnorePixelValueMask were to be u...
void Print()
Creates a StatisticsMapType containing all real valued statistics stored in this class (= all statist...
void SetMask(mitk::MaskGenerator::Pointer mask)
Set the mask generator that creates the mask which is to be used to calculate statistics. If no more mask is desired simply set.
void Reset()
Deletes all stored values.
std::map< std::string, statisticsValueType > statisticsMapType
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
Extension of the itkStatisticsImageFilter that also calculates the Skewness and Kurtosis.
std::string GetAsString()
Generates a string that contains all real valued statistics stored in this class (= all statistics ex...
MITKCORE_EXPORT const ScalarType eps
double GetBinSizeForHistogramStatistics() const
Retrieve the bin size for histogram statistics. Careful: The return value does not indicate whether N...
void SetBinSizeForHistogramStatistics(double binSize)
Set bin size to be used for histogram statistics. If nbins is set after bin size, nbins will be used ...
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.