Page MenuHomePhabricator

mitkImageStatisticsCalculator.cpp.html

Authored By
j762e
Apr 3 2020, 1:46 PM
Size
30 KB
Referenced Files
None
Subscribers
None

mitkImageStatisticsCalculator.cpp.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8"/>
<title>mitkImageStatisticsCalculator.cpp</title>
<link href="../../third-party/google-code-prettify/prettify-CppCoverage.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="../../third-party/google-code-prettify/prettify.js"></script>
</head>
<body onload="prettyPrint()">
<h4></h4>
<pre class="prettyprint lang-cpp linenums">
/*============================================================================
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.
============================================================================*/
#include "mitkImageStatisticsCalculator.h"
#include &lt;mitkExtendedLabelStatisticsImageFilter.h&gt;
#include &lt;mitkExtendedStatisticsImageFilter.h&gt;
#include &lt;mitkImage.h&gt;
#include &lt;mitkImageAccessByItk.h&gt;
#include &lt;mitkImageCast.h&gt;
#include &lt;mitkImageStatisticsConstants.h&gt;
#include &lt;mitkImageTimeSelector.h&gt;
#include &lt;mitkImageToItk.h&gt;
#include &lt;mitkMaskUtilities.h&gt;
#include &lt;mitkMinMaxImageFilterWithIndex.h&gt;
#include &lt;mitkMinMaxLabelmageFilterWithIndex.h&gt;
#include &lt;mitkitkMaskImageFilter.h&gt;
namespace mitk
{
void ImageStatisticsCalculator::SetInputImage(const mitk::Image *image)
<span style = "background-color:#0f0"> {
if (image != m_Image)</span>
{
<span style = "background-color:#0f0"> m_Image = image;
this-&gt;Modified();</span>
}
<span style = "background-color:#0f0"> }</span>
void ImageStatisticsCalculator::SetMask(mitk::MaskGenerator *mask)
<span style = "background-color:#0f0"> {
if (mask != m_MaskGenerator)</span>
{
<span style = "background-color:#0f0"> m_MaskGenerator = mask;
this-&gt;Modified();</span>
}
<span style = "background-color:#0f0"> }</span>
void ImageStatisticsCalculator::SetSecondaryMask(mitk::MaskGenerator *mask)
<span style = "background-color:#f00"> {
if (mask != m_SecondaryMaskGenerator)</span>
{
<span style = "background-color:#f00"> m_SecondaryMaskGenerator = mask;
this-&gt;Modified();</span>
}
<span style = "background-color:#f00"> }</span>
void ImageStatisticsCalculator::SetNBinsForHistogramStatistics(unsigned int nBins)
<span style = "background-color:#f00"> {
if (nBins != m_nBinsForHistogramStatistics)</span>
{
<span style = "background-color:#f00"> m_nBinsForHistogramStatistics = nBins;
this-&gt;Modified();
this-&gt;m_UseBinSizeOverNBins = false;</span>
}
<span style = "background-color:#f00"> if (m_UseBinSizeOverNBins)</span>
{
<span style = "background-color:#f00"> this-&gt;Modified();
this-&gt;m_UseBinSizeOverNBins = false;</span>
}
<span style = "background-color:#f00"> }</span>
unsigned int ImageStatisticsCalculator::GetNBinsForHistogramStatistics() const
<span style = "background-color:#f00"> {
return m_nBinsForHistogramStatistics;
}</span>
void ImageStatisticsCalculator::SetBinSizeForHistogramStatistics(double binSize)
<span style = "background-color:#f00"> {
if (binSize != m_binSizeForHistogramStatistics)</span>
{
<span style = "background-color:#f00"> m_binSizeForHistogramStatistics = binSize;
this-&gt;Modified();
this-&gt;m_UseBinSizeOverNBins = true;</span>
}
<span style = "background-color:#f00"> if (!m_UseBinSizeOverNBins)</span>
{
<span style = "background-color:#f00"> this-&gt;Modified();
this-&gt;m_UseBinSizeOverNBins = true;</span>
}
<span style = "background-color:#f00"> }</span>
<span style = "background-color:#f00"> double ImageStatisticsCalculator::GetBinSizeForHistogramStatistics() const { return m_binSizeForHistogramStatistics; }</span>
mitk::ImageStatisticsContainer* ImageStatisticsCalculator::GetStatistics(LabelIndex label)
<span style = "background-color:#0f0"> {
if (m_Image.IsNull())</span>
{
<span style = "background-color:#0f0"> mitkThrow() &lt;&lt; "no image";</span>
}
<span style = "background-color:#0f0"> if (!m_Image-&gt;IsInitialized())</span>
{
<span style = "background-color:#f00"> mitkThrow() &lt;&lt; "Image not initialized!";</span>
}
<span style = "background-color:#0f0"> if (IsUpdateRequired(label))</span>
{
<span style = "background-color:#0f0"> auto timeGeometry = m_Image-&gt;GetTimeGeometry();</span>
// always compute statistics on all timesteps
<span style = "background-color:#0f0"> for (unsigned int timeStep = 0; timeStep &lt; m_Image-&gt;GetTimeSteps(); timeStep++)</span>
{
<span style = "background-color:#0f0"> if (m_MaskGenerator.IsNotNull())</span>
{
<span style = "background-color:#0f0"> m_MaskGenerator-&gt;SetTimeStep(timeStep);</span>
//See T25625: otherwise, the mask is not computed again after setting a different time step
<span style = "background-color:#0f0"> m_MaskGenerator-&gt;Modified();
m_InternalMask = m_MaskGenerator-&gt;GetMask();
if (m_MaskGenerator-&gt;GetReferenceImage().IsNotNull())</span>
{
<span style = "background-color:#0f0"> m_InternalImageForStatistics = m_MaskGenerator-&gt;GetReferenceImage();
}</span>
else
{
<span style = "background-color:#f00"> m_InternalImageForStatistics = m_Image;</span>
}
<span style = "background-color:#0f0"> }</span>
else
{
<span style = "background-color:#0f0"> m_InternalImageForStatistics = m_Image;</span>
}
<span style = "background-color:#0f0"> if (m_SecondaryMaskGenerator.IsNotNull())</span>
{
<span style = "background-color:#f00"> m_SecondaryMaskGenerator-&gt;SetTimeStep(timeStep);
m_SecondaryMask = m_SecondaryMaskGenerator-&gt;GetMask();</span>
}
<span style = "background-color:#0f0"> ImageTimeSelector::Pointer imgTimeSel = ImageTimeSelector::New();
imgTimeSel-&gt;SetInput(m_InternalImageForStatistics);
imgTimeSel-&gt;SetTimeNr(timeStep);
imgTimeSel-&gt;UpdateLargestPossibleRegion();
imgTimeSel-&gt;Update();
m_ImageTimeSlice = imgTimeSel-&gt;GetOutput();</span>
// Calculate statistics with/without mask
<span style = "background-color:#0f0"> if (m_MaskGenerator.IsNull() &amp;&amp; m_SecondaryMaskGenerator.IsNull())</span>
{
// 1) calculate statistics unmasked:
<span style = "background-color:#0f0"> AccessByItk_2(m_ImageTimeSlice, InternalCalculateStatisticsUnmasked, timeGeometry, timeStep)
}</span>
else
{
// 2) calculate statistics masked
<span style = "background-color:#0f0"> AccessByItk_2(m_ImageTimeSlice, InternalCalculateStatisticsMasked, timeGeometry, timeStep)</span>
}
<span style = "background-color:#0f0"> }</span>
}
<span style = "background-color:#0f0"> auto it = m_StatisticContainers.find(label);
if (it != m_StatisticContainers.end())</span>
{
<span style = "background-color:#0f0"> return (it-&gt;second).GetPointer();</span>
<span style = "background-color:#f00"> }</span>
else
{
<span style = "background-color:#f00"> mitkThrow() &lt;&lt; "unknown label";
return nullptr;</span>
}
<span style = "background-color:#f00"> }</span>
template &lt;typename TPixel, unsigned int VImageDimension&gt;
void ImageStatisticsCalculator::InternalCalculateStatisticsUnmasked(
typename itk::Image&lt;TPixel, VImageDimension&gt; *image, const TimeGeometry *timeGeometry, TimeStepType timeStep)
<span style = "background-color:#0f0"> {</span>
typedef typename itk::Image&lt;TPixel, VImageDimension&gt; ImageType;
typedef typename itk::ExtendedStatisticsImageFilter&lt;ImageType&gt; ImageStatisticsFilterType;
typedef typename itk::MinMaxImageFilterWithIndex&lt;ImageType&gt; MinMaxFilterType;
// reset statistics container if exists
<span style = "background-color:#0f0"> ImageStatisticsContainer::Pointer statisticContainerForImage;
LabelIndex labelNoMask = 1;
auto it = m_StatisticContainers.find(labelNoMask);
if (it != m_StatisticContainers.end())</span>
{
<span style = "background-color:#f00"> statisticContainerForImage = it-&gt;second;
}</span>
else
{
<span style = "background-color:#0f0"> statisticContainerForImage = ImageStatisticsContainer::New();
statisticContainerForImage-&gt;SetTimeGeometry(const_cast&lt;mitk::TimeGeometry*&gt;(timeGeometry));
m_StatisticContainers.emplace(labelNoMask, statisticContainerForImage);</span>
}
<span style = "background-color:#0f0"> auto statObj = ImageStatisticsContainer::ImageStatisticsObject();</span>
<span style = "background-color:#0f0"> typename ImageStatisticsFilterType::Pointer statisticsFilter = ImageStatisticsFilterType::New();
statisticsFilter-&gt;SetInput(image);
statisticsFilter-&gt;SetCoordinateTolerance(0.001);
statisticsFilter-&gt;SetDirectionTolerance(0.001);</span>
// TODO: this is single threaded. Implement our own image filter that does this multi threaded
// typename itk::MinimumMaximumImageCalculator&lt;ImageType&gt;::Pointer imgMinMaxFilter =
// itk::MinimumMaximumImageCalculator&lt;ImageType&gt;::New(); imgMinMaxFilter-&gt;SetImage(image);
// imgMinMaxFilter-&gt;Compute();
<span style = "background-color:#0f0"> vnl_vector&lt;int&gt; minIndex, maxIndex;</span>
<span style = "background-color:#0f0"> typename MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New();
minMaxFilter-&gt;SetInput(image);
minMaxFilter-&gt;UpdateLargestPossibleRegion();
typename ImageType::PixelType minval = minMaxFilter-&gt;GetMin();
typename ImageType::PixelType maxval = minMaxFilter-&gt;GetMax();</span>
<span style = "background-color:#0f0"> typename ImageType::IndexType tmpMinIndex = minMaxFilter-&gt;GetMinIndex();
typename ImageType::IndexType tmpMaxIndex = minMaxFilter-&gt;GetMaxIndex();</span>
// typename ImageType::IndexType tmpMinIndex = imgMinMaxFilter-&gt;GetIndexOfMinimum();
// typename ImageType::IndexType tmpMaxIndex = imgMinMaxFilter-&gt;GetIndexOfMaximum();
<span style = "background-color:#0f0"> minIndex.set_size(tmpMaxIndex.GetIndexDimension());
maxIndex.set_size(tmpMaxIndex.GetIndexDimension());</span>
<span style = "background-color:#0f0"> for (unsigned int i = 0; i &lt; tmpMaxIndex.GetIndexDimension(); i++)</span>
{
<span style = "background-color:#0f0"> minIndex[i] = tmpMinIndex[i];
maxIndex[i] = tmpMaxIndex[i];
}</span>
<span style = "background-color:#0f0"> statObj.AddStatistic(mitk::ImageStatisticsConstants::MINIMUMPOSITION(), minIndex);
statObj.AddStatistic(mitk::ImageStatisticsConstants::MAXIMUMPOSITION(), maxIndex);</span>
// convert m_binSize in m_nBins if necessary
unsigned int nBinsForHistogram;
<span style = "background-color:#0f0"> if (m_UseBinSizeOverNBins)</span>
{
<span style = "background-color:#f00"> nBinsForHistogram = std::max(static_cast&lt;double&gt;(std::ceil(maxval - minval)) / m_binSizeForHistogramStatistics,</span>
10.); // do not allow less than 10 bins
<span style = "background-color:#f00"> }</span>
else
{
<span style = "background-color:#0f0"> nBinsForHistogram = m_nBinsForHistogramStatistics;</span>
}
<span style = "background-color:#0f0"> statisticsFilter-&gt;SetHistogramParameters(nBinsForHistogram, minval, maxval);</span>
try
{
<span style = "background-color:#0f0"> statisticsFilter-&gt;Update();</span>
}
catch (const itk::ExceptionObject &amp;e)
<span style = "background-color:#f00"> {
mitkThrow() &lt;&lt; "Image statistics calculation failed due to following ITK Exception: \n " &lt;&lt; e.what();
}</span>
<span style = "background-color:#0f0"> auto voxelVolume = GetVoxelVolume&lt;TPixel, VImageDimension&gt;(image);</span>
<span style = "background-color:#0f0"> auto numberOfPixels = image-&gt;GetLargestPossibleRegion().GetNumberOfPixels();
auto volume = static_cast&lt;double&gt;(numberOfPixels) * voxelVolume;
auto variance = statisticsFilter-&gt;GetSigma() * statisticsFilter-&gt;GetSigma();
auto rms =</span>
std::sqrt(std::pow(statisticsFilter-&gt;GetMean(), 2.) + statisticsFilter-&gt;GetVariance()); // variance = sigma^2
<span style = "background-color:#0f0"> statObj.AddStatistic(mitk::ImageStatisticsConstants::NUMBEROFVOXELS(),</span>
static_cast&lt;ImageStatisticsContainer::VoxelCountType&gt;(numberOfPixels));
<span style = "background-color:#0f0"> statObj.AddStatistic(mitk::ImageStatisticsConstants::VOLUME(), volume);
statObj.AddStatistic(mitk::ImageStatisticsConstants::MEAN(), statisticsFilter-&gt;GetMean());
statObj.AddStatistic(mitk::ImageStatisticsConstants::MINIMUM(),</span>
static_cast&lt;ImageStatisticsContainer::RealType&gt;(statisticsFilter-&gt;GetMinimum()));
<span style = "background-color:#0f0"> statObj.AddStatistic(mitk::ImageStatisticsConstants::MAXIMUM(),</span>
static_cast&lt;ImageStatisticsContainer::RealType&gt;(statisticsFilter-&gt;GetMaximum()));
<span style = "background-color:#0f0"> statObj.AddStatistic(mitk::ImageStatisticsConstants::STANDARDDEVIATION(), statisticsFilter-&gt;GetSigma());
statObj.AddStatistic(mitk::ImageStatisticsConstants::VARIANCE(), variance);
statObj.AddStatistic(mitk::ImageStatisticsConstants::SKEWNESS(), statisticsFilter-&gt;GetSkewness());
statObj.AddStatistic(mitk::ImageStatisticsConstants::KURTOSIS(), statisticsFilter-&gt;GetKurtosis());
statObj.AddStatistic(mitk::ImageStatisticsConstants::RMS(), rms);
statObj.AddStatistic(mitk::ImageStatisticsConstants::MPP(), statisticsFilter-&gt;GetMPP());
statObj.AddStatistic(mitk::ImageStatisticsConstants::ENTROPY(), statisticsFilter-&gt;GetEntropy());
statObj.AddStatistic(mitk::ImageStatisticsConstants::MEDIAN(), statisticsFilter-&gt;GetMedian());
statObj.AddStatistic(mitk::ImageStatisticsConstants::UNIFORMITY(), statisticsFilter-&gt;GetUniformity());
statObj.AddStatistic(mitk::ImageStatisticsConstants::UPP(), statisticsFilter-&gt;GetUPP());
statObj.m_Histogram = statisticsFilter-&gt;GetHistogram().GetPointer();
statisticContainerForImage-&gt;SetStatisticsForTimeStep(timeStep, statObj);
}</span>
template &lt;typename TPixel, unsigned int VImageDimension&gt;
double ImageStatisticsCalculator::GetVoxelVolume(typename itk::Image&lt;TPixel, VImageDimension&gt; *image) const
<span style = "background-color:#0f0"> {
auto spacing = image-&gt;GetSpacing();
double voxelVolume = 1.;
for (unsigned int i = 0; i &lt; image-&gt;GetImageDimension(); i++)</span>
{
<span style = "background-color:#0f0"> voxelVolume *= spacing[i];
}
return voxelVolume;
}</span>
template &lt;typename TPixel, unsigned int VImageDimension&gt;
void ImageStatisticsCalculator::InternalCalculateStatisticsMasked(typename itk::Image&lt;TPixel, VImageDimension&gt; *image,
const TimeGeometry *timeGeometry,
unsigned int timeStep)
<span style = "background-color:#0f0"> {</span>
typedef itk::Image&lt;TPixel, VImageDimension&gt; ImageType;
typedef itk::Image&lt;MaskPixelType, VImageDimension&gt; MaskType;
typedef typename MaskType::PixelType LabelPixelType;
typedef itk::ExtendedLabelStatisticsImageFilter&lt;ImageType, MaskType&gt; ImageStatisticsFilterType;
typedef MaskUtilities&lt;TPixel, VImageDimension&gt; MaskUtilType;
typedef typename itk::MinMaxLabelImageFilterWithIndex&lt;ImageType, MaskType&gt; MinMaxLabelFilterType;
typedef typename ImageType::PixelType InputImgPixelType;
// workaround: if m_SecondaryMaskGenerator ist not null but m_MaskGenerator is! (this is the case if we request a
// 'ignore zuero valued pixels' mask in the gui but do not define a primary mask)
<span style = "background-color:#0f0"> bool swapMasks = false;
if (m_SecondaryMask.IsNotNull() &amp;&amp; m_InternalMask.IsNull())</span>
{
<span style = "background-color:#f00"> m_InternalMask = m_SecondaryMask;
m_SecondaryMask = nullptr;
swapMasks = true;</span>
}
// maskImage has to have the same dimension as image
<span style = "background-color:#0f0"> typename MaskType::Pointer maskImage = MaskType::New();</span>
try
{
// try to access the pixel values directly (no copying or casting). Only works if mask pixels are of pixelType
// unsigned short
<span style = "background-color:#0f0"> maskImage = ImageToItkImage&lt;MaskPixelType, VImageDimension&gt;(m_InternalMask);</span>
}
catch (const itk::ExceptionObject &amp;)
<span style = "background-color:#f00"> {</span>
// if the pixel type of the mask is not short, then we have to make a copy of m_InternalMask (and cast the values)
<span style = "background-color:#f00"> CastToItkImage(m_InternalMask, maskImage);
}</span>
// if we have a secondary mask (say a ignoreZeroPixelMask) we need to combine the masks (corresponds to AND)
<span style = "background-color:#0f0"> if (m_SecondaryMask.IsNotNull())</span>
{
// dirty workaround for a bug when pf mask + any other mask is used in conjunction. We need a proper fix for this
// (Fabian Isensee is responsible and probably working on it!)
<span style = "background-color:#f00"> if (m_InternalMask-&gt;GetDimension() == 2 &amp;&amp;</span>
(m_SecondaryMask-&gt;GetDimension() == 3 || m_SecondaryMask-&gt;GetDimension() == 4))
{
<span style = "background-color:#f00"> mitk::Image::ConstPointer old_img = m_SecondaryMaskGenerator-&gt;GetReferenceImage();
m_SecondaryMaskGenerator-&gt;SetInputImage(m_MaskGenerator-&gt;GetReferenceImage());
m_SecondaryMask = m_SecondaryMaskGenerator-&gt;GetMask();
m_SecondaryMaskGenerator-&gt;SetInputImage(old_img);
}
typename MaskType::Pointer secondaryMaskImage = MaskType::New();
secondaryMaskImage = ImageToItkImage&lt;MaskPixelType, VImageDimension&gt;(m_SecondaryMask);</span>
// secondary mask should be a ignore zero value pixel mask derived from image. it has to be cropped to the mask
// region (which may be planar or simply smaller)
<span style = "background-color:#f00"> typename MaskUtilities&lt;MaskPixelType, VImageDimension&gt;::Pointer secondaryMaskMaskUtil =</span>
MaskUtilities&lt;MaskPixelType, VImageDimension&gt;::New();
<span style = "background-color:#f00"> secondaryMaskMaskUtil-&gt;SetImage(secondaryMaskImage.GetPointer());
secondaryMaskMaskUtil-&gt;SetMask(maskImage.GetPointer());
typename MaskType::Pointer adaptedSecondaryMaskImage = secondaryMaskMaskUtil-&gt;ExtractMaskImageRegion();</span>
<span style = "background-color:#f00"> typename itk::MaskImageFilter2&lt;MaskType, MaskType, MaskType&gt;::Pointer maskFilter =</span>
itk::MaskImageFilter2&lt;MaskType, MaskType, MaskType&gt;::New();
<span style = "background-color:#f00"> maskFilter-&gt;SetInput1(maskImage);
maskFilter-&gt;SetInput2(adaptedSecondaryMaskImage);
maskFilter-&gt;SetMaskingValue(</span>
1); // all pixels of maskImage where secondaryMaskImage==1 will be kept, all the others are set to 0
<span style = "background-color:#f00"> maskFilter-&gt;UpdateLargestPossibleRegion();
maskImage = maskFilter-&gt;GetOutput();
}</span>
<span style = "background-color:#0f0"> typename MaskUtilType::Pointer maskUtil = MaskUtilType::New();
maskUtil-&gt;SetImage(image);
maskUtil-&gt;SetMask(maskImage.GetPointer());</span>
// if mask is smaller than image, extract the image region where the mask is
<span style = "background-color:#0f0"> typename ImageType::Pointer adaptedImage = ImageType::New();</span>
<span style = "background-color:#0f0"> adaptedImage = maskUtil-&gt;ExtractMaskImageRegion(); // this also checks mask sanity</span>
// find min, max, minindex and maxindex
<span style = "background-color:#0f0"> typename MinMaxLabelFilterType::Pointer minMaxFilter = MinMaxLabelFilterType::New();
minMaxFilter-&gt;SetInput(adaptedImage);
minMaxFilter-&gt;SetLabelInput(maskImage);
minMaxFilter-&gt;UpdateLargestPossibleRegion();</span>
// set histogram parameters for each label individually (min/max may be different for each label)
typedef typename std::map&lt;LabelPixelType, InputImgPixelType&gt; MapType;
typedef typename std::pair&lt;LabelPixelType, InputImgPixelType&gt; PairType;
<span style = "background-color:#0f0"> std::vector&lt;LabelPixelType&gt; relevantLabels = minMaxFilter-&gt;GetRelevantLabels();
MapType minVals;
MapType maxVals;
std::map&lt;LabelPixelType, unsigned int&gt; nBins;</span>
<span style = "background-color:#0f0"> for (LabelPixelType label : relevantLabels)</span>
{
<span style = "background-color:#0f0"> minVals.insert(PairType(label, minMaxFilter-&gt;GetMin(label)));
maxVals.insert(PairType(label, minMaxFilter-&gt;GetMax(label)));</span>
unsigned int nBinsForHistogram;
<span style = "background-color:#0f0"> if (m_UseBinSizeOverNBins)</span>
{
<span style = "background-color:#f00"> nBinsForHistogram =</span>
std::max(static_cast&lt;double&gt;(std::ceil(minMaxFilter-&gt;GetMax(label) - minMaxFilter-&gt;GetMin(label))) /
m_binSizeForHistogramStatistics,
10.); // do not allow less than 10 bins
<span style = "background-color:#f00"> }</span>
else
{
<span style = "background-color:#0f0"> nBinsForHistogram = m_nBinsForHistogramStatistics;</span>
}
<span style = "background-color:#0f0"> nBins.insert(typename std::pair&lt;LabelPixelType, unsigned int&gt;(label, nBinsForHistogram));
}</span>
<span style = "background-color:#0f0"> typename ImageStatisticsFilterType::Pointer imageStatisticsFilter = ImageStatisticsFilterType::New();
imageStatisticsFilter-&gt;SetDirectionTolerance(0.001);
imageStatisticsFilter-&gt;SetCoordinateTolerance(0.001);
imageStatisticsFilter-&gt;SetInput(adaptedImage);
imageStatisticsFilter-&gt;SetLabelInput(maskImage);
imageStatisticsFilter-&gt;SetHistogramParametersForLabels(nBins, minVals, maxVals);
imageStatisticsFilter-&gt;Update();</span>
<span style = "background-color:#0f0"> std::list&lt;int&gt; labels = imageStatisticsFilter-&gt;GetRelevantLabels();
auto it = labels.begin();</span>
<span style = "background-color:#0f0"> while (it != labels.end())</span>
{
<span style = "background-color:#0f0"> ImageStatisticsContainer::Pointer statisticContainerForLabelImage;
auto labelIt = m_StatisticContainers.find(*it);</span>
// reset if statisticContainer already exist
<span style = "background-color:#0f0"> if (labelIt != m_StatisticContainers.end())</span>
{
<span style = "background-color:#0f0"> statisticContainerForLabelImage = labelIt-&gt;second;
}</span>
// create new statisticContainer
else
{
<span style = "background-color:#0f0"> statisticContainerForLabelImage = ImageStatisticsContainer::New();
statisticContainerForLabelImage-&gt;SetTimeGeometry(const_cast&lt;mitk::TimeGeometry*&gt;(timeGeometry));</span>
// link label (*it) to statisticContainer
<span style = "background-color:#0f0"> m_StatisticContainers.emplace(*it, statisticContainerForLabelImage);</span>
}
<span style = "background-color:#0f0"> ImageStatisticsContainer::ImageStatisticsObject statObj;</span>
// find min, max, minindex and maxindex
// make sure to only look in the masked region, use a masker for this
<span style = "background-color:#0f0"> vnl_vector&lt;int&gt; minIndex, maxIndex;
mitk::Point3D worldCoordinateMin;
mitk::Point3D worldCoordinateMax;
mitk::Point3D indexCoordinateMin;
mitk::Point3D indexCoordinateMax;
m_InternalImageForStatistics-&gt;GetGeometry()-&gt;IndexToWorld(minMaxFilter-&gt;GetMinIndex(*it), worldCoordinateMin);
m_InternalImageForStatistics-&gt;GetGeometry()-&gt;IndexToWorld(minMaxFilter-&gt;GetMaxIndex(*it), worldCoordinateMax);
m_Image-&gt;GetGeometry()-&gt;WorldToIndex(worldCoordinateMin, indexCoordinateMin);
m_Image-&gt;GetGeometry()-&gt;WorldToIndex(worldCoordinateMax, indexCoordinateMax);</span>
<span style = "background-color:#0f0"> minIndex.set_size(3);
maxIndex.set_size(3);</span>
// for (unsigned int i=0; i &lt; tmpMaxIndex.GetIndexDimension(); i++)
<span style = "background-color:#0f0"> for (unsigned int i = 0; i &lt; 3; i++)</span>
{
<span style = "background-color:#0f0"> minIndex[i] = indexCoordinateMin[i];
maxIndex[i] = indexCoordinateMax[i];
}</span>
<span style = "background-color:#0f0"> statObj.AddStatistic(mitk::ImageStatisticsConstants::MINIMUMPOSITION(), minIndex);
statObj.AddStatistic(mitk::ImageStatisticsConstants::MAXIMUMPOSITION(), maxIndex);</span>
<span style = "background-color:#0f0"> assert(std::abs(minMaxFilter-&gt;GetMax(*it) - imageStatisticsFilter-&gt;GetMaximum(*it)) &lt; mitk::eps);
assert(std::abs(minMaxFilter-&gt;GetMin(*it) - imageStatisticsFilter-&gt;GetMinimum(*it)) &lt; mitk::eps);</span>
<span style = "background-color:#0f0"> auto voxelVolume = GetVoxelVolume&lt;TPixel, VImageDimension&gt;(image);
auto numberOfVoxels =</span>
static_cast&lt;unsigned long&gt;(imageStatisticsFilter-&gt;GetSum(*it) / (double)imageStatisticsFilter-&gt;GetMean(*it));
<span style = "background-color:#0f0"> auto volume = static_cast&lt;double&gt;(numberOfVoxels) * voxelVolume;
auto rms = std::sqrt(std::pow(imageStatisticsFilter-&gt;GetMean(*it), 2.) +</span>
imageStatisticsFilter-&gt;GetVariance(*it)); // variance = sigma^2
<span style = "background-color:#0f0"> auto variance = imageStatisticsFilter-&gt;GetSigma(*it) * imageStatisticsFilter-&gt;GetSigma(*it);</span>
<span style = "background-color:#0f0"> statObj.AddStatistic(mitk::ImageStatisticsConstants::NUMBEROFVOXELS(), numberOfVoxels);
statObj.AddStatistic(mitk::ImageStatisticsConstants::VOLUME(), volume);
statObj.AddStatistic(mitk::ImageStatisticsConstants::MEAN(), imageStatisticsFilter-&gt;GetMean(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::MINIMUM(), imageStatisticsFilter-&gt;GetMinimum(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::MAXIMUM(), imageStatisticsFilter-&gt;GetMaximum(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::STANDARDDEVIATION(), imageStatisticsFilter-&gt;GetSigma(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::VARIANCE(), variance);
statObj.AddStatistic(mitk::ImageStatisticsConstants::SKEWNESS(), imageStatisticsFilter-&gt;GetSkewness(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::KURTOSIS(), imageStatisticsFilter-&gt;GetKurtosis(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::RMS(), rms);
statObj.AddStatistic(mitk::ImageStatisticsConstants::MPP(), imageStatisticsFilter-&gt;GetMPP(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::ENTROPY(), imageStatisticsFilter-&gt;GetEntropy(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::MEDIAN(), imageStatisticsFilter-&gt;GetMedian(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::UNIFORMITY(), imageStatisticsFilter-&gt;GetUniformity(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::UPP(), imageStatisticsFilter-&gt;GetUPP(*it));
statObj.m_Histogram = imageStatisticsFilter-&gt;GetHistogram(*it).GetPointer();</span>
<span style = "background-color:#0f0"> statisticContainerForLabelImage-&gt;SetStatisticsForTimeStep(timeStep, statObj);
++it;
}</span>
// swap maskGenerators back
<span style = "background-color:#0f0"> if (swapMasks)</span>
{
<span style = "background-color:#f00"> m_SecondaryMask = m_InternalMask;
m_InternalMask = nullptr;</span>
}
<span style = "background-color:#0f0"> }</span>
bool ImageStatisticsCalculator::IsUpdateRequired(LabelIndex label) const
<span style = "background-color:#0f0"> {
unsigned long thisClassTimeStamp = this-&gt;GetMTime();
unsigned long inputImageTimeStamp = m_Image-&gt;GetMTime();</span>
<span style = "background-color:#0f0"> auto it = m_StatisticContainers.find(label);
if (it == m_StatisticContainers.end())</span>
{
<span style = "background-color:#0f0"> return true;</span>
}
<span style = "background-color:#f00"> unsigned long statisticsTimeStamp = it-&gt;second-&gt;GetMTime();</span>
<span style = "background-color:#f00"> if (thisClassTimeStamp &gt; statisticsTimeStamp) // inputs have changed</span>
{
<span style = "background-color:#f00"> return true;</span>
}
<span style = "background-color:#f00"> if (inputImageTimeStamp &gt; statisticsTimeStamp) // image has changed</span>
{
<span style = "background-color:#f00"> return true;</span>
}
<span style = "background-color:#f00"> if (m_MaskGenerator.IsNotNull())</span>
{
<span style = "background-color:#f00"> unsigned long maskGeneratorTimeStamp = m_MaskGenerator-&gt;GetMTime();
if (maskGeneratorTimeStamp &gt; statisticsTimeStamp) // there is a mask generator and it has changed</span>
{
<span style = "background-color:#f00"> return true;</span>
}
}
<span style = "background-color:#f00"> if (m_SecondaryMaskGenerator.IsNotNull())</span>
{
<span style = "background-color:#f00"> unsigned long maskGeneratorTimeStamp = m_SecondaryMaskGenerator-&gt;GetMTime();
if (maskGeneratorTimeStamp &gt; statisticsTimeStamp) // there is a secondary mask generator and it has changed</span>
{
<span style = "background-color:#f00"> return true;</span>
}
}
<span style = "background-color:#f00"> return false;</span>
<span style = "background-color:#0f0"> }</span>
} // namespace mitk</pre>
</body>
</html>

File Metadata

Mime Type
text/x-c
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
729861
Default Alt Text
mitkImageStatisticsCalculator.cpp.html (30 KB)

Event Timeline