X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=tools%2FclitkBinarizeImageGenericFilter.cxx;h=f94cf1a09206c0404fc2ba004a2195638b9b1cec;hb=3566b753a5db63397cb87ca4dd84578238749ca4;hp=26b08a06844258f27b5034eab3be9d1a951ff473;hpb=870c69d4433f861755085ce2e398032223768a94;p=clitk.git diff --git a/tools/clitkBinarizeImageGenericFilter.cxx b/tools/clitkBinarizeImageGenericFilter.cxx index 26b08a0..f94cf1a 100644 --- a/tools/clitkBinarizeImageGenericFilter.cxx +++ b/tools/clitkBinarizeImageGenericFilter.cxx @@ -3,7 +3,7 @@ Authors belong to: - University of LYON http://www.universite-lyon.fr/ - - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - Léon Bérard cancer center http://www.centreleonberard.fr - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr This software is distributed WITHOUT ANY WARRANTY; without even @@ -14,7 +14,7 @@ - BSD See included LICENSE.txt file - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html -======================================================================-====*/ +===========================================================================**/ #ifndef clitkBinarizeImageGenericFilter_cxx #define clitkBinarizeImageGenericFilter_cxx @@ -41,7 +41,7 @@ namespace clitk //-------------------------------------------------------------------- BinarizeImageGenericFilter::BinarizeImageGenericFilter(): - ImageToImageGenericFilter("Binarize") + ImageToImageGenericFilter("BinarizeImage") { InitializeImageType<2>(); InitializeImageType<3>(); @@ -63,8 +63,10 @@ void BinarizeImageGenericFilter::InitializeImageType() void BinarizeImageGenericFilter::SetArgsInfo(const args_info_type & a) { mArgsInfo=a; - SetIOVerbose(mArgsInfo.verbose_flag); - if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes(); + if (mArgsInfo.verbose_given) + SetIOVerbose(mArgsInfo.verbose_flag); + if (mArgsInfo.imagetypes_given && mArgsInfo.imagetypes_flag) + this->PrintAvailableImageTypes(); if (mArgsInfo.input_given) { SetInputFilename(mArgsInfo.input_arg); @@ -72,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); + } } //-------------------------------------------------------------------- @@ -83,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