X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=segmentation%2FclitkExtractPatientFilter.txx;h=97f79c5e9050bdcf1b5b4d2275ad0a32e73c60f8;hb=48727138e88f056b67312603560e600362346462;hp=cfc2ab2f8d4544c992374864ab38364b5da187d3;hpb=e008d74b0ecdc4ca2eaae8c429901a78f9ef5c31;p=clitk.git diff --git a/segmentation/clitkExtractPatientFilter.txx b/segmentation/clitkExtractPatientFilter.txx index cfc2ab2..97f79c5 100644 --- a/segmentation/clitkExtractPatientFilter.txx +++ b/segmentation/clitkExtractPatientFilter.txx @@ -1,9 +1,9 @@ /*========================================================================= Program: vv http://www.creatis.insa-lyon.fr/rio/vv - Authors belong to: + 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 CLITKEXTRACTPATIENTFILTER_TXX #define CLITKEXTRACTPATIENTFILTER_TXX @@ -24,6 +24,8 @@ #include "clitkSetBackgroundImageFilter.h" #include "clitkDecomposeAndReconstructImageFilter.h" #include "clitkAutoCropFilter.h" +#include "clitkMemoryUsage.h" +#include "clitkSegmentationUtils.h" // itk #include "itkBinaryThresholdImageFilter.h" @@ -33,17 +35,20 @@ #include "itkBinaryMorphologicalOpeningImageFilter.h" #include "itkBinaryBallStructuringElement.h" #include "itkCastImageFilter.h" +#include "itkConstantPadImageFilter.h" //-------------------------------------------------------------------- -template -clitk::ExtractPatientFilter:: +template +clitk::ExtractPatientFilter:: ExtractPatientFilter(): clitk::FilterBase(), - itk::ImageToImageFilter() + clitk::FilterWithAnatomicalFeatureDatabaseManagement(), + itk::ImageToImageFilter() { this->SetNumberOfRequiredInputs(1); SetBackgroundValue(0); // Must be zero SetForegroundValue(1); + SetPrimaryOpeningRadius(0); // Step 1: Threshold + CC + sort (Find low density areas) SetUpperThreshold(-300); @@ -65,23 +70,23 @@ ExtractPatientFilter(): SetRadius2(r); SetMaximumNumberOfLabels2(2); SetNumberOfNewLabels2(1); - + // Step 5: Only keep label corresponding (Keep patient's labels) SetFirstKeep(1); SetLastKeep(1); - + // Step 4: OpenClose (option) - FinalOpenCloseOn(); - AutoCropOff(); + FinalOpenCloseOff(); + AutoCropOn(); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- -template -void -clitk::ExtractPatientFilter:: -SetInput(const TInputImageType * image) +template +void +clitk::ExtractPatientFilter:: +SetInput(const TInputImageType * image) { this->SetNthInput(0, const_cast(image)); } @@ -89,88 +94,98 @@ SetInput(const TInputImageType * image) //-------------------------------------------------------------------- -template -template -void -clitk::ExtractPatientFilter:: -SetArgsInfo(ArgsInfoType arg) -{ - SetVerboseOption_GGO(arg); - SetVerboseStep_GGO(arg); - SetWriteStep_GGO(arg); - SetVerboseWarningOff_GGO(arg); - - SetUpperThreshold_GGO(arg); - SetLowerThreshold_GGO(arg); - - SetDecomposeAndReconstructDuringFirstStep_GGO(arg); - SetRadius1_GGO(arg); - SetMaximumNumberOfLabels1_GGO(arg); - SetNumberOfNewLabels1_GGO(arg); - - SetDecomposeAndReconstructDuringSecondStep_GGO(arg); - SetRadius2_GGO(arg); - SetMaximumNumberOfLabels2_GGO(arg); - SetNumberOfNewLabels2_GGO(arg); - - SetFirstKeep_GGO(arg); - SetLastKeep_GGO(arg); - - SetFinalOpenClose_GGO(arg); - SetAutoCrop_GGO(arg); -} -//-------------------------------------------------------------------- +template +void +clitk::ExtractPatientFilter:: +GenerateOutputInformation() { - -//-------------------------------------------------------------------- -template -void -clitk::ExtractPatientFilter:: -GenerateOutputInformation() { + clitk::PrintMemory(GetVerboseMemoryFlag(), "Initial memory"); // OK Superclass::GenerateOutputInformation(); input = dynamic_cast(itk::ProcessObject::GetInput(0)); - // OutputImagePointer outputImage = this->GetOutput(0); + // MaskImagePointer outputImage = this->GetOutput(0); // outputImage->SetRegions(input->GetLargestPossibleRegion()); // Get input pointers static const unsigned int Dim = InputImageType::ImageDimension; //input = dynamic_cast(itk::ProcessObject::GetInput(0)); - + //-------------------------------------------------------------------- //-------------------------------------------------------------------- - // Step 1: + // Step 1: StartNewStep("Find low densities areas"); - typedef itk::BinaryThresholdImageFilter BinarizeFilterType; + + // Pad images with air to prevent patient touching the image border + // But the lungs can touch the outside air. In such case, use primaryOpeningRadius with 1 kernel + typedef itk::ConstantPadImageFilter PadFilterType; + typename PadFilterType::Pointer padFilter = PadFilterType::New(); + padFilter->SetInput(input); + padFilter->SetConstant(GetUpperThreshold() - 1); + typename InputImageType::SizeType bounds; + for (unsigned i = 0; i < Dim - 1; ++i) + bounds[i] = 1; + bounds[Dim - 1] = 0; + padFilter->SetPadLowerBound(bounds); + padFilter->SetPadUpperBound(bounds); + padFilter->Update(); + + typedef itk::BinaryThresholdImageFilter BinarizeFilterType; typename BinarizeFilterType::Pointer binarizeFilter=BinarizeFilterType::New(); - binarizeFilter->SetInput(input); + binarizeFilter->SetInput(padFilter->GetOutput()); if (m_UseLowerThreshold) binarizeFilter->SetLowerThreshold(GetLowerThreshold()); binarizeFilter->SetUpperThreshold(GetUpperThreshold()); binarizeFilter ->SetInsideValue(this->GetForegroundValue()); binarizeFilter ->SetOutsideValue(this->GetBackgroundValue()); + padFilter->GetOutput()->ReleaseData(); + working_image = binarizeFilter->GetOutput(); + + typedef itk::BinaryBallStructuringElement KernelType; + unsigned int radius = this->GetPrimaryOpeningRadius(); + if (radius > 0) + { + if (this->GetVerboseOptionFlag()) std::cout << ("Opening after threshold; R = ") << radius << std::endl; + KernelType kernel; + kernel.SetRadius(radius); + + typedef itk::BinaryMorphologicalOpeningImageFilter OpenFilterType2; + typename OpenFilterType2::Pointer openFilter2 = OpenFilterType2::New(); + openFilter2->SetInput(working_image); + openFilter2->SetBackgroundValue(0); + openFilter2->SetForegroundValue(1); + openFilter2->SetKernel(kernel); + openFilter2->Update(); + working_image->ReleaseData(); + working_image = openFilter2->GetOutput(); + } + if (this->GetVerboseOptionFlag()) std::cout << ("Labelling") << std::endl; // Connected component labeling typedef itk::ConnectedComponentImageFilter ConnectFilterType; typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New(); - connectFilter->SetInput(binarizeFilter->GetOutput()); + connectFilter->SetInput(working_image); connectFilter->SetBackgroundValue(this->GetBackgroundValue()); connectFilter->SetFullyConnected(false); - + connectFilter->Update(); + working_image->ReleaseData(); + working_image = connectFilter->GetOutput(); + + if (this->GetVerboseOptionFlag()) std::cout << ("RelabelComponentImageFilter") << std::endl; // Sort labels according to size typedef itk::RelabelComponentImageFilter RelabelFilterType; typename RelabelFilterType::Pointer relabelFilter=RelabelFilterType::New(); relabelFilter->InPlaceOn(); relabelFilter->SetInput(connectFilter->GetOutput()); relabelFilter->Update(); + working_image->ReleaseData(); working_image = relabelFilter->GetOutput(); - + // End StopCurrentStep(working_image); //-------------------------------------------------------------------- //-------------------------------------------------------------------- - // [Optional] + // [Optional] if (GetDecomposeAndReconstructDuringFirstStep()) { StartNewStep("First Decompose & Reconstruct step"); typedef clitk::DecomposeAndReconstructImageFilter FilterType; @@ -184,36 +199,48 @@ GenerateOutputInformation() { f->SetFullyConnected(true); f->SetNumberOfNewLabels(GetNumberOfNewLabels1()); f->Update(); + working_image->ReleaseData(); working_image = f->GetOutput(); StopCurrentStep(working_image); } - + //-------------------------------------------------------------------- //-------------------------------------------------------------------- + if (this->GetVerboseOptionFlag()) std::cout << ("Remove the air (largest area)") << std::endl; StartNewStep("Remove the air (largest area)"); - typedef itk::BinaryThresholdImageFilter iBinarizeFilterType; + typedef itk::BinaryThresholdImageFilter iBinarizeFilterType; typename iBinarizeFilterType::Pointer binarizeFilter2 = iBinarizeFilterType::New(); binarizeFilter2->SetInput(working_image); - binarizeFilter2->SetLowerThreshold(this->GetForegroundValue()); - binarizeFilter2->SetUpperThreshold(this->GetForegroundValue()); - binarizeFilter2 ->SetInsideValue(this->GetBackgroundValue()); - binarizeFilter2 ->SetOutsideValue(this->GetForegroundValue()); - // binarizeFilter2 ->Update(); // NEEDED ? + binarizeFilter2->SetLowerThreshold(GetFirstKeep()); + binarizeFilter2->SetUpperThreshold(GetLastKeep()); + binarizeFilter2 ->SetInsideValue(0); + binarizeFilter2 ->SetOutsideValue(1); + binarizeFilter2 ->Update(); + working_image->ReleaseData(); + working_image = binarizeFilter2->GetOutput(); typename ConnectFilterType::Pointer connectFilter2 = ConnectFilterType::New(); - connectFilter2->SetInput(binarizeFilter2->GetOutput()); + connectFilter2->SetInput(working_image); connectFilter2->SetBackgroundValue(this->GetBackgroundValue()); connectFilter2->SetFullyConnected(false); + connectFilter2->Update(); + working_image->ReleaseData(); + working_image = connectFilter2->GetOutput(); typename RelabelFilterType::Pointer relabelFilter2 = RelabelFilterType::New(); - relabelFilter2->SetInput(connectFilter2->GetOutput()); + relabelFilter2->SetInput(working_image); relabelFilter2->Update(); + working_image->ReleaseData(); working_image = relabelFilter2->GetOutput(); + + // Keep main label + working_image = KeepLabels + (working_image, GetBackgroundValue(), GetForegroundValue(), 1, 1, true); StopCurrentStep(working_image); //-------------------------------------------------------------------- //-------------------------------------------------------------------- - // [Optional] + // [Optional] if (GetDecomposeAndReconstructDuringSecondStep()) { StartNewStep("Second Decompose & Reconstruct step"); typedef clitk::DecomposeAndReconstructImageFilter FilterType; @@ -227,30 +254,17 @@ GenerateOutputInformation() { f->SetFullyConnected(true); f->SetNumberOfNewLabels(GetNumberOfNewLabels2()); f->Update(); + working_image->ReleaseData(); working_image = f->GetOutput(); StopCurrentStep(working_image); } - //-------------------------------------------------------------------- - //-------------------------------------------------------------------- - StartNewStep("Keep patient's labels"); - typename iBinarizeFilterType::Pointer binarizeFilter3 = iBinarizeFilterType::New(); - binarizeFilter3->SetInput(working_image); - binarizeFilter3->SetLowerThreshold(GetFirstKeep()); - binarizeFilter3->SetUpperThreshold(GetLastKeep()); - binarizeFilter3 ->SetInsideValue(this->GetForegroundValue()); - binarizeFilter3 ->SetOutsideValue(this->GetBackgroundValue()); - binarizeFilter3->Update(); - working_image = binarizeFilter3->GetOutput(); - StopCurrentStep(working_image); - //-------------------------------------------------------------------- //-------------------------------------------------------------------- // [Optional] if (GetFinalOpenClose()) { StartNewStep("Final OpenClose"); // Open - typedef itk::BinaryBallStructuringElement KernelType; KernelType structuringElement; structuringElement.SetRadius(1); structuringElement.CreateStructuringElement(); @@ -259,7 +273,7 @@ GenerateOutputInformation() { openFilter->SetInput(working_image); openFilter->SetBackgroundValue(this->GetBackgroundValue()); openFilter->SetForegroundValue(this->GetForegroundValue()); - openFilter->SetKernel(structuringElement); + openFilter->SetKernel(structuringElement); // Close typedef itk::BinaryMorphologicalClosingImageFilter CloseFilterType; typename CloseFilterType::Pointer closeFilter = CloseFilterType::New(); @@ -268,18 +282,20 @@ GenerateOutputInformation() { closeFilter->SetForegroundValue(this->GetForegroundValue()); // closeFilter->SetBackgroundValue(SetBackgroundValue()); closeFilter->SetKernel(structuringElement); - closeFilter->Update(); + closeFilter->Update(); + working_image->ReleaseData(); working_image = closeFilter->GetOutput(); StopCurrentStep(working_image); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- - // Final Cast - typedef itk::CastImageFilter CastImageFilterType; + // Final Cast + typedef itk::CastImageFilter CastImageFilterType; typename CastImageFilterType::Pointer caster= CastImageFilterType::New(); caster->SetInput(working_image); caster->Update(); + working_image->ReleaseData(); output = caster->GetOutput(); //-------------------------------------------------------------------- @@ -287,27 +303,43 @@ GenerateOutputInformation() { // [Optional] if (GetAutoCrop()) { StartNewStep("AutoCrop"); - typedef clitk::AutoCropFilter CropFilterType; + typedef clitk::AutoCropFilter CropFilterType; typename CropFilterType::Pointer cropFilter = CropFilterType::New(); cropFilter->SetInput(output); cropFilter->SetBackgroundValue(GetBackgroundValue()); - cropFilter->Update(); + cropFilter->Update(); + output->ReleaseData(); + output = cropFilter->GetOutput(); + StopCurrentStep(output); + } + else + { + // Remove Padding region + typedef itk::CropImageFilter CropFilterType; + typename CropFilterType::Pointer cropFilter = CropFilterType::New(); + cropFilter->SetInput(output); + cropFilter->SetLowerBoundaryCropSize(bounds); + cropFilter->SetUpperBoundaryCropSize(bounds); + cropFilter->Update(); + output->ReleaseData(); output = cropFilter->GetOutput(); - StopCurrentStep(output); } } //-------------------------------------------------------------------- //-------------------------------------------------------------------- -template -void -clitk::ExtractPatientFilter:: +template +void +clitk::ExtractPatientFilter:: GenerateData() { - //this->SetNthOutput(0, output); // -> no because redo filter otherwise + // Final Graft this->GraftOutput(output); + // Store image filename into AFDB + GetAFDB()->SetImageFilename("Patient", this->GetOutputPatientFilename()); + WriteAFDB(); } //-------------------------------------------------------------------- - + #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX