From af53fb7a5d3ac13f88dce2871ea130f8e00abd3d Mon Sep 17 00:00:00 2001 From: tbaudier Date: Thu, 3 Aug 2017 14:40:04 +0200 Subject: [PATCH] Integrate MaskOfIntegratedIntensity into clitkBinarizeImage --- tools/clitkBinarizeImage.ggo | 1 + tools/clitkBinarizeImageGenericFilter.cxx | 203 +++++++++++++++++----- tools/clitkBinarizeImageGenericFilter.h | 8 + 3 files changed, 167 insertions(+), 45 deletions(-) diff --git a/tools/clitkBinarizeImage.ggo b/tools/clitkBinarizeImage.ggo index dfc37b8..3808d33 100644 --- a/tools/clitkBinarizeImage.ggo +++ b/tools/clitkBinarizeImage.ggo @@ -17,3 +17,4 @@ option "bg" - "Background (BG) or 'ouside' value" double no default option "mode" - "Use FG and/or BG values (if FG, the BG is replaced by the input image values)" values="FG","BG","both" no default="both" +option "percentage" p "Percentage of total pixels values (in %)" double no diff --git a/tools/clitkBinarizeImageGenericFilter.cxx b/tools/clitkBinarizeImageGenericFilter.cxx index 46f846b..6affce0 100644 --- a/tools/clitkBinarizeImageGenericFilter.cxx +++ b/tools/clitkBinarizeImageGenericFilter.cxx @@ -74,6 +74,9 @@ void BinarizeImageGenericFilter::SetArgsInfo(const args_info_type & a) if (mArgsInfo.output_given) { SetOutputFilename(mArgsInfo.output_arg); } + if (mArgsInfo.percentage_given) { + SetPercentage(mArgsInfo.percentage_arg); + } } //-------------------------------------------------------------------- @@ -85,60 +88,170 @@ template void BinarizeImageGenericFilter::UpdateWithInputImageType() { + if (mArgsInfo.percentage_given) + MaskOfIntegratedIntensity(); + else { + // Reading input + typename InputImageType::Pointer input = this->template GetInput(0); - // Reading input - typename InputImageType::Pointer input = this->template GetInput(0); + // Main filter + typedef typename InputImageType::PixelType PixelType; + typedef itk::Image OutputImageType; - // Main filter - typedef typename InputImageType::PixelType PixelType; - typedef itk::Image OutputImageType; - - // Filter - typedef itk::BinaryThresholdImageFilter BinaryThresholdImageFilterType; - typename BinaryThresholdImageFilterType::Pointer thresholdFilter=BinaryThresholdImageFilterType::New(); - thresholdFilter->SetInput(input); - thresholdFilter->SetInsideValue(mArgsInfo.fg_arg); - - if (mArgsInfo.lower_given) thresholdFilter->SetLowerThreshold(static_cast(mArgsInfo.lower_arg)); - if (mArgsInfo.upper_given) thresholdFilter->SetUpperThreshold(static_cast(mArgsInfo.upper_arg)); - - /* Three modes : - - FG -> only use FG value for pixel in the Foreground (or Inside), keep input values for outside - - BG -> only use BG value for pixel in the Background (or Outside), keep input values for inside - - both -> use FG and BG (real binary image) - */ - if (mArgsInfo.mode_arg == std::string("both")) { - thresholdFilter->SetOutsideValue(mArgsInfo.bg_arg); - thresholdFilter->Update(); - typename OutputImageType::Pointer outputImage = thresholdFilter->GetOutput(); - this->template SetNextOutput(outputImage); - } else { - typename InputImageType::Pointer outputImage; - thresholdFilter->SetOutsideValue(0); - if (mArgsInfo.mode_arg == std::string("BG")) { - typedef itk::MaskImageFilter maskFilterType; - typename maskFilterType::Pointer maskFilter = maskFilterType::New(); - maskFilter->SetInput1(input); - maskFilter->SetInput2(thresholdFilter->GetOutput()); - maskFilter->SetOutsideValue(mArgsInfo.bg_arg); - maskFilter->Update(); - outputImage = maskFilter->GetOutput(); + // Filter + typedef itk::BinaryThresholdImageFilter BinaryThresholdImageFilterType; + typename BinaryThresholdImageFilterType::Pointer thresholdFilter=BinaryThresholdImageFilterType::New(); + thresholdFilter->SetInput(input); + thresholdFilter->SetInsideValue(mArgsInfo.fg_arg); + + if (mArgsInfo.lower_given) thresholdFilter->SetLowerThreshold(static_cast(mArgsInfo.lower_arg)); + if (mArgsInfo.upper_given) thresholdFilter->SetUpperThreshold(static_cast(mArgsInfo.upper_arg)); + + /* Three modes : + - FG -> only use FG value for pixel in the Foreground (or Inside), keep input values for outside + - BG -> only use BG value for pixel in the Background (or Outside), keep input values for inside + - both -> use FG and BG (real binary image) + */ + if (mArgsInfo.mode_arg == std::string("both")) { + thresholdFilter->SetOutsideValue(mArgsInfo.bg_arg); + thresholdFilter->Update(); + typename OutputImageType::Pointer outputImage = thresholdFilter->GetOutput(); + this->template SetNextOutput(outputImage); } else { - typedef itk::MaskNegatedImageFilter maskFilterType; - typename maskFilterType::Pointer maskFilter = maskFilterType::New(); - maskFilter->SetInput1(input); - maskFilter->SetInput2(thresholdFilter->GetOutput()); - maskFilter->SetOutsideValue(mArgsInfo.fg_arg); - maskFilter->Update(); - outputImage = maskFilter->GetOutput(); + typename InputImageType::Pointer outputImage; + thresholdFilter->SetOutsideValue(0); + if (mArgsInfo.mode_arg == std::string("BG")) { + typedef itk::MaskImageFilter maskFilterType; + typename maskFilterType::Pointer maskFilter = maskFilterType::New(); + maskFilter->SetInput1(input); + maskFilter->SetInput2(thresholdFilter->GetOutput()); + maskFilter->SetOutsideValue(mArgsInfo.bg_arg); + maskFilter->Update(); + outputImage = maskFilter->GetOutput(); + } else { + typedef itk::MaskNegatedImageFilter maskFilterType; + typename maskFilterType::Pointer maskFilter = maskFilterType::New(); + maskFilter->SetInput1(input); + maskFilter->SetInput2(thresholdFilter->GetOutput()); + maskFilter->SetOutsideValue(mArgsInfo.fg_arg); + maskFilter->Update(); + outputImage = maskFilter->GetOutput(); + } + // Write/Save results + this->template SetNextOutput(outputImage); } - // Write/Save results - this->template SetNextOutput(outputImage); } } //-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// https://stackoverflow.com/questions/1577475/c-sorting-and-keeping-track-of-indexes +template +std::vector sort_indexes(const std::vector &v) { + + // initialize original index locations + std::vector idx(v.size()); + std::vector > compVector(v.size()); + for (size_t i = 0; i < v.size(); ++i) { + compVector[i].first = v[i]; + compVector[i].second = i; + } + + // sort indexes based on comparing values in v + std::sort(compVector.begin(), compVector.end(), comparator); + for (size_t i = 0; i < v.size(); ++i) { + idx[i] = compVector[i].second; + } + + return idx; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +// Update with the number of dimensions and the pixeltype +//-------------------------------------------------------------------- +template +void +BinarizeImageGenericFilter::MaskOfIntegratedIntensity() +{ + // Main filter + typedef typename InputImageType::PixelType InputPixelType; + typedef itk::Image MaskImageType; + + // Reading input + typename InputImageType::Pointer input = this->template GetInput(0); + + typename MaskImageType::Pointer mask; + mask = MaskImageType::New(); + mask->SetRegions(input->GetLargestPossibleRegion()); + mask->SetOrigin(input->GetOrigin()); + mask->SetSpacing(input->GetSpacing()); + mask->Allocate(); + mask->FillBuffer(0); + + // Get a vector of all values (will be easier to sort) + // And compute total sum of values + std::vector values; + typedef itk::ImageRegionIterator IteratorInputType; + IteratorInputType iter(input, input->GetLargestPossibleRegion()); + iter.GoToBegin(); + double total = 0.0; + while (!iter.IsAtEnd()) { + values.push_back(iter.Get()); + total += iter.Get(); + ++iter; + } + + // Sort (reverse) + std::vector indices = sort_indexes(values); + + // Get max index of pixel to reach xx percent + double current = 0.0; + double max = GetPercentage()/100.0*total; + int i=0; + int n = input->GetLargestPossibleRegion().GetNumberOfPixels(); + std::vector should_keep(values.size());; + std::fill(should_keep.begin(), should_keep.end(), 0); + while (current IteratorMaskType; + IteratorMaskType itm(mask, mask->GetLargestPossibleRegion()); + iter.GoToBegin(); + itm.GoToBegin(); + i = 0; + while (!iter.IsAtEnd()) { + if (should_keep[i]) itm.Set(1); + ++iter; + ++itm; + ++i; + } + + // Verbose option + if (this->m_IOVerbose) + std::cout << "Sum of pixel values : " << total << std::endl + << "Percentage : " << GetPercentage() << "%" << std::endl + << "Number of pixels : " << nb << "/" << n << std::endl + << "Number of pixels : " << nb/n*100.0 << "%" << std::endl; + + // Write/Save results + this->template SetNextOutput(mask); +} +//-------------------------------------------------------------------- + +//-------------------------------------------------------------------- +template +bool comparator ( const std::pair& l, const std::pair& r) + { return l.first > r.first; } +//-------------------------------------------------------------------- + }//end clitk #endif //#define clitkBinarizeImageGenericFilter_cxx diff --git a/tools/clitkBinarizeImageGenericFilter.h b/tools/clitkBinarizeImageGenericFilter.h index c21e31e..4a919f5 100644 --- a/tools/clitkBinarizeImageGenericFilter.h +++ b/tools/clitkBinarizeImageGenericFilter.h @@ -46,20 +46,28 @@ namespace clitk //-------------------------------------------------------------------- void SetArgsInfo(const args_info_type & a); + void SetPercentage(double p) { mPercentage = p; } + double GetPercentage() const { return mPercentage; } //-------------------------------------------------------------------- // Main function called each time the filter is updated template void UpdateWithInputImageType(); + template + void MaskOfIntegratedIntensity(); + protected: BinarizeImageGenericFilter(); template void InitializeImageType(); args_info_type mArgsInfo; + double mPercentage; }; // end class //-------------------------------------------------------------------- +//Implementation of the pair comparative function +template bool comparator ( const std::pair& l, const std::pair& r); } // end namespace clitk //-------------------------------------------------------------------- -- 2.47.1