40 if (mask != m_MaskGenerator)
42 m_MaskGenerator =
mask;
49 if (mask != m_SecondaryMaskGenerator)
51 m_SecondaryMaskGenerator =
mask;
58 if (nBins != m_nBinsForHistogramStatistics)
60 m_nBinsForHistogramStatistics = nBins;
62 this->m_UseBinSizeOverNBins =
false;
64 if (m_UseBinSizeOverNBins)
67 this->m_UseBinSizeOverNBins =
false;
73 return m_nBinsForHistogramStatistics;
78 if (binSize != m_binSizeForHistogramStatistics)
80 m_binSizeForHistogramStatistics = binSize;
82 this->m_UseBinSizeOverNBins =
true;
84 if (!m_UseBinSizeOverNBins)
87 this->m_UseBinSizeOverNBins =
true;
100 if (!m_Image->IsInitialized())
105 if (IsUpdateRequired(label))
107 auto timeGeometry = m_Image->GetTimeGeometry();
109 for (
unsigned int timeStep = 0; timeStep < m_Image->GetTimeSteps(); timeStep++)
111 if (m_MaskGenerator.IsNotNull())
113 m_MaskGenerator->SetTimeStep(timeStep);
115 m_MaskGenerator->Modified();
116 m_InternalMask = m_MaskGenerator->GetMask();
117 if (m_MaskGenerator->GetReferenceImage().IsNotNull())
119 m_InternalImageForStatistics = m_MaskGenerator->GetReferenceImage();
123 m_InternalImageForStatistics = m_Image;
128 m_InternalImageForStatistics = m_Image;
131 if (m_SecondaryMaskGenerator.IsNotNull())
133 m_SecondaryMaskGenerator->SetTimeStep(timeStep);
134 m_SecondaryMask = m_SecondaryMaskGenerator->GetMask();
138 imgTimeSel->SetInput(m_InternalImageForStatistics);
139 imgTimeSel->SetTimeNr(timeStep);
140 imgTimeSel->UpdateLargestPossibleRegion();
141 imgTimeSel->Update();
142 m_ImageTimeSlice = imgTimeSel->GetOutput();
145 if (m_MaskGenerator.IsNull() && m_SecondaryMaskGenerator.IsNull())
148 AccessByItk_2(m_ImageTimeSlice, InternalCalculateStatisticsUnmasked, timeGeometry, timeStep)
153 AccessByItk_2(m_ImageTimeSlice, InternalCalculateStatisticsMasked, timeGeometry, timeStep)
158 auto it = m_StatisticContainers.find(label);
159 if (it != m_StatisticContainers.end())
161 return (it->second).GetPointer();
170 template <
typename TPixel,
unsigned int VImageDimension>
171 void ImageStatisticsCalculator::InternalCalculateStatisticsUnmasked(
174 typedef typename itk::Image<TPixel, VImageDimension>
ImageType;
181 auto it = m_StatisticContainers.find(labelNoMask);
182 if (it != m_StatisticContainers.end())
184 statisticContainerForImage = it->second;
189 statisticContainerForImage->SetTimeGeometry(const_cast<mitk::TimeGeometry*>(timeGeometry));
190 m_StatisticContainers.emplace(labelNoMask, statisticContainerForImage);
195 typename ImageStatisticsFilterType::Pointer statisticsFilter = ImageStatisticsFilterType::New();
196 statisticsFilter->SetInput(image);
197 statisticsFilter->SetCoordinateTolerance(0.001);
198 statisticsFilter->SetDirectionTolerance(0.001);
204 vnl_vector<int> minIndex, maxIndex;
206 typename MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New();
207 minMaxFilter->SetInput(image);
208 minMaxFilter->UpdateLargestPossibleRegion();
209 typename ImageType::PixelType minval = minMaxFilter->GetMin();
210 typename ImageType::PixelType maxval = minMaxFilter->GetMax();
212 typename ImageType::IndexType tmpMinIndex = minMaxFilter->GetMinIndex();
213 typename ImageType::IndexType tmpMaxIndex = minMaxFilter->GetMaxIndex();
218 minIndex.set_size(tmpMaxIndex.GetIndexDimension());
219 maxIndex.set_size(tmpMaxIndex.GetIndexDimension());
221 for (
unsigned int i = 0; i < tmpMaxIndex.GetIndexDimension(); i++)
223 minIndex[i] = tmpMinIndex[i];
224 maxIndex[i] = tmpMaxIndex[i];
231 unsigned int nBinsForHistogram;
232 if (m_UseBinSizeOverNBins)
234 nBinsForHistogram =
std::max(static_cast<double>(std::ceil(maxval - minval)) / m_binSizeForHistogramStatistics,
239 nBinsForHistogram = m_nBinsForHistogramStatistics;
242 statisticsFilter->SetHistogramParameters(nBinsForHistogram, minval, maxval);
246 statisticsFilter->Update();
248 catch (
const itk::ExceptionObject &e)
250 mitkThrow() <<
"Image statistics calculation failed due to following ITK Exception: \n " << e.what();
253 auto voxelVolume = GetVoxelVolume<TPixel, VImageDimension>(
image);
255 auto numberOfPixels = image->GetLargestPossibleRegion().GetNumberOfPixels();
256 auto volume =
static_cast<double>(numberOfPixels) * voxelVolume;
257 auto variance = statisticsFilter->GetSigma() * statisticsFilter->GetSigma();
259 std::sqrt(std::pow(statisticsFilter->GetMean(), 2.) + statisticsFilter->GetVariance());
262 static_cast<ImageStatisticsContainer::VoxelCountType>(numberOfPixels));
266 static_cast<ImageStatisticsContainer::RealType>(statisticsFilter->GetMinimum()));
268 static_cast<ImageStatisticsContainer::RealType>(statisticsFilter->GetMaximum()));
279 statObj.m_Histogram = statisticsFilter->GetHistogram().GetPointer();
280 statisticContainerForImage->SetStatisticsForTimeStep(timeStep, statObj);
283 template <
typename TPixel,
unsigned int VImageDimension>
284 double ImageStatisticsCalculator::GetVoxelVolume(
typename itk::Image<TPixel, VImageDimension> *image)
const 286 auto spacing = image->GetSpacing();
287 double voxelVolume = 1.;
288 for (
unsigned int i = 0; i < image->GetImageDimension(); i++)
290 voxelVolume *= spacing[i];
295 template <
typename TPixel,
unsigned int VImageDimension>
296 void ImageStatisticsCalculator::InternalCalculateStatisticsMasked(
typename itk::Image<TPixel, VImageDimension> *image,
298 unsigned int timeStep)
300 typedef itk::Image<TPixel, VImageDimension>
ImageType;
301 typedef itk::Image<MaskPixelType, VImageDimension> MaskType;
302 typedef typename MaskType::PixelType LabelPixelType;
306 typedef typename ImageType::PixelType InputImgPixelType;
310 bool swapMasks =
false;
311 if (m_SecondaryMask.IsNotNull() && m_InternalMask.IsNull())
313 m_InternalMask = m_SecondaryMask;
314 m_SecondaryMask =
nullptr;
319 typename MaskType::Pointer maskImage = MaskType::New();
324 maskImage = ImageToItkImage<MaskPixelType, VImageDimension>(m_InternalMask);
326 catch (
const itk::ExceptionObject &)
334 if (m_SecondaryMask.IsNotNull())
338 if (m_InternalMask->GetDimension() == 2 &&
339 (m_SecondaryMask->GetDimension() == 3 || m_SecondaryMask->GetDimension() == 4))
342 m_SecondaryMaskGenerator->SetInputImage(m_MaskGenerator->GetReferenceImage());
343 m_SecondaryMask = m_SecondaryMaskGenerator->GetMask();
344 m_SecondaryMaskGenerator->SetInputImage(old_img);
346 typename MaskType::Pointer secondaryMaskImage = MaskType::New();
347 secondaryMaskImage = ImageToItkImage<MaskPixelType, VImageDimension>(m_SecondaryMask);
353 secondaryMaskMaskUtil->SetImage(secondaryMaskImage.GetPointer());
354 secondaryMaskMaskUtil->SetMask(maskImage.GetPointer());
355 typename MaskType::Pointer adaptedSecondaryMaskImage = secondaryMaskMaskUtil->ExtractMaskImageRegion();
359 maskFilter->SetInput1(maskImage);
360 maskFilter->SetInput2(adaptedSecondaryMaskImage);
361 maskFilter->SetMaskingValue(
363 maskFilter->UpdateLargestPossibleRegion();
364 maskImage = maskFilter->GetOutput();
367 typename MaskUtilType::Pointer maskUtil = MaskUtilType::New();
368 maskUtil->SetImage(image);
369 maskUtil->SetMask(maskImage.GetPointer());
372 typename ImageType::Pointer adaptedImage = ImageType::New();
374 adaptedImage = maskUtil->ExtractMaskImageRegion();
377 typename MinMaxLabelFilterType::Pointer minMaxFilter = MinMaxLabelFilterType::New();
378 minMaxFilter->SetInput(adaptedImage);
379 minMaxFilter->SetLabelInput(maskImage);
380 minMaxFilter->UpdateLargestPossibleRegion();
383 typedef typename std::map<LabelPixelType, InputImgPixelType> MapType;
384 typedef typename std::pair<LabelPixelType, InputImgPixelType> PairType;
386 std::vector<LabelPixelType> relevantLabels = minMaxFilter->GetRelevantLabels();
389 std::map<LabelPixelType, unsigned int> nBins;
391 for (LabelPixelType label : relevantLabels)
393 minVals.insert(PairType(label, minMaxFilter->GetMin(label)));
394 maxVals.insert(PairType(label, minMaxFilter->GetMax(label)));
396 unsigned int nBinsForHistogram;
397 if (m_UseBinSizeOverNBins)
400 std::max(static_cast<double>(std::ceil(minMaxFilter->GetMax(label) - minMaxFilter->GetMin(label))) /
401 m_binSizeForHistogramStatistics,
406 nBinsForHistogram = m_nBinsForHistogramStatistics;
409 nBins.insert(
typename std::pair<LabelPixelType, unsigned int>(label, nBinsForHistogram));
412 typename ImageStatisticsFilterType::Pointer imageStatisticsFilter = ImageStatisticsFilterType::New();
413 imageStatisticsFilter->SetDirectionTolerance(0.001);
414 imageStatisticsFilter->SetCoordinateTolerance(0.001);
415 imageStatisticsFilter->SetInput(adaptedImage);
416 imageStatisticsFilter->SetLabelInput(maskImage);
417 imageStatisticsFilter->SetHistogramParametersForLabels(nBins, minVals, maxVals);
418 imageStatisticsFilter->Update();
420 std::list<int> labels = imageStatisticsFilter->GetRelevantLabels();
421 auto it = labels.begin();
423 while (it != labels.end())
426 auto labelIt = m_StatisticContainers.find(*it);
428 if (labelIt != m_StatisticContainers.end())
430 statisticContainerForLabelImage = labelIt->second;
436 statisticContainerForLabelImage->SetTimeGeometry(const_cast<mitk::TimeGeometry*>(timeGeometry));
438 m_StatisticContainers.emplace(*it, statisticContainerForLabelImage);
446 vnl_vector<int> minIndex, maxIndex;
451 m_InternalImageForStatistics->GetGeometry()->IndexToWorld(minMaxFilter->GetMinIndex(*it), worldCoordinateMin);
452 m_InternalImageForStatistics->GetGeometry()->IndexToWorld(minMaxFilter->GetMaxIndex(*it), worldCoordinateMax);
453 m_Image->GetGeometry()->WorldToIndex(worldCoordinateMin, indexCoordinateMin);
454 m_Image->GetGeometry()->WorldToIndex(worldCoordinateMax, indexCoordinateMax);
456 minIndex.set_size(3);
457 maxIndex.set_size(3);
460 for (
unsigned int i = 0; i < 3; i++)
462 minIndex[i] = indexCoordinateMin[i];
463 maxIndex[i] = indexCoordinateMax[i];
469 assert(std::abs(minMaxFilter->GetMax(*it) - imageStatisticsFilter->GetMaximum(*it)) <
mitk::eps);
470 assert(std::abs(minMaxFilter->GetMin(*it) - imageStatisticsFilter->GetMinimum(*it)) <
mitk::eps);
472 auto voxelVolume = GetVoxelVolume<TPixel, VImageDimension>(
image);
473 auto numberOfVoxels =
474 static_cast<unsigned long>(imageStatisticsFilter->GetSum(*it) / (double)imageStatisticsFilter->GetMean(*it));
475 auto volume =
static_cast<double>(numberOfVoxels) * voxelVolume;
476 auto rms = std::sqrt(std::pow(imageStatisticsFilter->GetMean(*it), 2.) +
477 imageStatisticsFilter->GetVariance(*it));
478 auto variance = imageStatisticsFilter->GetSigma(*it) * imageStatisticsFilter->GetSigma(*it);
495 statObj.
m_Histogram = imageStatisticsFilter->GetHistogram(*it).GetPointer();
497 statisticContainerForLabelImage->SetStatisticsForTimeStep(timeStep, statObj);
504 m_SecondaryMask = m_InternalMask;
505 m_InternalMask =
nullptr;
509 bool ImageStatisticsCalculator::IsUpdateRequired(
LabelIndex label)
const 511 unsigned long thisClassTimeStamp = this->GetMTime();
512 unsigned long inputImageTimeStamp = m_Image->GetMTime();
514 auto it = m_StatisticContainers.find(label);
515 if (it == m_StatisticContainers.end())
520 unsigned long statisticsTimeStamp = it->second->GetMTime();
522 if (thisClassTimeStamp > statisticsTimeStamp)
527 if (inputImageTimeStamp > statisticsTimeStamp)
532 if (m_MaskGenerator.IsNotNull())
534 unsigned long maskGeneratorTimeStamp = m_MaskGenerator->GetMTime();
535 if (maskGeneratorTimeStamp > statisticsTimeStamp)
541 if (m_SecondaryMaskGenerator.IsNotNull())
543 unsigned long maskGeneratorTimeStamp = m_SecondaryMaskGenerator->GetMTime();
544 if (maskGeneratorTimeStamp > statisticsTimeStamp)
static const std::string NUMBEROFVOXELS()
HistogramType::ConstPointer m_Histogram
static const std::string MEDIAN()
static const std::string MINIMUMPOSITION()
static const std::string MAXIMUMPOSITION()
ImageStatisticsContainer * GetStatistics(LabelIndex label=1)
Returns the statistics for label label. If these requested statistics are not computed yet the comput...
itk::Image< unsigned char, 3 > ImageType
Extension of the itkLabelStatisticsImageFilter that also calculates the Skewness,Kurtosis,Entropy,Uniformity.
static const std::string UPP()
double GetBinSizeForHistogramStatistics() const
Retrieve the bin size for histogram statistics. Careful: The return value does not indicate whether N...
void SetSecondaryMask(mitk::MaskGenerator *mask)
Set this if more than one mask should be applied (for instance if a IgnorePixelValueMask were to be u...
Base Class for all Mask Generators. Mask generators are classes that provide functionality for the cr...
DataCollection - Class to facilitate loading/accessing structured data.
Utility class for mask operations. It checks whether an image and a mask are compatible (spacing...
void AddStatistic(const std::string &key, StatisticsVariantType value)
Adds a statistic to the statistics object.
static const std::string VARIANCE()
static const std::string RMS()
unsigned int GetNBinsForHistogramStatistics() const
Retrieve the number of bins used for histogram statistics. Careful: The return value does not indicat...
static const std::string UNIFORMITY()
void SetNBinsForHistogramStatistics(unsigned int nBins)
Set number of bins to be used for histogram statistics. If Bin size is set after number of bins...
static const std::string MPP()
void SetMask(mitk::MaskGenerator *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.
Image class for storing images.
static const std::string KURTOSIS()
std::vcl_size_t TimeStepType
static const std::string MINIMUM()
mitk::Image::Pointer image
ImageStatisticsContainer::LabelIndex LabelIndex
static const std::string SKEWNESS()
static const std::string STANDARDDEVIATION()
static const std::string ENTROPY()
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
static const std::string MAXIMUM()
Extension of the itkStatisticsImageFilter that also calculates the Skewness and Kurtosis.
MITKCORE_EXPORT const ScalarType eps
mitk::Image::Pointer mask
#define AccessByItk_2(mitkImage, itkImageTypeFunction, arg1, arg2)
void SetBinSizeForHistogramStatistics(double binSize)
Set bin size to be used for histogram statistics. If nbins is set after bin size, nbins will be used ...
Container class for storing the computed image statistics.
itk::SmartPointer< Self > Pointer
static const std::string MEAN()
void SetInputImage(const mitk::Image *image)
Set the image for which the statistics are to be computed.
static const std::string VOLUME()
Container class for storing a StatisticsObject for each timestep.