21 #include <itkLabelStatisticsImageFilter.h> 22 #include <itkMinimumMaximumImageCalculator.h> 23 #include <itkImageRegionIterator.h> 28 struct FirstOrderNumericParameterStruct {
30 double MinimumIntensity;
31 double MaximumIntensity;
36 template<
typename TPixel,
unsigned int VImageDimension>
40 typedef itk::Image<TPixel, VImageDimension>
ImageType;
41 typedef itk::Image<unsigned short, VImageDimension> MaskType;
43 typename MaskType::Pointer maskImage = MaskType::New();
49 double voxelVolume = 1;
50 for (
unsigned int i = 0; i < std::min<unsigned int>(3, VImageDimension); ++i)
51 voxelVolume *= itkImage->GetSpacing()[i];
56 double voxelSpace = 1;
57 for (
unsigned int i = 0; i < VImageDimension; ++i)
58 voxelSpace *= itkImage->GetSpacing()[i];
60 unsigned int numberOfBins = params.quantifier->GetBins();
61 std::vector<unsigned int> histogram;
62 histogram.resize(numberOfBins, 0);
66 double maximum = std::numeric_limits<double>::lowest();
68 double absoluteMaximum = std::numeric_limits<double>::lowest();
72 unsigned int numberOfVoxels = 0;
74 itk::ImageRegionIterator<ImageType> imageIter(itkImage, itkImage->GetLargestPossibleRegion());
75 itk::ImageRegionIterator<MaskType> maskIter(maskImage, maskImage->GetLargestPossibleRegion());
77 while (!imageIter.IsAtEnd())
79 double value = imageIter.Get();
81 absoluteMinimum = std::min<double>(minimum, value);
82 absoluteMaximum = std::max<double>(maximum, value);
83 if (maskIter.Get() > 0)
85 minimum = std::min<double>(minimum, value);
86 maximum = std::max<double>(maximum, value);
89 sumTwo += value * value;
90 sumThree += value * value*value;
92 histogram[params.quantifier->IntensityToIndex(value)] += 1;
103 unsigned int passedValues = 0;
104 double doubleNoOfVoxes = numberOfVoxels;
106 double lastIntensityWithValues = params.quantifier->IndexToMeanIntensity(0);
107 std::size_t modeIdx = 0;
110 double uniformity = 0;
112 std::vector<double> percentiles;
113 percentiles.resize(20, 0);
115 for (std::size_t idx = 0; idx < histogram.size(); ++idx)
117 unsigned int actualValues = histogram[idx];
119 for (std::size_t percentileIdx = 0; percentileIdx < percentiles.size(); ++percentileIdx)
121 double threshold = doubleNoOfVoxes * (percentileIdx + 1) *1.0 / (percentiles.size());
122 if ((passedValues < threshold) & ((passedValues + actualValues) >= threshold))
125 if (passedValues == std::floor(threshold))
127 percentiles[percentileIdx] = 0.5*(lastIntensityWithValues + params.quantifier->IndexToMeanIntensity(idx));
131 percentiles[percentileIdx] = params.quantifier->IndexToMeanIntensity(idx);
136 if ((passedValues < doubleNoOfVoxes * 0.5) & ((passedValues + actualValues) >= doubleNoOfVoxes * 0.5))
139 if (passedValues == std::floor(doubleNoOfVoxes * 0.5))
141 median = 0.5*(lastIntensityWithValues + params.quantifier->IndexToMeanIntensity(idx));
145 median = params.quantifier->IndexToMeanIntensity(idx);
149 if (actualValues > histogram[modeIdx])
154 if (actualValues > 0)
156 lastIntensityWithValues = params.quantifier->IndexToMeanIntensity(idx);
158 double currentProbability = actualValues / (1.0 *numberOfVoxels);
159 uniformity += currentProbability * currentProbability;
160 entropy += currentProbability * std::log(currentProbability) / std::log(2);
162 passedValues += actualValues;
164 double p10 = percentiles[1];
167 double p25idx = percentiles[4];
168 double p75idx = percentiles[14];
169 double p90 = percentiles[17];
171 double mean = sum / (numberOfVoxels);
172 double variance = sumTwo / (numberOfVoxels) - (mean*mean);
173 double energy = sumTwo;
174 double rootMeanSquare = std::sqrt(sumTwo / numberOfVoxels);
176 double sumAbsoluteDistanceToMean = 0;
177 double sumAbsoluteDistanceToMedian = 0;
178 double sumRobust = 0;
179 double sumRobustSquare = 0;
180 double sumRobustAbsolulteDistanceToMean = 0;
181 double sumValueMinusMean = 0;
182 double sumValueMinusMeanThree = 0;
183 double sumValueMinusMeanFour = 0;
184 unsigned int numberOfRobustVoxel = 0;
187 maskIter.GoToBegin();
188 imageIter.GoToBegin();
189 while (!imageIter.IsAtEnd())
191 if (maskIter.Get() > 0)
193 double value = imageIter.Get();
194 double valueMinusMean = value - mean;
196 sumAbsoluteDistanceToMean += std::abs<double>(valueMinusMean);
197 sumAbsoluteDistanceToMedian += std::abs<double>(value - median);
198 sumValueMinusMean += valueMinusMean;
199 sumValueMinusMeanThree += valueMinusMean * valueMinusMean * valueMinusMean;
200 sumValueMinusMeanFour += valueMinusMean * valueMinusMean * valueMinusMean * valueMinusMean;
202 if ((p10 <= value) & (value <= p90))
205 sumRobustSquare += value * value;
206 ++numberOfRobustVoxel;
212 double robustMean = sumRobust / numberOfRobustVoxel;
213 double robustVariance = sumRobustSquare / numberOfRobustVoxel - (robustMean * robustMean);
215 maskIter.GoToBegin();
216 imageIter.GoToBegin();
217 while (!imageIter.IsAtEnd())
219 if (maskIter.Get() > 0)
221 double value = imageIter.Get();
223 if ((p10 <= value) & (value <= p90))
225 sumRobustAbsolulteDistanceToMean += std::abs(value - robustMean);
234 double meanAbsoluteDeviation = sumAbsoluteDistanceToMean / numberOfVoxels;
235 double medianAbsoluteDeviation = sumAbsoluteDistanceToMedian / numberOfVoxels;
236 double robustMeanAbsoluteDeviation = sumRobustAbsolulteDistanceToMean / numberOfRobustVoxel;
237 double skewness = sumValueMinusMeanThree / numberOfVoxels / variance / std::sqrt(variance);
238 double kurtosis = sumValueMinusMeanFour / numberOfVoxels / variance / variance;
239 double interquantileRange = p75idx - p25idx;
240 double coefficientOfVariation = std::sqrt(variance) / mean;
241 double quantileCoefficientOfDispersion = (p75idx - p25idx) / (p75idx + p25idx);
242 double coveredImageRange = (maximum - minimum)/ (absoluteMaximum - absoluteMinimum) ;
244 featureList.push_back(std::make_pair(params.prefix +
"Mean", mean));
245 featureList.push_back(std::make_pair(params.prefix +
"Variance", variance));
246 featureList.push_back(std::make_pair(params.prefix +
"Skewness", skewness));
247 featureList.push_back(std::make_pair(params.prefix +
"Excess kurtosis", kurtosis-3));
248 featureList.push_back(std::make_pair(params.prefix +
"Median", median));
249 featureList.push_back(std::make_pair(params.prefix +
"Minimum", minimum));
250 featureList.push_back(std::make_pair(params.prefix +
"05th Percentile", percentiles[0]));
251 featureList.push_back(std::make_pair(params.prefix +
"10th Percentile", percentiles[1]));
252 featureList.push_back(std::make_pair(params.prefix +
"15th Percentile", percentiles[2]));
253 featureList.push_back(std::make_pair(params.prefix +
"20th Percentile", percentiles[3]));
254 featureList.push_back(std::make_pair(params.prefix +
"25th Percentile", percentiles[4]));
255 featureList.push_back(std::make_pair(params.prefix +
"30th Percentile", percentiles[5]));
256 featureList.push_back(std::make_pair(params.prefix +
"35th Percentile", percentiles[6]));
257 featureList.push_back(std::make_pair(params.prefix +
"40th Percentile", percentiles[7]));
258 featureList.push_back(std::make_pair(params.prefix +
"45th Percentile", percentiles[8]));
259 featureList.push_back(std::make_pair(params.prefix +
"50th Percentile", percentiles[9]));
260 featureList.push_back(std::make_pair(params.prefix +
"55th Percentile", percentiles[10]));
261 featureList.push_back(std::make_pair(params.prefix +
"60th Percentile", percentiles[11]));
262 featureList.push_back(std::make_pair(params.prefix +
"65th Percentile", percentiles[12]));
263 featureList.push_back(std::make_pair(params.prefix +
"70th Percentile", percentiles[13]));
264 featureList.push_back(std::make_pair(params.prefix +
"75th Percentile", percentiles[14]));
265 featureList.push_back(std::make_pair(params.prefix +
"80th Percentile", percentiles[15]));
266 featureList.push_back(std::make_pair(params.prefix +
"85th Percentile", percentiles[16]));
267 featureList.push_back(std::make_pair(params.prefix +
"90th Percentile", percentiles[17]));
268 featureList.push_back(std::make_pair(params.prefix +
"95th Percentile", percentiles[18]));
269 featureList.push_back(std::make_pair(params.prefix +
"Maximum", maximum));
270 featureList.push_back(std::make_pair(params.prefix +
"Interquantile range", interquantileRange));
271 featureList.push_back(std::make_pair(params.prefix +
"Range", maximum-minimum));
272 featureList.push_back(std::make_pair(params.prefix +
"Mean absolute deviation", meanAbsoluteDeviation));
273 featureList.push_back(std::make_pair(params.prefix +
"Robust mean absolute deviation", robustMeanAbsoluteDeviation));
274 featureList.push_back(std::make_pair(params.prefix +
"Median absolute deviation", medianAbsoluteDeviation));
275 featureList.push_back(std::make_pair(params.prefix +
"Coefficient of variation", coefficientOfVariation));
276 featureList.push_back(std::make_pair(params.prefix +
"Quantile coefficient of dispersion", quantileCoefficientOfDispersion));
277 featureList.push_back(std::make_pair(params.prefix +
"Energy", energy));
278 featureList.push_back(std::make_pair(params.prefix +
"Root mean square", rootMeanSquare));
280 featureList.push_back(std::make_pair(params.prefix +
"Standard Deviation", std::sqrt(variance)));
281 featureList.push_back(std::make_pair(params.prefix +
"Kurtosis", kurtosis));
282 featureList.push_back(std::make_pair(params.prefix +
"Robust mean", robustMean));
283 featureList.push_back(std::make_pair(params.prefix +
"Robust variance", robustVariance));
284 featureList.push_back(std::make_pair(params.prefix +
"Covered image intensity range", coveredImageRange));
285 featureList.push_back(std::make_pair(params.prefix +
"Mode index", modeIdx));
286 featureList.push_back(std::make_pair(params.prefix +
"Mode value", params.quantifier->IndexToMeanIntensity(modeIdx)));
287 featureList.push_back(std::make_pair(params.prefix +
"Mode probability", histogram[modeIdx] / (1.0*numberOfVoxels)));
288 featureList.push_back(std::make_pair(params.prefix +
"Entropy", entropy));
289 featureList.push_back(std::make_pair(params.prefix +
"Uniformtiy", uniformity));
290 featureList.push_back(std::make_pair(params.prefix +
"Number of voxels", numberOfVoxels));
291 featureList.push_back(std::make_pair(params.prefix +
"Sum of voxels", sum));
292 featureList.push_back(std::make_pair(params.prefix +
"Voxel space", voxelSpace));
293 featureList.push_back(std::make_pair(params.prefix +
"Voxel volume", voxelVolume));
294 featureList.push_back(std::make_pair(params.prefix +
"Image Dimension", VImageDimension));
302 SetLongName(
"first-order-numeric");
303 SetFeatureClassName(
"First Order Numeric");
308 InitializeQuantifier(image, mask);
311 FirstOrderNumericParameterStruct params;
313 params.quantifier = GetQuantifier();
314 params.MinimumIntensity = GetQuantifier()->GetMinimum();
315 params.MaximumIntensity = GetQuantifier()->GetMaximum();
316 params.Bins = GetQuantifier()->GetBins();
317 params.prefix = FeatureDescriptionPrefix();
332 std::string name = GetOptionPrefix();
335 AddQuantifierArguments(parser);
341 auto parsedArgs = GetParameter();
342 if (parsedArgs.count(GetLongName()))
344 InitializeQuantifierFromParameters(feature, maskNoNAN);
345 MITK_INFO <<
"Start calculating first order features ....";
347 featureList.insert(featureList.end(), localResults.begin(), localResults.end());
348 MITK_INFO <<
"Finished calculating first order features....";
354 return QuantifierParameterString();
std::string GetCurrentFeatureEncoding() override
Adds an additional Separator to the name of the feature, which encodes the used parameters.
#define AccessByItk_3(mitkImage, itkImageTypeFunction, arg1, arg2, arg3)
std::vector< std::string > FeatureNameListType
itk::Image< unsigned char, 3 > ImageType
void CalculateFeaturesUsingParameters(const Image::Pointer &feature, const Image::Pointer &mask, const Image::Pointer &maskNoNAN, FeatureListType &featureList) override
Calculates the feature of this abstact interface. Does not necessarily considers the parameter settin...
GIFFirstOrderNumericStatistics()
void addArgument(const std::string &longarg, const std::string &shortarg, Type type, const std::string &argLabel, const std::string &argHelp=std::string(), const us::Any &defaultValue=us::Any(), bool optional=true, bool ignoreRest=false, bool deprecated=false, mitkCommandLineParser::Channel channel=mitkCommandLineParser::Channel::None)
FeatureNameListType GetFeatureNames() override
Returns a list of the names of all features that are calculated from this class.
std::vector< std::pair< std::string, double > > FeatureListType
mitk::Image::Pointer image
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
mitk::Image::Pointer mask
void CalculateFirstOrderStatistics(itk::Image< TPixel, VImageDimension > *itkImage, mitk::Image::Pointer mask, mitk::GIFFirstOrderNumericStatistics::FeatureListType &featureList, FirstOrderNumericParameterStruct params)
void CalculateFeatures(mitk::CoocurenceMatrixHolder &holder, mitk::CoocurenceMatrixFeatures &results)
void AddArguments(mitkCommandLineParser &parser) override
FeatureListType CalculateFeatures(const Image::Pointer &image, const Image::Pointer &feature) override
Calculates the First Order Features based on a binned version of the image.