Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F1546955
mitkImageStatisticsCalculator.cpp.html
j762e (Jan Sahrhage)
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Authored By
j762e
Apr 3 2020, 1:46 PM
2020-04-03 13:46:43 (UTC+2)
Size
30 KB
Referenced Files
None
Subscribers
None
mitkImageStatisticsCalculator.cpp.html
View Options
<!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
<
mitkExtendedLabelStatisticsImageFilter.h
>
#include
<
mitkExtendedStatisticsImageFilter.h
>
#include
<
mitkImage.h
>
#include
<
mitkImageAccessByItk.h
>
#include
<
mitkImageCast.h
>
#include
<
mitkImageStatisticsConstants.h
>
#include
<
mitkImageTimeSelector.h
>
#include
<
mitkImageToItk.h
>
#include
<
mitkMaskUtilities.h
>
#include
<
mitkMinMaxImageFilterWithIndex.h
>
#include
<
mitkMinMaxLabelmageFilterWithIndex.h
>
#include
<
mitkitkMaskImageFilter.h
>
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-
>
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-
>
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-
>
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-
>
Modified();
this-
>
m_UseBinSizeOverNBins = false;
</span>
}
<span
style =
"background-color:#f00"
>
if (m_UseBinSizeOverNBins)
</span>
{
<span
style =
"background-color:#f00"
>
this-
>
Modified();
this-
>
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-
>
Modified();
this-
>
m_UseBinSizeOverNBins = true;
</span>
}
<span
style =
"background-color:#f00"
>
if (!m_UseBinSizeOverNBins)
</span>
{
<span
style =
"background-color:#f00"
>
this-
>
Modified();
this-
>
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()
<<
"no image";
</span>
}
<span
style =
"background-color:#0f0"
>
if (!m_Image-
>
IsInitialized())
</span>
{
<span
style =
"background-color:#f00"
>
mitkThrow()
<<
"Image not initialized!";
</span>
}
<span
style =
"background-color:#0f0"
>
if (IsUpdateRequired(label))
</span>
{
<span
style =
"background-color:#0f0"
>
auto timeGeometry = m_Image-
>
GetTimeGeometry();
</span>
// always compute statistics on all timesteps
<span
style =
"background-color:#0f0"
>
for (unsigned int timeStep = 0; timeStep
<
m_Image-
>
GetTimeSteps(); timeStep++)
</span>
{
<span
style =
"background-color:#0f0"
>
if (m_MaskGenerator.IsNotNull())
</span>
{
<span
style =
"background-color:#0f0"
>
m_MaskGenerator-
>
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-
>
Modified();
m_InternalMask = m_MaskGenerator-
>
GetMask();
if (m_MaskGenerator-
>
GetReferenceImage().IsNotNull())
</span>
{
<span
style =
"background-color:#0f0"
>
m_InternalImageForStatistics = m_MaskGenerator-
>
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-
>
SetTimeStep(timeStep);
m_SecondaryMask = m_SecondaryMaskGenerator-
>
GetMask();
</span>
}
<span
style =
"background-color:#0f0"
>
ImageTimeSelector::Pointer imgTimeSel = ImageTimeSelector::New();
imgTimeSel-
>
SetInput(m_InternalImageForStatistics);
imgTimeSel-
>
SetTimeNr(timeStep);
imgTimeSel-
>
UpdateLargestPossibleRegion();
imgTimeSel-
>
Update();
m_ImageTimeSlice = imgTimeSel-
>
GetOutput();
</span>
// Calculate statistics with/without mask
<span
style =
"background-color:#0f0"
>
if (m_MaskGenerator.IsNull()
&&
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-
>
second).GetPointer();
</span>
<span
style =
"background-color:#f00"
>
}
</span>
else
{
<span
style =
"background-color:#f00"
>
mitkThrow()
<<
"unknown label";
return nullptr;
</span>
}
<span
style =
"background-color:#f00"
>
}
</span>
template
<
typename TPixel, unsigned int VImageDimension
>
void ImageStatisticsCalculator::InternalCalculateStatisticsUnmasked(
typename itk::Image
<
TPixel, VImageDimension
>
*image, const TimeGeometry *timeGeometry, TimeStepType timeStep)
<span
style =
"background-color:#0f0"
>
{
</span>
typedef typename itk::Image
<
TPixel, VImageDimension
>
ImageType;
typedef typename itk::ExtendedStatisticsImageFilter
<
ImageType
>
ImageStatisticsFilterType;
typedef typename itk::MinMaxImageFilterWithIndex
<
ImageType
>
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-
>
second;
}
</span>
else
{
<span
style =
"background-color:#0f0"
>
statisticContainerForImage = ImageStatisticsContainer::New();
statisticContainerForImage-
>
SetTimeGeometry(const_cast
<
mitk::TimeGeometry*
>
(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-
>
SetInput(image);
statisticsFilter-
>
SetCoordinateTolerance(0.001);
statisticsFilter-
>
SetDirectionTolerance(0.001);
</span>
// TODO: this is single threaded. Implement our own image filter that does this multi threaded
// typename itk::MinimumMaximumImageCalculator
<
ImageType
>
::Pointer imgMinMaxFilter =
// itk::MinimumMaximumImageCalculator
<
ImageType
>
::New(); imgMinMaxFilter-
>
SetImage(image);
// imgMinMaxFilter-
>
Compute();
<span
style =
"background-color:#0f0"
>
vnl_vector
<
int
>
minIndex, maxIndex;
</span>
<span
style =
"background-color:#0f0"
>
typename MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New();
minMaxFilter-
>
SetInput(image);
minMaxFilter-
>
UpdateLargestPossibleRegion();
typename ImageType::PixelType minval = minMaxFilter-
>
GetMin();
typename ImageType::PixelType maxval = minMaxFilter-
>
GetMax();
</span>
<span
style =
"background-color:#0f0"
>
typename ImageType::IndexType tmpMinIndex = minMaxFilter-
>
GetMinIndex();
typename ImageType::IndexType tmpMaxIndex = minMaxFilter-
>
GetMaxIndex();
</span>
// typename ImageType::IndexType tmpMinIndex = imgMinMaxFilter-
>
GetIndexOfMinimum();
// typename ImageType::IndexType tmpMaxIndex = imgMinMaxFilter-
>
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
<
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
<
double
>
(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-
>
SetHistogramParameters(nBinsForHistogram, minval, maxval);
</span>
try
{
<span
style =
"background-color:#0f0"
>
statisticsFilter-
>
Update();
</span>
}
catch (const itk::ExceptionObject
&
e)
<span
style =
"background-color:#f00"
>
{
mitkThrow()
<<
"Image statistics calculation failed due to following ITK Exception: \n "
<<
e.what();
}
</span>
<span
style =
"background-color:#0f0"
>
auto voxelVolume = GetVoxelVolume
<
TPixel, VImageDimension
>
(image);
</span>
<span
style =
"background-color:#0f0"
>
auto numberOfPixels = image-
>
GetLargestPossibleRegion().GetNumberOfPixels();
auto volume = static_cast
<
double
>
(numberOfPixels) * voxelVolume;
auto variance = statisticsFilter-
>
GetSigma() * statisticsFilter-
>
GetSigma();
auto rms =
</span>
std::sqrt(std::pow(statisticsFilter-
>
GetMean(), 2.) + statisticsFilter-
>
GetVariance()); // variance = sigma^2
<span
style =
"background-color:#0f0"
>
statObj.AddStatistic(mitk::ImageStatisticsConstants::NUMBEROFVOXELS(),
</span>
static_cast
<
ImageStatisticsContainer::VoxelCountType
>
(numberOfPixels));
<span
style =
"background-color:#0f0"
>
statObj.AddStatistic(mitk::ImageStatisticsConstants::VOLUME(), volume);
statObj.AddStatistic(mitk::ImageStatisticsConstants::MEAN(), statisticsFilter-
>
GetMean());
statObj.AddStatistic(mitk::ImageStatisticsConstants::MINIMUM(),
</span>
static_cast
<
ImageStatisticsContainer::RealType
>
(statisticsFilter-
>
GetMinimum()));
<span
style =
"background-color:#0f0"
>
statObj.AddStatistic(mitk::ImageStatisticsConstants::MAXIMUM(),
</span>
static_cast
<
ImageStatisticsContainer::RealType
>
(statisticsFilter-
>
GetMaximum()));
<span
style =
"background-color:#0f0"
>
statObj.AddStatistic(mitk::ImageStatisticsConstants::STANDARDDEVIATION(), statisticsFilter-
>
GetSigma());
statObj.AddStatistic(mitk::ImageStatisticsConstants::VARIANCE(), variance);
statObj.AddStatistic(mitk::ImageStatisticsConstants::SKEWNESS(), statisticsFilter-
>
GetSkewness());
statObj.AddStatistic(mitk::ImageStatisticsConstants::KURTOSIS(), statisticsFilter-
>
GetKurtosis());
statObj.AddStatistic(mitk::ImageStatisticsConstants::RMS(), rms);
statObj.AddStatistic(mitk::ImageStatisticsConstants::MPP(), statisticsFilter-
>
GetMPP());
statObj.AddStatistic(mitk::ImageStatisticsConstants::ENTROPY(), statisticsFilter-
>
GetEntropy());
statObj.AddStatistic(mitk::ImageStatisticsConstants::MEDIAN(), statisticsFilter-
>
GetMedian());
statObj.AddStatistic(mitk::ImageStatisticsConstants::UNIFORMITY(), statisticsFilter-
>
GetUniformity());
statObj.AddStatistic(mitk::ImageStatisticsConstants::UPP(), statisticsFilter-
>
GetUPP());
statObj.m_Histogram = statisticsFilter-
>
GetHistogram().GetPointer();
statisticContainerForImage-
>
SetStatisticsForTimeStep(timeStep, statObj);
}
</span>
template
<
typename TPixel, unsigned int VImageDimension
>
double ImageStatisticsCalculator::GetVoxelVolume(typename itk::Image
<
TPixel, VImageDimension
>
*image) const
<span
style =
"background-color:#0f0"
>
{
auto spacing = image-
>
GetSpacing();
double voxelVolume = 1.;
for (unsigned int i = 0; i
<
image-
>
GetImageDimension(); i++)
</span>
{
<span
style =
"background-color:#0f0"
>
voxelVolume *= spacing[i];
}
return voxelVolume;
}
</span>
template
<
typename TPixel, unsigned int VImageDimension
>
void ImageStatisticsCalculator::InternalCalculateStatisticsMasked(typename itk::Image
<
TPixel, VImageDimension
>
*image,
const TimeGeometry *timeGeometry,
unsigned int timeStep)
<span
style =
"background-color:#0f0"
>
{
</span>
typedef itk::Image
<
TPixel, VImageDimension
>
ImageType;
typedef itk::Image
<
MaskPixelType, VImageDimension
>
MaskType;
typedef typename MaskType::PixelType LabelPixelType;
typedef itk::ExtendedLabelStatisticsImageFilter
<
ImageType, MaskType
>
ImageStatisticsFilterType;
typedef MaskUtilities
<
TPixel, VImageDimension
>
MaskUtilType;
typedef typename itk::MinMaxLabelImageFilterWithIndex
<
ImageType, MaskType
>
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()
&&
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
<
MaskPixelType, VImageDimension
>
(m_InternalMask);
</span>
}
catch (const itk::ExceptionObject
&
)
<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-
>
GetDimension() == 2
&&
</span>
(m_SecondaryMask-
>
GetDimension() == 3 || m_SecondaryMask-
>
GetDimension() == 4))
{
<span
style =
"background-color:#f00"
>
mitk::Image::ConstPointer old_img = m_SecondaryMaskGenerator-
>
GetReferenceImage();
m_SecondaryMaskGenerator-
>
SetInputImage(m_MaskGenerator-
>
GetReferenceImage());
m_SecondaryMask = m_SecondaryMaskGenerator-
>
GetMask();
m_SecondaryMaskGenerator-
>
SetInputImage(old_img);
}
typename MaskType::Pointer secondaryMaskImage = MaskType::New();
secondaryMaskImage = ImageToItkImage
<
MaskPixelType, VImageDimension
>
(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
<
MaskPixelType, VImageDimension
>
::Pointer secondaryMaskMaskUtil =
</span>
MaskUtilities
<
MaskPixelType, VImageDimension
>
::New();
<span
style =
"background-color:#f00"
>
secondaryMaskMaskUtil-
>
SetImage(secondaryMaskImage.GetPointer());
secondaryMaskMaskUtil-
>
SetMask(maskImage.GetPointer());
typename MaskType::Pointer adaptedSecondaryMaskImage = secondaryMaskMaskUtil-
>
ExtractMaskImageRegion();
</span>
<span
style =
"background-color:#f00"
>
typename itk::MaskImageFilter2
<
MaskType, MaskType, MaskType
>
::Pointer maskFilter =
</span>
itk::MaskImageFilter2
<
MaskType, MaskType, MaskType
>
::New();
<span
style =
"background-color:#f00"
>
maskFilter-
>
SetInput1(maskImage);
maskFilter-
>
SetInput2(adaptedSecondaryMaskImage);
maskFilter-
>
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-
>
UpdateLargestPossibleRegion();
maskImage = maskFilter-
>
GetOutput();
}
</span>
<span
style =
"background-color:#0f0"
>
typename MaskUtilType::Pointer maskUtil = MaskUtilType::New();
maskUtil-
>
SetImage(image);
maskUtil-
>
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-
>
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-
>
SetInput(adaptedImage);
minMaxFilter-
>
SetLabelInput(maskImage);
minMaxFilter-
>
UpdateLargestPossibleRegion();
</span>
// set histogram parameters for each label individually (min/max may be different for each label)
typedef typename std::map
<
LabelPixelType, InputImgPixelType
>
MapType;
typedef typename std::pair
<
LabelPixelType, InputImgPixelType
>
PairType;
<span
style =
"background-color:#0f0"
>
std::vector
<
LabelPixelType
>
relevantLabels = minMaxFilter-
>
GetRelevantLabels();
MapType minVals;
MapType maxVals;
std::map
<
LabelPixelType, unsigned int
>
nBins;
</span>
<span
style =
"background-color:#0f0"
>
for (LabelPixelType label : relevantLabels)
</span>
{
<span
style =
"background-color:#0f0"
>
minVals.insert(PairType(label, minMaxFilter-
>
GetMin(label)));
maxVals.insert(PairType(label, minMaxFilter-
>
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
<
double
>
(std::ceil(minMaxFilter-
>
GetMax(label) - minMaxFilter-
>
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
<
LabelPixelType, unsigned int
>
(label, nBinsForHistogram));
}
</span>
<span
style =
"background-color:#0f0"
>
typename ImageStatisticsFilterType::Pointer imageStatisticsFilter = ImageStatisticsFilterType::New();
imageStatisticsFilter-
>
SetDirectionTolerance(0.001);
imageStatisticsFilter-
>
SetCoordinateTolerance(0.001);
imageStatisticsFilter-
>
SetInput(adaptedImage);
imageStatisticsFilter-
>
SetLabelInput(maskImage);
imageStatisticsFilter-
>
SetHistogramParametersForLabels(nBins, minVals, maxVals);
imageStatisticsFilter-
>
Update();
</span>
<span
style =
"background-color:#0f0"
>
std::list
<
int
>
labels = imageStatisticsFilter-
>
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-
>
second;
}
</span>
// create new statisticContainer
else
{
<span
style =
"background-color:#0f0"
>
statisticContainerForLabelImage = ImageStatisticsContainer::New();
statisticContainerForLabelImage-
>
SetTimeGeometry(const_cast
<
mitk::TimeGeometry*
>
(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
<
int
>
minIndex, maxIndex;
mitk::Point3D worldCoordinateMin;
mitk::Point3D worldCoordinateMax;
mitk::Point3D indexCoordinateMin;
mitk::Point3D indexCoordinateMax;
m_InternalImageForStatistics-
>
GetGeometry()-
>
IndexToWorld(minMaxFilter-
>
GetMinIndex(*it), worldCoordinateMin);
m_InternalImageForStatistics-
>
GetGeometry()-
>
IndexToWorld(minMaxFilter-
>
GetMaxIndex(*it), worldCoordinateMax);
m_Image-
>
GetGeometry()-
>
WorldToIndex(worldCoordinateMin, indexCoordinateMin);
m_Image-
>
GetGeometry()-
>
WorldToIndex(worldCoordinateMax, indexCoordinateMax);
</span>
<span
style =
"background-color:#0f0"
>
minIndex.set_size(3);
maxIndex.set_size(3);
</span>
// for (unsigned int i=0; i
<
tmpMaxIndex.GetIndexDimension(); i++)
<span
style =
"background-color:#0f0"
>
for (unsigned int i = 0; i
<
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-
>
GetMax(*it) - imageStatisticsFilter-
>
GetMaximum(*it))
<
mitk::eps);
assert(std::abs(minMaxFilter-
>
GetMin(*it) - imageStatisticsFilter-
>
GetMinimum(*it))
<
mitk::eps);
</span>
<span
style =
"background-color:#0f0"
>
auto voxelVolume = GetVoxelVolume
<
TPixel, VImageDimension
>
(image);
auto numberOfVoxels =
</span>
static_cast
<
unsigned long
>
(imageStatisticsFilter-
>
GetSum(*it) / (double)imageStatisticsFilter-
>
GetMean(*it));
<span
style =
"background-color:#0f0"
>
auto volume = static_cast
<
double
>
(numberOfVoxels) * voxelVolume;
auto rms = std::sqrt(std::pow(imageStatisticsFilter-
>
GetMean(*it), 2.) +
</span>
imageStatisticsFilter-
>
GetVariance(*it)); // variance = sigma^2
<span
style =
"background-color:#0f0"
>
auto variance = imageStatisticsFilter-
>
GetSigma(*it) * imageStatisticsFilter-
>
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-
>
GetMean(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::MINIMUM(), imageStatisticsFilter-
>
GetMinimum(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::MAXIMUM(), imageStatisticsFilter-
>
GetMaximum(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::STANDARDDEVIATION(), imageStatisticsFilter-
>
GetSigma(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::VARIANCE(), variance);
statObj.AddStatistic(mitk::ImageStatisticsConstants::SKEWNESS(), imageStatisticsFilter-
>
GetSkewness(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::KURTOSIS(), imageStatisticsFilter-
>
GetKurtosis(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::RMS(), rms);
statObj.AddStatistic(mitk::ImageStatisticsConstants::MPP(), imageStatisticsFilter-
>
GetMPP(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::ENTROPY(), imageStatisticsFilter-
>
GetEntropy(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::MEDIAN(), imageStatisticsFilter-
>
GetMedian(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::UNIFORMITY(), imageStatisticsFilter-
>
GetUniformity(*it));
statObj.AddStatistic(mitk::ImageStatisticsConstants::UPP(), imageStatisticsFilter-
>
GetUPP(*it));
statObj.m_Histogram = imageStatisticsFilter-
>
GetHistogram(*it).GetPointer();
</span>
<span
style =
"background-color:#0f0"
>
statisticContainerForLabelImage-
>
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-
>
GetMTime();
unsigned long inputImageTimeStamp = m_Image-
>
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-
>
second-
>
GetMTime();
</span>
<span
style =
"background-color:#f00"
>
if (thisClassTimeStamp
>
statisticsTimeStamp) // inputs have changed
</span>
{
<span
style =
"background-color:#f00"
>
return true;
</span>
}
<span
style =
"background-color:#f00"
>
if (inputImageTimeStamp
>
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-
>
GetMTime();
if (maskGeneratorTimeStamp
>
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-
>
GetMTime();
if (maskGeneratorTimeStamp
>
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
Details
Attached
Mime Type
text/x-c
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
729861
Default Alt Text
mitkImageStatisticsCalculator.cpp.html (30 KB)
Attached To
Mode
T27289: Different coverage results with OpenCppCoverage and Gcov
Attached
Detach File
Event Timeline
Log In to Comment