]> Creatis software - clitk.git/blobdiff - segmentation/clitkExtractLungFilter.txx
Add padding in clitkExtractLung
[clitk.git] / segmentation / clitkExtractLungFilter.txx
index 92b2d4f75cf2e8daa0c6633e64c23c7812886ffd..0954c2a3de46a11249c21237b9644e9a4a123404 100644 (file)
@@ -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 CLITKEXTRACTLUNGSFILTER_TXX
 #define CLITKEXTRACTLUNGSFILTER_TXX
@@ -24,7 +24,9 @@
 #include "clitkSetBackgroundImageFilter.h"
 #include "clitkSegmentationUtils.h"
 #include "clitkAutoCropFilter.h"
-#include "clitkExtractSliceFilter.h"
+#include "clitkCropLikeImageFilter.h"
+#include "clitkFillMaskFilter.h"
+#include "clitkMemoryUsage.h"
 
 // itk
 #include "itkBinaryThresholdImageFilter.h"
 #include "itkOtsuThresholdImageFilter.h"
 #include "itkBinaryThinningImageFilter3D.h"
 #include "itkImageIteratorWithIndex.h"
+#include "itkBinaryMorphologicalOpeningImageFilter.h"
+#include "itkBinaryMorphologicalClosingImageFilter.h"
+#include "itkConstantPadImageFilter.h"
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+template <class ImageType>
+clitk::ExtractLungFilter<ImageType>::
 ExtractLungFilter():
   clitk::FilterBase(),
   clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
@@ -46,11 +51,12 @@ ExtractLungFilter():
   m_MaxSeedNumber = 500;
 
   // Default global options
-  this->SetNumberOfRequiredInputs(2);
+  this->SetNumberOfRequiredInputs(1);
   SetPatientMaskBackgroundValue(0);
   SetBackgroundValue(0); // Must be zero
   SetForegroundValue(1);
   SetMinimalComponentSize(100);
+  VerboseRegionGrowingFlagOff();
 
   // Step 1 default values
   SetUpperThreshold(-300);
@@ -67,6 +73,7 @@ ExtractLungFilter():
   SetMultiplierForTrachea(5);
   SetThresholdStepSizeForTrachea(64);
   SetNumberOfSlicesToSkipBeforeSearchingSeed(0);
+  TracheaVolumeMustBeCheckedFlagOn();
   
   // Step 3 default values
   SetNumberOfHistogramBins(500);
@@ -84,16 +91,21 @@ ExtractLungFilter():
   p3->UseLastKeepOff();
   SetLabelizeParameters3(p3);
   
-  // Step 5 : find bronchial bifurcations
-  FindBronchialBifurcationsOn();
+  // Step 5
+  OpenCloseFlagOff();
+  SetOpenCloseRadius(1);
+  
+  // Step 6
+  FillHolesFlagOn();
+  AutoCropOn();
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 SetInput(const ImageType * image) 
 {
   this->SetNthInput(0, const_cast<ImageType *>(image));
@@ -102,21 +114,9 @@ SetInput(const ImageType * image)
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
-SetInputPatientMask(MaskImageType * image, MaskImagePixelType bg ) 
-{
-  this->SetNthInput(1, const_cast<MaskImageType *>(image));
-  SetPatientMaskBackgroundValue(bg);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
-void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 AddSeed(InternalIndexType s) 
 { 
   m_Seeds.push_back(s);
@@ -125,68 +125,70 @@ AddSeed(InternalIndexType s)
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
-template<class ArgsInfoType>
+template <class ImageType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
-SetArgsInfo(ArgsInfoType mArgsInfo)
-{
-  SetVerboseOption_GGO(mArgsInfo);
-  SetVerboseStep_GGO(mArgsInfo);
-  SetWriteStep_GGO(mArgsInfo);
-  SetVerboseWarningOff_GGO(mArgsInfo);
-
-  SetUpperThreshold_GGO(mArgsInfo);
-  SetLowerThreshold_GGO(mArgsInfo);
-  SetNumberOfSlicesToSkipBeforeSearchingSeed_GGO(mArgsInfo);
-  SetLabelizeParameters1_GGO(mArgsInfo);
-  if (!mArgsInfo.remove1_given) {
-    GetLabelizeParameters1()->AddLabelToRemove(2); 
-    if (GetVerboseOption()) VerboseOption("remove1", 2);
-  }
-
-  SetUpperThresholdForTrachea_GGO(mArgsInfo);
-  SetMultiplierForTrachea_GGO(mArgsInfo);
-  SetThresholdStepSizeForTrachea_GGO(mArgsInfo);
-  AddSeed_GGO(mArgsInfo);
-
-  SetMinimalComponentSize_GGO(mArgsInfo);
-  
-  SetNumberOfHistogramBins_GGO(mArgsInfo);
-  SetLabelizeParameters2_GGO(mArgsInfo);
-
-  SetRadiusForTrachea_GGO(mArgsInfo);
-  SetLabelizeParameters3_GGO(mArgsInfo);
-  
-  SetAFDBFilename_GGO(mArgsInfo);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
-void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 GenerateOutputInformation() 
 { 
+  clitk::PrintMemory(GetVerboseMemoryFlag(), "Initial memory"); // OK
   Superclass::GenerateOutputInformation();
-  //this->GetOutput(0)->SetRequestedRegion(this->GetOutput(0)->GetLargestPossibleRegion());
+  
+  // Read DB
+  LoadAFDB();
 
   // Get input pointers
-  patient = dynamic_cast<const MaskImageType*>(itk::ProcessObject::GetInput(1));
   input   = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
+  patient = GetAFDB()->template GetImage <MaskImageType>("Patient");  
+  PrintMemory(GetVerboseMemoryFlag(), "After reading patient"); // OK
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // Crop input like patient image (must have the same spacing)
+  // It copy the input if the same are the same
+  StartNewStep("Copy and crop input image to 'patient' extends");
+  typedef clitk::CropLikeImageFilter<ImageType> CropImageFilter;
+  typename CropImageFilter::Pointer cropFilter = CropImageFilter::New();
+  // cropFilter->ReleaseDataFlagOn(); // NO=seg fault !!
+  cropFilter->SetInput(input);
+  cropFilter->SetCropLikeImage(patient);
+  cropFilter->Update();
+  working_input = cropFilter->GetOutput();
+  //  cropFilter->Delete(); // NO !!!! if yes, sg fault, Cropfilter is buggy !??
+  StopCurrentStep<ImageType>(working_input);
+  PrintMemory(GetVerboseMemoryFlag(), "After crop"); // OK, slightly more than a copy of input
 
-  // Check image
-  if (!HaveSameSizeAndSpacing<ImageType, MaskImageType>(input, patient)) {
-    clitkExceptionMacro("the 'input' and 'patient' masks must have the same size & spacing.");
-  }
-  
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
   StartNewStep("Set background to initial image");
   working_input = SetBackground<ImageType, MaskImageType>
-    (input, patient, GetPatientMaskBackgroundValue(), -1000);
+    (working_input, patient, GetPatientMaskBackgroundValue(), -1000, true);
+
+  // Pad images with air to prevent patient touching the image border
+  static const unsigned int Dim = ImageType::ImageDimension;
+  typedef itk::ConstantPadImageFilter<ImageType, ImageType> PadFilterType;
+  typename PadFilterType::Pointer padFilter = PadFilterType::New();
+  padFilter->SetInput(working_input);
+  padFilter->SetConstant(-1000);
+  typename ImageType::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();
+  working_input = padFilter->GetOutput();
+
   StopCurrentStep<ImageType>(working_input);
+  PrintMemory(GetVerboseMemoryFlag(), "After set bg"); // OK, additional mem = 0
+
+  /*
+  // We do not need patient mask anymore, release memory 
+  GetAFDB()->template ReleaseImage<MaskImageType>("Patient");
+  DD(patient->GetReferenceCount());
+  PrintMemory(GetVerboseMemoryFlag(), "After delete patient"); // OK, additional mem = 0
+  patient->Delete();
+  PrintMemory(GetVerboseMemoryFlag(), "After delete patient"); // OK, additional mem = 0
+  */
 
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
@@ -198,33 +200,41 @@ GenerateOutputInformation()
     }
   }
   // Threshold to get air
-  typedef itk::BinaryThresholdImageFilter<ImageType, InternalImageType> InputBinarizeFilterType; 
-  typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New();
+  typedef itk::BinaryThresholdImageFilter<ImageType, MaskImageType> InputBinarizeFilterType; 
+  typename InputBinarizeFilterType::Pointer binarizeFilter = InputBinarizeFilterType::New();
   binarizeFilter->SetInput(working_input);
   if (m_UseLowerThreshold) binarizeFilter->SetLowerThreshold(m_LowerThreshold);
+  // binarizeFilter->CanRunInPlace() is false
   binarizeFilter->SetUpperThreshold(m_UpperThreshold);
-  binarizeFilter ->SetInsideValue(this->GetForegroundValue());
-  binarizeFilter ->SetOutsideValue(this->GetBackgroundValue());
+  binarizeFilter->SetInsideValue(this->GetForegroundValue());
+  binarizeFilter->SetOutsideValue(this->GetBackgroundValue());
   binarizeFilter->Update();
-  working_image = binarizeFilter->GetOutput();
-  
-  // Labelize and keep right labels
-  working_image = Labelize<InternalImageType>(working_image, GetBackgroundValue(), true, GetMinimalComponentSize());
+  working_mask = binarizeFilter->GetOutput();
+  PrintMemory(GetVerboseMemoryFlag(), "After Binarizefilter"); // OK, additional mem is one mask image
 
-  working_image = RemoveLabels<InternalImageType>
-    (working_image, GetBackgroundValue(), GetLabelizeParameters1()->GetLabelsToRemove());
+  // Labelize and keep right labels
+  working_mask = 
+    Labelize<MaskImageType>
+    (working_mask, GetBackgroundValue(), true, GetMinimalComponentSize());
+  PrintMemory(GetVerboseMemoryFlag(), "After Labelize"); // BUG ? additional mem around 1 time the input ? 
+  
+  working_mask = RemoveLabels<MaskImageType>
+    (working_mask, GetBackgroundValue(), GetLabelizeParameters1()->GetLabelsToRemove());
+  PrintMemory(GetVerboseMemoryFlag(), "After RemoveLabels"); // OK additional mem = 0
 
-  typename InternalImageType::Pointer air = KeepLabels<InternalImageType>
-    (working_image
+  working_mask = KeepLabels<MaskImageType>
+    (working_mask
      GetBackgroundValue(), 
      GetForegroundValue(), 
      GetLabelizeParameters1()->GetFirstKeep(), 
      GetLabelizeParameters1()->GetLastKeep(), 
      GetLabelizeParameters1()->GetUseLastKeep());
+  PrintMemory(GetVerboseMemoryFlag(), "After KeepLabels to create the 'air'");
  
   // Set Air to BG
-  working_input = SetBackground<ImageType, InternalImageType>
-    (working_input, air, this->GetForegroundValue(), this->GetBackgroundValue());
+  working_input = SetBackground<ImageType, MaskImageType>
+    (working_input, working_mask, this->GetForegroundValue(), this->GetBackgroundValue(), true);
+  PrintMemory(GetVerboseMemoryFlag(), "After SetBackground");
 
   // End
   StopCurrentStep<ImageType>(working_input);
@@ -233,29 +243,31 @@ GenerateOutputInformation()
   //--------------------------------------------------------------------
   StartNewStep("Search for the trachea");
   SearchForTrachea();
+  PrintMemory(GetVerboseMemoryFlag(), "After SearchForTrachea");
 
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
   StartNewStep("Extract the lung with Otsu filter");
   // Automated Otsu thresholding and relabeling
-  typedef itk::OtsuThresholdImageFilter<ImageType,InternalImageType> OtsuThresholdImageFilterType;
+  typedef itk::OtsuThresholdImageFilter<ImageType,MaskImageType> OtsuThresholdImageFilterType;
   typename OtsuThresholdImageFilterType::Pointer otsuFilter=OtsuThresholdImageFilterType::New();
   otsuFilter->SetInput(working_input);
   otsuFilter->SetNumberOfHistogramBins(GetNumberOfHistogramBins());
   otsuFilter->SetInsideValue(this->GetForegroundValue());
   otsuFilter->SetOutsideValue(this->GetBackgroundValue());
   otsuFilter->Update();
-  working_image =  otsuFilter->GetOutput();
+  working_mask =  otsuFilter->GetOutput();
 
   // Set output
-  StopCurrentStep<InternalImageType>(working_image);
+  StopCurrentStep<MaskImageType>(working_mask);
+  PrintMemory(GetVerboseMemoryFlag(), "After Otsufilter");
 
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
   StartNewStep("Select labels");
   // Keep right labels
-  working_image = LabelizeAndSelectLabels<InternalImageType>
-    (working_image
+  working_mask = LabelizeAndSelectLabels<MaskImageType>
+    (working_mask
      GetBackgroundValue(), 
      GetForegroundValue(), 
      false, 
@@ -263,15 +275,17 @@ GenerateOutputInformation()
      GetLabelizeParameters2());
 
   // Set output
-  StopCurrentStep<InternalImageType>(working_image);
+  StopCurrentStep<MaskImageType>(working_mask);
+  PrintMemory(GetVerboseMemoryFlag(), "After LabelizeAndSelectLabels");
   
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
   if (m_Seeds.size() != 0) { // if ==0 ->no trachea found
     StartNewStep("Remove the trachea");
     // Set the trachea
-    working_image = SetBackground<InternalImageType, InternalImageType>
-      (working_image, trachea_tmp, 1, -1);
+    working_mask = SetBackground<MaskImageType, MaskImageType>
+      (working_mask, trachea, 1, -1, true);
+    PrintMemory(GetVerboseMemoryFlag(), "After SetBackground");
   
     // Dilate the trachea 
     static const unsigned int Dim = ImageType::ImageDimension;
@@ -279,27 +293,28 @@ GenerateOutputInformation()
     KernelType structuringElement;
     structuringElement.SetRadius(GetRadiusForTrachea());
     structuringElement.CreateStructuringElement();
-    typedef clitk::ConditionalBinaryDilateImageFilter<InternalImageType, InternalImageType, KernelType> ConditionalBinaryDilateImageFilterType;
+    typedef clitk::ConditionalBinaryDilateImageFilter<MaskImageType, MaskImageType, KernelType> ConditionalBinaryDilateImageFilterType;
     typename ConditionalBinaryDilateImageFilterType::Pointer dilateFilter = ConditionalBinaryDilateImageFilterType::New();
     dilateFilter->SetBoundaryToForeground(false);
     dilateFilter->SetKernel(structuringElement);
     dilateFilter->SetBackgroundValue (1);
     dilateFilter->SetForegroundValue (-1);
-    dilateFilter->SetInput (working_image);
+    dilateFilter->SetInput (working_mask);
     dilateFilter->Update();
-    working_image = dilateFilter->GetOutput();  
+    working_mask = dilateFilter->GetOutput();  
+    PrintMemory(GetVerboseMemoryFlag(), "After dilate");
     
     // Set trachea with dilatation
-    trachea_tmp = SetBackground<InternalImageType, InternalImageType>
-      (trachea_tmp, working_image, -1, this->GetForegroundValue()); 
+    trachea = SetBackground<MaskImageType, MaskImageType>
+      (trachea, working_mask, -1, this->GetForegroundValue(), true); 
 
     // Remove the trachea
-    working_image = SetBackground<InternalImageType, InternalImageType>
-      (working_image, working_image, -1, this->GetBackgroundValue());  
+    working_mask = SetBackground<MaskImageType, MaskImageType>
+      (working_mask, working_mask, -1, this->GetBackgroundValue(), true);  
     
     // Label
-    working_image = LabelizeAndSelectLabels<InternalImageType>
-      (working_image
+    working_mask = LabelizeAndSelectLabels<MaskImageType>
+      (working_mask
        GetBackgroundValue(), 
        GetForegroundValue(), 
        false, 
@@ -307,60 +322,128 @@ GenerateOutputInformation()
        GetLabelizeParameters3());
     
     // Set output
-    StopCurrentStep<InternalImageType>(working_image);
+    StopCurrentStep<MaskImageType>(working_mask);
   }
 
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
-  typedef clitk::AutoCropFilter<InternalImageType> CropFilterType;
-  typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+  PrintMemory(GetVerboseMemoryFlag(), "before autocropfilter");
   if (m_Seeds.size() != 0) { // if ==0 ->no trachea found
-    StartNewStep("Croping trachea");
-    cropFilter->SetInput(trachea_tmp);
-    cropFilter->Update(); // Needed
-    typedef itk::CastImageFilter<InternalImageType, MaskImageType> CastImageFilterType;
-    typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
-    caster->SetInput(cropFilter->GetOutput());
-    caster->Update();   
-    trachea = caster->GetOutput();
+    if (GetAutoCrop())
+      trachea = clitk::AutoCrop<MaskImageType>(trachea, GetBackgroundValue());
+    else
+    {
+      // Remove Padding region
+      typedef itk::CropImageFilter<MaskImageType, MaskImageType> CropFilterType;
+      typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+      cropFilter->SetInput(trachea);
+      cropFilter->SetLowerBoundaryCropSize(bounds);
+      cropFilter->SetUpperBoundaryCropSize(bounds);
+      cropFilter->Update();
+      trachea = cropFilter->GetOutput();
+    }
     StopCurrentStep<MaskImageType>(trachea);  
+    PrintMemory(GetVerboseMemoryFlag(), "after delete trachea");
   }
+  PrintMemory(GetVerboseMemoryFlag(), "after delete trachea");
 
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
-  StartNewStep("Croping lung");
-  typename CropFilterType::Pointer cropFilter2 = CropFilterType::New(); // Needed to reset pipeline
-  cropFilter2->SetInput(working_image);
-  cropFilter2->Update();   
-  working_image = cropFilter2->GetOutput();
-  StopCurrentStep<InternalImageType>(working_image);
+  StartNewStep("Cropping lung");
+  PrintMemory(GetVerboseMemoryFlag(), "Before Autocropfilter");
+  if (GetAutoCrop())
+    working_mask = clitk::AutoCrop<MaskImageType>(working_mask, GetBackgroundValue());
+  else
+  {
+    // Remove Padding region
+    typedef itk::CropImageFilter<MaskImageType, MaskImageType> CropFilterType;
+    typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+    cropFilter->SetInput(working_mask);
+    cropFilter->SetLowerBoundaryCropSize(bounds);
+    cropFilter->SetUpperBoundaryCropSize(bounds);
+    cropFilter->Update();
+    working_mask = cropFilter->GetOutput();
+  }
+  StopCurrentStep<MaskImageType>(working_mask);
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // Final OpenClose
+  if (GetOpenCloseFlag()) {
+    StartNewStep("Open/Close"); 
+    PrintMemory(GetVerboseMemoryFlag(), "Before OpenClose");
+  
+    // Structuring element
+    typedef itk::BinaryBallStructuringElement<InternalPixelType, ImageDimension> KernelType;
+    KernelType structuringElement;
+    structuringElement.SetRadius(GetOpenCloseRadius());
+    structuringElement.CreateStructuringElement();
+       
+    // Open
+    typedef itk::BinaryMorphologicalOpeningImageFilter<MaskImageType, InternalImageType, KernelType> OpenFilterType;
+    typename OpenFilterType::Pointer openFilter = OpenFilterType::New();
+    openFilter->SetInput(working_mask);
+    openFilter->SetBackgroundValue(GetBackgroundValue());
+    openFilter->SetForegroundValue(GetForegroundValue());
+    openFilter->SetKernel(structuringElement);
+       
+    // Close
+    typedef itk::BinaryMorphologicalClosingImageFilter<MaskImageType, MaskImageType, KernelType> CloseFilterType;
+    typename CloseFilterType::Pointer closeFilter = CloseFilterType::New();
+    closeFilter->SetInput(openFilter->GetOutput());
+    closeFilter->SetSafeBorder(true);
+    closeFilter->SetForegroundValue(GetForegroundValue());
+    closeFilter->SetKernel(structuringElement);
+    closeFilter->Update();
+    working_mask = closeFilter->GetOutput();
+  }
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // Fill Lungs
+  if (GetFillHolesFlag()) {
+    StartNewStep("Fill Holes");
+    PrintMemory(GetVerboseMemoryFlag(), "Before Fill Holes");
+    typedef clitk::FillMaskFilter<MaskImageType> FillMaskFilterType;
+    typename FillMaskFilterType::Pointer fillMaskFilter = FillMaskFilterType::New();
+    fillMaskFilter->SetInput(working_mask);
+    fillMaskFilter->AddDirection(2);
+    //fillMaskFilter->AddDirection(1);
+    fillMaskFilter->Update();   
+    working_mask = fillMaskFilter->GetOutput();
+    StopCurrentStep<MaskImageType>(working_mask);
+  }
 
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
   StartNewStep("Separate Left/Right lungs");
+    PrintMemory(GetVerboseMemoryFlag(), "Before Separate");
   // Initial label
-  working_image = Labelize<InternalImageType>(working_image, 
-                                              GetBackgroundValue(), 
-                                              false, 
-                                              GetMinimalComponentSize());
+  working_mask = Labelize<MaskImageType>(working_mask, 
+                                         GetBackgroundValue(), 
+                                         false, 
+                                         GetMinimalComponentSize());
+
+  PrintMemory(GetVerboseMemoryFlag(), "After Labelize");
 
   // Count the labels
-  typedef itk::StatisticsImageFilter<InternalImageType> StatisticsImageFilterType;
+  typedef itk::StatisticsImageFilter<MaskImageType> StatisticsImageFilterType;
   typename StatisticsImageFilterType::Pointer statisticsImageFilter=StatisticsImageFilterType::New();
-  statisticsImageFilter->SetInput(working_image);
+  statisticsImageFilter->SetInput(working_mask);
   statisticsImageFilter->Update();
   unsigned int initialNumberOfLabels = statisticsImageFilter->GetMaximum();
-  working_image = statisticsImageFilter->GetOutput();  
+  working_mask = statisticsImageFilter->GetOutput();   
+  
+  PrintMemory(GetVerboseMemoryFlag(), "After count label");
  
   // Decompose the first label
-  static const unsigned int Dim = ImageType::ImageDimension;
   if (initialNumberOfLabels<2) {
     // Structuring element radius
     typename ImageType::SizeType radius;
     for (unsigned int i=0;i<Dim;i++) radius[i]=1;
-    typedef clitk::DecomposeAndReconstructImageFilter<InternalImageType,InternalImageType> DecomposeAndReconstructFilterType;
+    typedef clitk::DecomposeAndReconstructImageFilter<MaskImageType,MaskImageType> DecomposeAndReconstructFilterType;
     typename DecomposeAndReconstructFilterType::Pointer decomposeAndReconstructFilter=DecomposeAndReconstructFilterType::New();
-    decomposeAndReconstructFilter->SetInput(working_image);
+    decomposeAndReconstructFilter->SetInput(working_mask);
     decomposeAndReconstructFilter->SetVerbose(false);
     decomposeAndReconstructFilter->SetRadius(radius);
     decomposeAndReconstructFilter->SetMaximumNumberOfLabels(2);
@@ -371,229 +454,62 @@ GenerateOutputInformation()
     decomposeAndReconstructFilter->SetFullyConnected(true);
     decomposeAndReconstructFilter->SetNumberOfNewLabels(1);
     decomposeAndReconstructFilter->Update();
-    working_image = decomposeAndReconstructFilter->GetOutput();      
+    working_mask = decomposeAndReconstructFilter->GetOutput();      
   }
+  PrintMemory(GetVerboseMemoryFlag(), "After decomposeAndReconstructFilter");
 
   // Retain labels ('1' is largset lung, so right. '2' is left)
-  typedef itk::ThresholdImageFilter<InternalImageType> ThresholdImageFilterType;
+  typedef itk::ThresholdImageFilter<MaskImageType> ThresholdImageFilterType;
   typename ThresholdImageFilterType::Pointer thresholdFilter = ThresholdImageFilterType::New();
-  thresholdFilter->SetInput(working_image);
+  thresholdFilter->SetInput(working_mask);
   thresholdFilter->ThresholdAbove(2);
   thresholdFilter->SetOutsideValue(this->GetBackgroundValue());
   thresholdFilter->Update();
-  working_image = thresholdFilter->GetOutput();
-  StopCurrentStep<InternalImageType> (working_image);
-  
-  // Final Cast 
-  StartNewStep("Cast the lung mask"); 
-  typedef itk::CastImageFilter<InternalImageType, MaskImageType> CastImageFilterType;
-  typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
-  caster->SetInput(working_image);
-  caster->Update();
-  output = caster->GetOutput();
+  working_mask = thresholdFilter->GetOutput();
+  StopCurrentStep<MaskImageType> (working_mask);
+  PrintMemory(GetVerboseMemoryFlag(), "After Thresholdfilter");
 
   // Update output info
-  this->GetOutput(0)->SetRegions(output->GetLargestPossibleRegion());
+  //  output = working_mask;
+  //this->GetOutput(0)->SetRegions(output->GetLargestPossibleRegion());
 
-  // Try to extract bifurcation in the trachea (bronchi)
-  if (m_Seeds.size() != 0) { // if ==0 ->no trachea found
+  //  this->GetOutput(0)->SetRegions(working_mask->GetLargestPossibleRegion());
 
-    if (GetFindBronchialBifurcations()) {
-      StartNewStep("Find bronchial bifurcations");
-      // Step 1 : extract skeleton
-      typedef itk::BinaryThinningImageFilter3D<MaskImageType, MaskImageType> ThinningFilterType;
-      typename ThinningFilterType::Pointer thinningFilter = ThinningFilterType::New();
-      thinningFilter->SetInput(trachea);
-      thinningFilter->Update();
-      typename MaskImageType::Pointer skeleton = thinningFilter->GetOutput();
-
-      // Step 2.1 : find first point for tracking
-      typedef itk::ImageRegionConstIteratorWithIndex<MaskImageType> IteratorType;
-      IteratorType it(skeleton, skeleton->GetLargestPossibleRegion());
-      it.GoToReverseBegin();
-      while ((!it.IsAtEnd()) && (it.Get() == GetBackgroundValue())) { 
-        --it;
-      }
-      if (it.IsAtEnd()) {
-        clitkExceptionMacro("first point in the trachea skeleton not found.");
-      }
-      typename MaskImageType::IndexType index = it.GetIndex();
-    
-      // Step 2.2 : initialize neighborhooditerator
-      typedef itk::NeighborhoodIterator<MaskImageType> NeighborhoodIteratorType;
-      typename NeighborhoodIteratorType::SizeType radius;
-      radius.Fill(1);
-      NeighborhoodIteratorType nit(radius, skeleton, skeleton->GetLargestPossibleRegion());
-    
-      // Find first label number (must be different from BG and FG)
-      typename MaskImageType::PixelType label = GetForegroundValue()+1;
-      while ((label == GetBackgroundValue()) || (label == GetForegroundValue())) { label++; }
-
-      // Track from the first point
-      std::vector<BifurcationType> listOfBifurcations;
-      m_SkeletonTree.set_head(index);
-      TrackFromThisIndex(listOfBifurcations, skeleton, index, label, m_SkeletonTree.begin());
-      DD("end track");
-      DD(listOfBifurcations.size());
-      DD(m_SkeletonTree.size());
-      
-      for(unsigned int i=0; i<listOfBifurcations.size(); i++) {
-        skeleton->TransformIndexToPhysicalPoint(listOfBifurcations[i].index, 
-                                                listOfBifurcations[i].point);
-      }
-
-      // Search for the first slice that separate the bronchus (carena)
-      typedef clitk::ExtractSliceFilter<MaskImageType> ExtractSliceFilterType;
-      typename ExtractSliceFilterType::Pointer extractSliceFilter = ExtractSliceFilterType::New();
-      extractSliceFilter->SetInput(trachea);
-      extractSliceFilter->SetDirection(2);
-      extractSliceFilter->Update();
-      typedef typename ExtractSliceFilterType::SliceType SliceType;
-      std::vector<typename SliceType::Pointer> mInputSlices;
-      extractSliceFilter->GetOutputSlices(mInputSlices);
-      
-      bool stop = false;
-      DD(listOfBifurcations[0].index);
-      DD(listOfBifurcations[1].index);
-      int slice_index = listOfBifurcations[0].index[2]; // first slice from carena in skeleton
-      int i=0;
-      TreeIterator firstIter = m_SkeletonTree.child(listOfBifurcations[1].treeIter, 0);
-      TreeIterator secondIter = m_SkeletonTree.child(listOfBifurcations[1].treeIter, 1);
-      typename SliceType::IndexType in1;
-      typename SliceType::IndexType in2;
-      while (!stop) {
-        DD(slice_index);
-
-       //  Labelize the current slice
-        typename SliceType::Pointer temp = Labelize<SliceType>(mInputSlices[slice_index],
-                                                               GetBackgroundValue(), 
-                                                               true, 
-                                                               GetMinimalComponentSize());
-       // Check the value of the two skeleton points;
-        in1[0] = (*firstIter)[0];
-        in1[1] = (*firstIter)[1];
-       typename SliceType::PixelType v1 = temp->GetPixel(in1);
-       DD(in1);
-       DD((int)v1);
-        in2[0] = (*secondIter)[0];
-        in2[1] = (*secondIter)[1];
-       typename SliceType::PixelType v2 = temp->GetPixel(in2);
-       DD(in2);
-       DD((int)v2);
-
-       // TODO IF NOT FOUND ????
-
-        if (v1 != v2) {
-         stop = true;
-       }
-       else {
-         i++;
-         --slice_index;
-         ++firstIter;
-         ++secondIter;
-       }
-      }
-      MaskImageIndexType carena_index;
-      carena_index[0] = lrint(in2[0] + in1[0])/2.0;
-      carena_index[1] = lrint(in2[1] + in1[1])/2.0;
-      carena_index[2] = slice_index;
-      MaskImagePointType carena_position;
-      DD(carena_index);
-      skeleton->TransformIndexToPhysicalPoint(carena_index,
-                                             carena_position);
-      DD(carena_position);
-
-      // Set and save Carina position      
-      StartNewStep("Save carina position");
-      // Try to load the DB
-      try {
-        LoadAFDB();
-      } catch (clitk::ExceptionObject e) {
-        // Do nothing if not found, it will be used anyway to write the result
-      }
-      GetAFDB()->SetPoint3D("Carena", carena_position);
-    }
-  }
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class TImageType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
-GenerateData() 
-{
-  // If everything goes well, set the output
-  this->GraftOutput(output); // not SetNthOutput
+clitk::ExtractLungFilter<TImageType>::
+GenerateInputRequestedRegion() {
+  //  DD("GenerateInputRequestedRegion (nothing?)");
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
-TrackFromThisIndex(std::vector<BifurcationType> & listOfBifurcations, 
-                   MaskImagePointer skeleton, 
-                   MaskImageIndexType index,
-                   MaskImagePixelType label, 
-                  TreeIterator currentNode) 
+clitk::ExtractLungFilter<ImageType>::
+GenerateData() 
 {
-  // Create NeighborhoodIterator 
-  typedef itk::NeighborhoodIterator<MaskImageType> NeighborhoodIteratorType;
-  typename NeighborhoodIteratorType::SizeType radius;
-  radius.Fill(1);
-  NeighborhoodIteratorType nit(radius, skeleton, skeleton->GetLargestPossibleRegion());
-      
-  // Track
-  std::vector<typename NeighborhoodIteratorType::IndexType> listOfTrackedPoint;
-  bool stop = false;
-  while (!stop) {
-    nit.SetLocation(index);
-    nit.SetCenterPixel(label);
-    listOfTrackedPoint.clear();
-    for(unsigned int i=0; i<nit.Size(); i++) {
-      if (i != nit.GetCenterNeighborhoodIndex ()) { // Do not observe the current point
-        if (nit.GetPixel(i) == GetForegroundValue()) { // if this is foreground, we continue the tracking
-          listOfTrackedPoint.push_back(nit.GetIndex(i));
-        }
-      }
-    }
-    if (listOfTrackedPoint.size() == 1) {
-      // Add this point to the current path
-      currentNode = m_SkeletonTree.append_child(currentNode, listOfTrackedPoint[0]);
-      index = listOfTrackedPoint[0];
-    }
-    else {
-      if (listOfTrackedPoint.size() == 2) {
-        // m_SkeletonTree->Add(listOfTrackedPoint[0], index); // the parent is 'index'
-        // m_SkeletonTree->Add(listOfTrackedPoint[1], index); // the parent is 'index'
-        BifurcationType bif(index, label, label+1, label+2);
-       bif.treeIter = currentNode;
-        listOfBifurcations.push_back(bif);
-       TreeIterator firstNode = m_SkeletonTree.append_child(currentNode, listOfTrackedPoint[0]);
-        TreeIterator secondNode = m_SkeletonTree.append_child(currentNode, listOfTrackedPoint[1]);
-        TrackFromThisIndex(listOfBifurcations, skeleton, listOfTrackedPoint[0], label+1, firstNode);
-        TrackFromThisIndex(listOfBifurcations, skeleton, listOfTrackedPoint[1], label+2, secondNode);
-      }
-      else {
-        if (listOfTrackedPoint.size() > 2) {
-          clitkExceptionMacro("error while tracking trachea bifurcation. Too much bifurcation points ... ?");
-        }
-        // Else this it the end of the tracking
-      }
-      stop = true;
-    }
-  }
+  // Set the output
+  //  this->GraftOutput(output); // not SetNthOutput
+  this->GraftOutput(working_mask); // not SetNthOutput
+  // Store image filenames into AFDB 
+  GetAFDB()->SetImageFilename("Lungs", this->GetOutputLungFilename());  
+  GetAFDB()->SetImageFilename("Trachea", this->GetOutputTracheaFilename());  
+  WriteAFDB();
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 bool 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 SearchForTracheaSeed(int skip)
 {
   if (m_Seeds.size() == 0) { // try to find seed (if not zero, it is given by user)    
@@ -623,7 +539,7 @@ SearchForTracheaSeed(int skip)
       // if we do not found : restart
       stop = (m_Seeds.size() != 0);
       if (!stop) {
-       if (GetVerboseStep()) {
+       if (GetVerboseStepFlag()) {
          std::cout << "\t No seed found this time. I skip some slices and restart." << std::endl;
        }
         if (skip > 0.5 * working_input->GetLargestPossibleRegion().GetSize()[2]) {
@@ -633,6 +549,10 @@ SearchForTracheaSeed(int skip)
         }
         skip += 5;
       }
+      else {
+        // DD(m_Seeds[0]);
+        // DD(m_Seeds.size());
+      }
     }
   }
   return (m_Seeds.size() != 0);
@@ -641,20 +561,21 @@ SearchForTracheaSeed(int skip)
 
   
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 TracheaRegionGrowing()
 {
   // Explosion controlled region growing
-  typedef clitk::ExplosionControlledThresholdConnectedImageFilter<ImageType, InternalImageType> ImageFilterType;
+  PrintMemory(GetVerboseMemoryFlag(), "Before ExplosionControlledThresholdConnectedImageFilter");
+  typedef clitk::ExplosionControlledThresholdConnectedImageFilter<ImageType, MaskImageType> ImageFilterType;
   typename ImageFilterType::Pointer f= ImageFilterType::New();
   f->SetInput(working_input);
-  f->SetVerbose(false);
   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); 
@@ -662,33 +583,37 @@ TracheaRegionGrowing()
   f->SetMultiplier(GetMultiplierForTrachea());
   f->SetThresholdStepSize(GetThresholdStepSizeForTrachea());
   f->SetMinimumThresholdStepSize(1);
+  f->SetVerbose(GetVerboseRegionGrowingFlag());
   for(unsigned int i=0; i<m_Seeds.size();i++) {
     f->AddSeed(m_Seeds[i]);
     // DD(m_Seeds[i]);
   }  
   f->Update();
-
+  PrintMemory(GetVerboseMemoryFlag(), "After RG update");
+  
   // take first (main) connected component
-  trachea_tmp = Labelize<InternalImageType>(f->GetOutput(), 
-                                           GetBackgroundValue(), 
-                                           true, 
-                                           GetMinimalComponentSize());
-  trachea_tmp = KeepLabels<InternalImageType>(trachea_tmp, 
+  trachea = Labelize<MaskImageType>(f->GetOutput(), 
+                                    GetBackgroundValue(), 
+                                    true, 
+                                    1000);//GetMinimalComponentSize());
+  PrintMemory(GetVerboseMemoryFlag(), "After Labelize");
+  trachea = KeepLabels<MaskImageType>(trachea, 
                                              GetBackgroundValue(), 
                                              GetForegroundValue(), 
                                              1, 1, false);
+  PrintMemory(GetVerboseMemoryFlag(), "After KeepLabels");
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 double 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 ComputeTracheaVolume()
 {
   typedef itk::ImageRegionConstIterator<InternalImageType> IteratorType;
-  IteratorType iter(trachea_tmp, trachea_tmp->GetLargestPossibleRegion());
+  IteratorType iter(trachea, trachea->GetLargestPossibleRegion());
   iter.GoToBegin();
   double volume = 0.0;
   while (!iter.IsAtEnd()) {
@@ -696,16 +621,16 @@ ComputeTracheaVolume()
     ++iter;
   }
   
-  double voxelsize = trachea_tmp->GetSpacing()[0]*trachea_tmp->GetSpacing()[1]*trachea_tmp->GetSpacing()[2];
+  double voxelsize = trachea->GetSpacing()[0]*trachea->GetSpacing()[1]*trachea->GetSpacing()[2];
   return volume*voxelsize;
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
-void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+template <class ImageType>
+void
+clitk::ExtractLungFilter<ImageType>::
 SearchForTrachea()
 {
   // Search for seed among n slices, skip some slices before starting
@@ -719,34 +644,46 @@ SearchForTrachea()
   double volume = 0.0;
   int skip = GetNumberOfSlicesToSkipBeforeSearchingSeed();
   while (!stop) {
-    stop = SearchForTracheaSeed(skip);
-    if (stop) {
+    stop = true;
+    if (SearchForTracheaSeed(skip)) {
       TracheaRegionGrowing();
       volume = ComputeTracheaVolume()/1000; // assume mm3, so divide by 1000 to get cc
-      if ((volume > 10) && (volume < 55 )) { // it is ok
-        // Typical volume 22.59 cm 3 (± 7.69 cm 3 ) [ Leader 2004 ]
-       if (GetVerboseStep()) {
-         std::cout << "\t Found trachea with volume " << volume << " cc." << std::endl;
-       }
-        stop = true; 
+      if (GetWriteStepFlag()) {
+        writeImage<MaskImageType>(trachea, "step-trachea-"+toString(skip)+".mhd");
+      }
+      if (GetTracheaVolumeMustBeCheckedFlag()) {
+        if ((volume > 10) && (volume < 65 )) { // depend on image size ...
+          // Typical volume 22.59 cm 3 (± 7.69 cm 3 ) [ Leader 2004 ]
+          if (GetVerboseStepFlag()) {
+            std::cout << "\t Found trachea with volume " << volume << " cc." << std::endl;
+          }
+        }
+        else {
+          if (GetVerboseStepFlag()) {
+            std::cout << "\t The volume of the trachea (" << volume 
+                      << " cc) seems not correct. I skip some slices (" << skip << ") and restart to find seeds." 
+                      << std::endl;
+          }
+          skip += 5;
+          stop = false;
+          // empty the list of seed
+          m_Seeds.clear();
+        }
+        if (skip > 0.5 * working_input->GetLargestPossibleRegion().GetSize()[2]) {
+          // we want to skip more than a half of the image, it is probably a bug
+          std::cerr << "2 : Number of slices to skip to find trachea too high = " << skip << std::endl;
+          stop = true;
+        }
       }
       else {
-       if (GetVerboseStep()) {
-         std::cout << "\t The volume of the trachea (" << volume 
-                   << " cc) seems not correct. I skip some slices (" << skip << ") and restart to find seeds." 
-                   << std::endl;
-       }
-        skip += 5;
-        stop = false;
-       // empty the list of seed
-       m_Seeds.clear();
+        stop = true;
       }
     }
   }
 
   if (volume != 0.0) {
     // Set output
-    StopCurrentStep<InternalImageType>(trachea_tmp);
+    StopCurrentStep<MaskImageType>(trachea);
   }
   else { // Trachea not found
     this->SetWarning("* WARNING * No seed found for trachea.");