diff --git a/Modules/Classification/CLUtilities/include/mitkGIFIntensityVolumeHistogramFeatures.h b/Modules/Classification/CLUtilities/include/mitkGIFIntensityVolumeHistogramFeatures.h index f0ade18ac4..a28c48a689 100644 --- a/Modules/Classification/CLUtilities/include/mitkGIFIntensityVolumeHistogramFeatures.h +++ b/Modules/Classification/CLUtilities/include/mitkGIFIntensityVolumeHistogramFeatures.h @@ -1,84 +1,82 @@ /*============================================================================ 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. ============================================================================*/ #ifndef mitkGIFIntensityVolumeHistogramFeatures_h #define mitkGIFIntensityVolumeHistogramFeatures_h #include #include #include namespace mitk { /** * \brief Calculates the Intensity Volume Histogram features * * This class can be used to calculate the volume histogram and features that are calculated from * it. It is based on the intensity-volume histogram (IVH) which describes the relation between the * grey level index i (and the corresponding intensity \f$x_i\f$) and the volume fraction \f$f\f$ that * with an intensity that is equal or greater than \f$x_i\f$. This feature is original proposed in * El Naqa et al. Exploring feature-based approaches in PET images for prediciting cancer treatment outcomes. * Pattern recognition 2009. * * This feature calculator is activated by the option "-intensity-volume-histogram" or "-ivoh". * Beside the configuration of the histogram, which follows the describtion given in AbstractGlobalImageFeature * there are no additional parameters to configure this feature. Remark that, different from other features, * the number of bins is 1000 by default and not 256. * * The features are calculated based on a mask. It is assumed that the mask is * of the type of an unsigned short image and all voxels with an value of greater than zero * are treated as masked. * * The resulting features are: * - Intensity Volume Histogram::Volume fration at 0.10 intensity: The volume fraction with an intensity * of greater or equal to 10% of the maximum intensity. * - Intensity Volume Histogram::Volume fration at 0.90 intensity: The volume fraction with an intensity * of greater or equal to 90% of the maximum intensity. * - Intensity Volume Histogram::Intensity at 0.10 volume: The highest intensity so that at least * 10% of the masked image area has the same or higher intensity. * - Intensity Volume Histogram::Intensity at 0.90 volume: The highest intensity so that at least * 10% of the masked image area has the same or higher intensity. * - Intensity Volume Histogram::Difference volume fration at 0.10 and 0.90 intensity: The difference * between the volume fraction at 10% intensity and 90% intensity. * - Intensity Volume Histogram::Difference intensity at 0.10 and 0.90 volume: The intensity difference * between the intenstiy of 90% of the volume and 10% volume. * - Intensity Volume Histogram::Area under IVH curve: If the IVH is interpreted as curve, this value represents * the area under the curve. It is calculated using the bin indexes rather than the intensity values. */ class MITKCLUTILITIES_EXPORT GIFIntensityVolumeHistogramFeatures : public AbstractGlobalImageFeature { public: mitkClassMacro(GIFIntensityVolumeHistogramFeatures, AbstractGlobalImageFeature); - itkFactorylessNewMacro(Self); - itkCloneMacro(Self); + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); - GIFIntensityVolumeHistogramFeatures(); + GIFIntensityVolumeHistogramFeatures(); /** * \brief Calculates the Cooccurence-Matrix based features for this class. */ - FeatureListType CalculateFeatures(const Image::Pointer & image, const Image::Pointer &feature) override; + FeatureListType CalculateFeatures(const Image::Pointer & image, const Image::Pointer &mask) override; /** * \brief Returns a list of the names of all features that are calculated from this class */ FeatureNameListType GetFeatureNames() override; void AddArguments(mitkCommandLineParser &parser) override; void CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &mask, const Image::Pointer &maskNoNAN, FeatureListType &featureList) override; std::string GetCurrentFeatureEncoding() override; - - private: }; } #endif //mitkGIFIntensityVolumeHistogramFeatures_h diff --git a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFIntensityVolumeHistogramFeatures.cpp b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFIntensityVolumeHistogramFeatures.cpp index d2ecb1f42d..c520c1d3d7 100644 --- a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFIntensityVolumeHistogramFeatures.cpp +++ b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFIntensityVolumeHistogramFeatures.cpp @@ -1,169 +1,169 @@ /*============================================================================ 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 // MITK #include #include #include #include // ITK #include #include // STL #include -struct GIFIntensityVolumeHistogramFeaturesParameters +namespace { - mitk::IntensityQuantifier::Pointer quantifier; - std::string prefix; -}; - + struct GIFIntensityVolumeHistogramFeaturesParameters + { + mitk::IntensityQuantifier::Pointer quantifier; + std::string prefix; + }; -template -static void -CalculateIntensityPeak(itk::Image* itkImage, mitk::Image::Pointer mask, GIFIntensityVolumeHistogramFeaturesParameters params, mitk::GIFIntensityVolumeHistogramFeatures::FeatureListType & featureList) -{ - typedef itk::Image ImageType; - typedef itk::Image MaskType; + template + void CalculateIntensityPeak(itk::Image* itkImage, mitk::Image::Pointer mask, GIFIntensityVolumeHistogramFeaturesParameters params, mitk::GIFIntensityVolumeHistogramFeatures::FeatureListType& featureList) + { + typedef itk::Image ImageType; + typedef itk::Image MaskType; - typename MaskType::Pointer itkMask = MaskType::New(); - mitk::CastToItkImage(mask, itkMask); + typename MaskType::Pointer itkMask = MaskType::New(); + mitk::CastToItkImage(mask, itkMask); - mitk::IntensityQuantifier::Pointer quantifier = params.quantifier; - std::string prefix = params.prefix; + mitk::IntensityQuantifier::Pointer quantifier = params.quantifier; + std::string prefix = params.prefix; - itk::ImageRegionConstIterator iter(itkImage, itkImage->GetLargestPossibleRegion()); - itk::ImageRegionConstIterator iterMask(itkMask, itkMask->GetLargestPossibleRegion()); + itk::ImageRegionConstIterator iter(itkImage, itkImage->GetLargestPossibleRegion()); + itk::ImageRegionConstIterator iterMask(itkMask, itkMask->GetLargestPossibleRegion()); - MITK_INFO << "Quantification: " << quantifier->GetMinimum() << " to " << quantifier->GetMaximum() << " with " << quantifier->GetBins()<< " bins"; + MITK_INFO << "Quantification: " << quantifier->GetMinimum() << " to " << quantifier->GetMaximum() << " with " << quantifier->GetBins() << " bins"; - iter.GoToBegin(); - iterMask.GoToBegin(); - std::vector hist; - hist.resize(quantifier->GetBins() , 0); + iter.GoToBegin(); + iterMask.GoToBegin(); + std::vector hist; + hist.resize(quantifier->GetBins(), 0); - int count = 0; - while (!iter.IsAtEnd()) - { - if (iterMask.Get() > 0) + int count = 0; + while (!iter.IsAtEnd()) { - double value = iter.Get(); - //std::size_t index = std::floor((value - minimum) / (maximum - minimum) * (bins-1)); - std::size_t index = quantifier->IntensityToIndex(value); - ++count; - hist[index] += 1.0;// / count; + if (iterMask.Get() > 0) + { + double value = iter.Get(); + //std::size_t index = std::floor((value - minimum) / (maximum - minimum) * (bins-1)); + std::size_t index = quantifier->IntensityToIndex(value); + ++count; + hist[index] += 1.0;// / count; + } + ++iterMask; + ++iter; } - ++iterMask; - ++iter; - } - bool notFoundIntenstiy010 = true; - bool notFoundIntenstiy090 = true; + bool notFoundIntenstiy010 = true; + bool notFoundIntenstiy090 = true; - double intensity010 = -1; - double intensity090 = -1; - double fraction = 0; - double auc = 0; - bool firstRound = true; - for (int i = quantifier->GetBins()-1; i >= 0; --i) - { - hist[i] /= count; - hist[i] += fraction; - fraction = hist[i]; - if (!firstRound) + double intensity010 = -1; + double intensity090 = -1; + double fraction = 0; + double auc = 0; + bool firstRound = true; + for (int i = quantifier->GetBins() - 1; i >= 0; --i) { - auc += 0.5 * (hist[i] + hist[i+1]) / (quantifier->GetBins()-1); + hist[i] /= count; + hist[i] += fraction; + fraction = hist[i]; + if (!firstRound) + { + auc += 0.5 * (hist[i] + hist[i + 1]) / (quantifier->GetBins() - 1); + } + firstRound = false; + + if (notFoundIntenstiy010 && fraction > 0.1) + { + intensity010 = quantifier->IndexToMeanIntensity(i + 1); + notFoundIntenstiy010 = false; + } + if (notFoundIntenstiy090 && fraction > 0.9) + { + intensity090 = quantifier->IndexToMeanIntensity(i + 1); + notFoundIntenstiy090 = false; + } } - firstRound = false; - if (notFoundIntenstiy010 && fraction > 0.1) - { - intensity010 = quantifier->IndexToMeanIntensity(i + 1); - notFoundIntenstiy010 = false; - } - if (notFoundIntenstiy090 && fraction > 0.9) - { - intensity090 = quantifier->IndexToMeanIntensity(i + 1); - notFoundIntenstiy090 = false; - } + unsigned int index010 = std::ceil(quantifier->GetBins() * 0.1); + unsigned int index090 = std::floor(quantifier->GetBins() * 0.9); + + featureList.push_back(std::make_pair(prefix + "Volume fraction at 0.10 intensity", hist[index010])); + featureList.push_back(std::make_pair(prefix + "Volume fraction at 0.90 intensity", hist[index090])); + featureList.push_back(std::make_pair(prefix + "Intensity at 0.10 volume", intensity010)); + featureList.push_back(std::make_pair(prefix + "Intensity at 0.90 volume", intensity090)); + featureList.push_back(std::make_pair(prefix + "Difference volume fraction at 0.10 and 0.90 intensity", std::abs(hist[index010] - hist[index090]))); + featureList.push_back(std::make_pair(prefix + "Difference intensity at 0.10 and 0.90 volume", std::abs(intensity090 - intensity010))); + featureList.push_back(std::make_pair(prefix + "Area under IVH curve", auc)); + //featureList.push_back(std::make_pair("Local Intensity Global Intensity Peak", globalPeakValue)); } - - unsigned int index010 = std::ceil(quantifier->GetBins() * 0.1); - unsigned int index090 = std::floor(quantifier->GetBins() * 0.9); - - featureList.push_back(std::make_pair(prefix + "Volume fraction at 0.10 intensity", hist[index010])); - featureList.push_back(std::make_pair(prefix + "Volume fraction at 0.90 intensity", hist[index090])); - featureList.push_back(std::make_pair(prefix + "Intensity at 0.10 volume", intensity010)); - featureList.push_back(std::make_pair(prefix + "Intensity at 0.90 volume", intensity090)); - featureList.push_back(std::make_pair(prefix + "Difference volume fraction at 0.10 and 0.90 intensity", std::abs(hist[index010] - hist[index090]))); - featureList.push_back(std::make_pair(prefix + "Difference intensity at 0.10 and 0.90 volume", std::abs(intensity090 - intensity010))); - featureList.push_back(std::make_pair(prefix + "Area under IVH curve", auc)); - //featureList.push_back(std::make_pair("Local Intensity Global Intensity Peak", globalPeakValue)); } - mitk::GIFIntensityVolumeHistogramFeatures::GIFIntensityVolumeHistogramFeatures() { SetLongName("intensity-volume-histogram"); SetShortName("ivoh"); SetFeatureClassName("Intensity Volume Histogram"); } mitk::GIFIntensityVolumeHistogramFeatures::FeatureListType mitk::GIFIntensityVolumeHistogramFeatures::CalculateFeatures(const Image::Pointer & image, const Image::Pointer &mask) { InitializeQuantifier(image, mask, 1000); FeatureListType featureList; GIFIntensityVolumeHistogramFeaturesParameters params; params.quantifier = GetQuantifier(); params.prefix = FeatureDescriptionPrefix(); AccessByItk_3(image, CalculateIntensityPeak, mask, params, featureList); return featureList; } mitk::GIFIntensityVolumeHistogramFeatures::FeatureNameListType mitk::GIFIntensityVolumeHistogramFeatures::GetFeatureNames() { FeatureNameListType featureList; return featureList; } void mitk::GIFIntensityVolumeHistogramFeatures::AddArguments(mitkCommandLineParser &parser) { std::string name = GetOptionPrefix(); parser.addArgument(GetLongName(), name, mitkCommandLineParser::Bool, "Use Local Intensity", "calculates local intensity based features", us::Any()); AddQuantifierArguments(parser); } void mitk::GIFIntensityVolumeHistogramFeatures::CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &mask, const Image::Pointer &, FeatureListType &featureList) { InitializeQuantifierFromParameters(feature, mask, 1000); auto parsedArgs = GetParameter(); if (parsedArgs.count(GetLongName())) { MITK_INFO << "Start calculating local intensity features ...."; auto localResults = this->CalculateFeatures(feature, mask); featureList.insert(featureList.end(), localResults.begin(), localResults.end()); MITK_INFO << "Finished calculating local intensity features...."; } } std::string mitk::GIFIntensityVolumeHistogramFeatures::GetCurrentFeatureEncoding() { return QuantifierParameterString(); }