X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=segmentation%2FclitkExtractLungFilter.txx;h=52276f4478bb0cd55a6040efd07a763bd291d120;hb=a24b0a699298efe54b53c53cb215455fecd633fe;hp=3de027cc3b8210d0dbbac0e5d2a24d1a4aa02cfa;hpb=44ebb81a500e42cf19964d209e14a59812a0dd4d;p=clitk.git diff --git a/segmentation/clitkExtractLungFilter.txx b/segmentation/clitkExtractLungFilter.txx index 3de027c..52276f4 100644 --- a/segmentation/clitkExtractLungFilter.txx +++ b/segmentation/clitkExtractLungFilter.txx @@ -24,6 +24,8 @@ #include "clitkSetBackgroundImageFilter.h" #include "clitkSegmentationUtils.h" #include "clitkAutoCropFilter.h" +#include "clitkCropLikeImageFilter.h" +#include "clitkFillMaskFilter.h" // itk #include "itkBinaryThresholdImageFilter.h" @@ -36,17 +38,18 @@ #include "itkBinaryMorphologicalClosingImageFilter.h" //-------------------------------------------------------------------- -template -clitk::ExtractLungFilter:: +template +clitk::ExtractLungFilter:: ExtractLungFilter(): clitk::FilterBase(), + clitk::FilterWithAnatomicalFeatureDatabaseManagement(), itk::ImageToImageFilter() { SetNumberOfSteps(10); m_MaxSeedNumber = 500; // Default global options - this->SetNumberOfRequiredInputs(2); + this->SetNumberOfRequiredInputs(1); SetPatientMaskBackgroundValue(0); SetBackgroundValue(0); // Must be zero SetForegroundValue(1); @@ -85,16 +88,19 @@ ExtractLungFilter(): SetLabelizeParameters3(p3); // Step 5 - FinalOpenCloseOff(); - SetFinalOpenCloseRadius(1); + OpenCloseOff(); + SetOpenCloseRadius(1); + + // Step 6 + FillHolesOn(); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- -template +template void -clitk::ExtractLungFilter:: +clitk::ExtractLungFilter:: SetInput(const ImageType * image) { this->SetNthInput(0, const_cast(image)); @@ -103,21 +109,9 @@ SetInput(const ImageType * image) //-------------------------------------------------------------------- -template +template void -clitk::ExtractLungFilter:: -SetInputPatientMask(MaskImageType * image, MaskImagePixelType bg ) -{ - this->SetNthInput(1, const_cast(image)); - SetPatientMaskBackgroundValue(bg); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLungFilter:: +clitk::ExtractLungFilter:: AddSeed(InternalIndexType s) { m_Seeds.push_back(s); @@ -126,10 +120,10 @@ AddSeed(InternalIndexType s) //-------------------------------------------------------------------- -template +template template void -clitk::ExtractLungFilter:: +clitk::ExtractLungFilter:: SetArgsInfo(ArgsInfoType mArgsInfo) { SetVerboseOption_GGO(mArgsInfo); @@ -137,6 +131,10 @@ SetArgsInfo(ArgsInfoType mArgsInfo) SetWriteStep_GGO(mArgsInfo); SetVerboseWarningOff_GGO(mArgsInfo); + SetAFDBFilename_GGO(mArgsInfo); + SetOutputLungFilename_GGO(mArgsInfo); + SetOutputTracheaFilename_GGO(mArgsInfo); + SetUpperThreshold_GGO(mArgsInfo); SetLowerThreshold_GGO(mArgsInfo); SetNumberOfSlicesToSkipBeforeSearchingSeed_GGO(mArgsInfo); @@ -159,34 +157,47 @@ SetArgsInfo(ArgsInfoType mArgsInfo) SetRadiusForTrachea_GGO(mArgsInfo); SetLabelizeParameters3_GGO(mArgsInfo); - SetFinalOpenCloseRadius_GGO(mArgsInfo); - SetFinalOpenClose_GGO(mArgsInfo); + SetOpenCloseRadius_GGO(mArgsInfo); + SetOpenClose_GGO(mArgsInfo); + + SetFillHoles_GGO(mArgsInfo); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- -template +template void -clitk::ExtractLungFilter:: +clitk::ExtractLungFilter:: GenerateOutputInformation() { Superclass::GenerateOutputInformation(); + + // Read DB + LoadAFDB(); // Get input pointers - patient = dynamic_cast(itk::ProcessObject::GetInput(1)); input = dynamic_cast(itk::ProcessObject::GetInput(0)); + patient = GetAFDB()->template GetImage ("patient"); - // Check image - if (!HaveSameSizeAndSpacing(input, patient)) { - clitkExceptionMacro("the 'input' and 'patient' masks must have the same size & spacing."); - } - + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Crop input like patient image (must have the same spacing) + StartNewStep("Crop input image to 'patient' extends"); + typedef clitk::CropLikeImageFilter CropImageFilter; + typename CropImageFilter::Pointer cropFilter = CropImageFilter::New(); + cropFilter->SetInput(input); + cropFilter->SetCropLikeImage(patient); + cropFilter->Update(); + working_input = cropFilter->GetOutput(); + DD(working_input->GetLargestPossibleRegion()); + StopCurrentStep(working_input); + //-------------------------------------------------------------------- //-------------------------------------------------------------------- StartNewStep("Set background to initial image"); working_input = SetBackground - (input, patient, GetPatientMaskBackgroundValue(), -1000); + (working_input, patient, GetPatientMaskBackgroundValue(), -1000); StopCurrentStep(working_input); //-------------------------------------------------------------------- @@ -313,15 +324,15 @@ GenerateOutputInformation() //-------------------------------------------------------------------- //-------------------------------------------------------------------- - typedef clitk::AutoCropFilter CropFilterType; - typename CropFilterType::Pointer cropFilter = CropFilterType::New(); + typedef clitk::AutoCropFilter AutoCropFilterType; + typename AutoCropFilterType::Pointer autocropFilter = AutoCropFilterType::New(); if (m_Seeds.size() != 0) { // if ==0 ->no trachea found - StartNewStep("Croping trachea"); - cropFilter->SetInput(trachea_tmp); - cropFilter->Update(); // Needed + StartNewStep("Cropping trachea"); + autocropFilter->SetInput(trachea_tmp); + autocropFilter->Update(); // Needed typedef itk::CastImageFilter CastImageFilterType; typename CastImageFilterType::Pointer caster= CastImageFilterType::New(); - caster->SetInput(cropFilter->GetOutput()); + caster->SetInput(autocropFilter->GetOutput()); caster->Update(); trachea = caster->GetOutput(); StopCurrentStep(trachea); @@ -329,23 +340,24 @@ GenerateOutputInformation() //-------------------------------------------------------------------- //-------------------------------------------------------------------- - StartNewStep("Croping lung"); - typename CropFilterType::Pointer cropFilter2 = CropFilterType::New(); // Needed to reset pipeline - cropFilter2->SetInput(working_image); - cropFilter2->Update(); - working_image = cropFilter2->GetOutput(); + StartNewStep("Cropping lung"); + typename AutoCropFilterType::Pointer autocropFilter2 = AutoCropFilterType::New(); // Needed to reset pipeline + autocropFilter2->SetInput(working_image); + autocropFilter2->Update(); + working_image = autocropFilter2->GetOutput(); + DD(working_image->GetLargestPossibleRegion()); StopCurrentStep(working_image); //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Final OpenClose - if (GetFinalOpenClose()) { + if (GetOpenClose()) { StartNewStep("Open/Close"); // Structuring element typedef itk::BinaryBallStructuringElement KernelType; KernelType structuringElement; - structuringElement.SetRadius(GetFinalOpenCloseRadius()); + structuringElement.SetRadius(GetOpenCloseRadius()); structuringElement.CreateStructuringElement(); // Open @@ -367,6 +379,21 @@ GenerateOutputInformation() working_image = closeFilter->GetOutput(); } + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Fill Lungs + if (GetFillHoles()) { + StartNewStep("Fill Holes"); + typedef clitk::FillMaskFilter FillMaskFilterType; + typename FillMaskFilterType::Pointer fillMaskFilter = FillMaskFilterType::New(); + fillMaskFilter->SetInput(working_image); + fillMaskFilter->AddDirection(2); + //fillMaskFilter->AddDirection(1); + fillMaskFilter->Update(); + working_image = fillMaskFilter->GetOutput(); + StopCurrentStep(working_image); + } + //-------------------------------------------------------------------- //-------------------------------------------------------------------- StartNewStep("Separate Left/Right lungs"); @@ -387,13 +414,14 @@ GenerateOutputInformation() // Decompose the first label static const unsigned int Dim = ImageType::ImageDimension; if (initialNumberOfLabels<2) { + DD(initialNumberOfLabels); // Structuring element radius typename ImageType::SizeType radius; for (unsigned int i=0;i DecomposeAndReconstructFilterType; typename DecomposeAndReconstructFilterType::Pointer decomposeAndReconstructFilter=DecomposeAndReconstructFilterType::New(); decomposeAndReconstructFilter->SetInput(working_image); - decomposeAndReconstructFilter->SetVerbose(false); + decomposeAndReconstructFilter->SetVerbose(true); decomposeAndReconstructFilter->SetRadius(radius); decomposeAndReconstructFilter->SetMaximumNumberOfLabels(2); decomposeAndReconstructFilter->SetMinimumObjectSize(this->GetMinimalComponentSize()); @@ -426,28 +454,30 @@ GenerateOutputInformation() // Update output info this->GetOutput(0)->SetRegions(output->GetLargestPossibleRegion()); - - } //-------------------------------------------------------------------- //-------------------------------------------------------------------- -template +template void -clitk::ExtractLungFilter:: +clitk::ExtractLungFilter:: GenerateData() { // Set the output this->GraftOutput(output); // not SetNthOutput + // Store image filenames into AFDB + GetAFDB()->SetImageFilename("lungs", this->GetOutputLungFilename()); + GetAFDB()->SetImageFilename("trachea", this->GetOutputTracheaFilename()); + WriteAFDB(); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- -template +template bool -clitk::ExtractLungFilter:: +clitk::ExtractLungFilter:: SearchForTracheaSeed(int skip) { if (m_Seeds.size() == 0) { // try to find seed (if not zero, it is given by user) @@ -495,9 +525,9 @@ SearchForTracheaSeed(int skip) //-------------------------------------------------------------------- -template +template void -clitk::ExtractLungFilter:: +clitk::ExtractLungFilter:: TracheaRegionGrowing() { // Explosion controlled region growing @@ -508,7 +538,8 @@ TracheaRegionGrowing() f->SetLower(-2000); f->SetUpper(GetUpperThresholdForTrachea()); f->SetMinimumLowerThreshold(-2000); - f->SetMaximumUpperThreshold(0); + // f->SetMaximumUpperThreshold(0); // MAYBE TO CHANGE ??? + f->SetMaximumUpperThreshold(-800); // MAYBE TO CHANGE ??? f->SetAdaptLowerBorder(false); f->SetAdaptUpperBorder(true); f->SetMinimumSize(5000); @@ -516,12 +547,15 @@ TracheaRegionGrowing() f->SetMultiplier(GetMultiplierForTrachea()); f->SetThresholdStepSize(GetThresholdStepSizeForTrachea()); f->SetMinimumThresholdStepSize(1); + f->VerboseOn(); for(unsigned int i=0; iAddSeed(m_Seeds[i]); // DD(m_Seeds[i]); } f->Update(); + writeImage(f->GetOutput(), "trg.mhd"); + // take first (main) connected component trachea_tmp = Labelize(f->GetOutput(), GetBackgroundValue(), @@ -536,9 +570,9 @@ TracheaRegionGrowing() //-------------------------------------------------------------------- -template +template double -clitk::ExtractLungFilter:: +clitk::ExtractLungFilter:: ComputeTracheaVolume() { typedef itk::ImageRegionConstIterator IteratorType; @@ -557,9 +591,9 @@ ComputeTracheaVolume() //-------------------------------------------------------------------- -template +template void -clitk::ExtractLungFilter:: +clitk::ExtractLungFilter:: SearchForTrachea() { // Search for seed among n slices, skip some slices before starting