]> Creatis software - clitk.git/commitdiff
small improvement
authordsarrut <dsarrut>
Fri, 22 Oct 2010 07:37:10 +0000 (07:37 +0000)
committerdsarrut <dsarrut>
Fri, 22 Oct 2010 07:37:10 +0000 (07:37 +0000)
17 files changed:
segmentation/clitkAnatomicalFeatureDatabase.cxx
segmentation/clitkAnatomicalFeatureDatabase.h
segmentation/clitkExtractAirwaysTreeInfoFilter.txx
segmentation/clitkExtractBones.ggo
segmentation/clitkExtractBonesFilter.h
segmentation/clitkExtractBonesFilter.txx
segmentation/clitkExtractBonesGenericFilter.txx
segmentation/clitkExtractLung.ggo
segmentation/clitkExtractLungFilter.h
segmentation/clitkExtractLungFilter.txx
segmentation/clitkExtractLungGenericFilter.h
segmentation/clitkExtractLungGenericFilter.txx
segmentation/clitkExtractMediastinumFilter.txx
segmentation/clitkExtractPatient.ggo
segmentation/clitkExtractPatientFilter.h
segmentation/clitkExtractPatientFilter.txx
segmentation/clitkExtractPatientGenericFilter.txx

index afd082e0d1c9453dedfef87aaa003d970a275a6b..dbd05c61a30fcb8a628fef0150a7b6de8dfd3f37 100644 (file)
@@ -47,6 +47,25 @@ void clitk::AnatomicalFeatureDatabase::Write()
 //--------------------------------------------------------------------
 
 
+//--------------------------------------------------------------------
+//http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
+// trim from start
+static inline std::string &ltrim(std::string &s) {
+  s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
+  return s;
+}
+// trim from end
+static inline std::string &rtrim(std::string &s) {
+  s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
+  return s;
+}
+// trim from both ends
+static inline std::string &trim(std::string &s) {
+  return ltrim(rtrim(s));
+}
+//--------------------------------------------------------------------
+
+
 //--------------------------------------------------------------------
 void clitk::AnatomicalFeatureDatabase::Load() 
 {
@@ -59,6 +78,7 @@ void clitk::AnatomicalFeatureDatabase::Load()
     is >> tag; 
     std::string value;
     std::getline(is,value,'\n');
+    ltrim(value); // remove leading space
     m_MapOfTag[tag] = value;
   }
 }
@@ -95,9 +115,7 @@ void clitk::AnatomicalFeatureDatabase::GetPoint3D(std::string tag, PointType3D &
 
     // parse the string into 3 doubles
     for(int i=0; i<3; i++) {
-      DD(results[i]);
       p[i] = atof(results[i].c_str());
-      DD(p[i]);
     }
 
     /*
@@ -109,12 +127,20 @@ void clitk::AnatomicalFeatureDatabase::GetPoint3D(std::string tag, PointType3D &
     boost::tokenizer<boost::char_separator<char> > tokens(s, sep);
     int i=0;
     BOOST_FOREACH(std::string t, tokens) {
-      std::cout << t << "." << std::endl;
-      p[i] = atof(t.c_str());
-      i++;
+    std::cout << t << "." << std::endl;
+    p[i] = atof(t.c_str());
+    i++;
     }
     */
   }
 }
 //--------------------------------------------------------------------
 
+
+//--------------------------------------------------------------------
+void clitk::AnatomicalFeatureDatabase::SetImageFilename(std::string tag, std::string f)
+{
+  m_MapOfTag[tag] = f;
+}
+//--------------------------------------------------------------------
+
index 78f04e32a91dbb512f65e680539d39b744f77113..dcf7efd27c90969208742e4481f5340ba211ad89 100644 (file)
 
 // clitk
 #include "clitkCommon.h"
+#include "clitkImageCommon.h"
 
 namespace clitk {
   
+
   //--------------------------------------------------------------------
   /*
     Class to store and retreive anatomical feature such as 3D
@@ -34,6 +36,8 @@ namespace clitk {
   public:
     AnatomicalFeatureDatabase();
 
+    typedef std::string TagType;
+
     // Set/Get filename 
     itkSetMacro(Filename, std::string);
     itkGetConstMacro(Filename, std::string);
@@ -42,19 +46,30 @@ namespace clitk {
     void Write();
     void Load();
     
-    // Get landmarks
+    // Set Get landmarks
     typedef itk::Point<double,3> PointType3D;
-    void SetPoint3D(std::string tag, PointType3D & p);
-    void GetPoint3D(std::string tag, PointType3D & p);
+    void SetPoint3D(TagType tag, PointType3D & p);
+    void GetPoint3D(TagType tag, PointType3D & p);
+    
+    // Set Get image
+    void SetImageFilename(TagType tag, std::string f);
+    template<class ImageType>
+    typename ImageType::Pointer GetImage(TagType tag);
     
+    // Set Get Double
+    void SetDouble(TagType tag, double d);
+    double GetDouble(TagType tag);
+
   protected:
     std::string m_Filename;
-    typedef std::map<std::string, std::string> MapTagType;
+    typedef std::map<TagType, std::string> MapTagType;
     MapTagType m_MapOfTag;
 
   }; // end class
   //--------------------------------------------------------------------
 
+  #include "clitkAnatomicalFeatureDatabase.txx" 
+
 } // end namespace clitk
 //--------------------------------------------------------------------
 
index 69b73808807670bd025c66861a4dcdf77d006394..6145ad764319dfb770a6b3d52b567942872a0971 100644 (file)
@@ -179,11 +179,19 @@ GenerateData()
   extractSliceFilter->GetOutputSlices(mInputSlices);
   DD(mInputSlices.size());
       
+
+  DD("REDO !!!!!!!!!!!!");
+  /**
+     => chercher la bif qui a les plus important sous-arbres
+   **/
+
   bool stop = false;
   int slice_index = listOfBifurcations[0].index[2]; // first slice from carina in skeleton
   int i=0;
   TreeIterator firstIter = m_SkeletonTree.child(listOfBifurcations[0].treeIter, 0);
   TreeIterator secondIter = m_SkeletonTree.child(listOfBifurcations[0].treeIter, 1);
+  DD(firstIter.number_of_children());
+  DD(secondIter.number_of_children());
   typename SliceType::IndexType in1;
   typename SliceType::IndexType in2;
   while (!stop) {
@@ -192,6 +200,8 @@ GenerateData()
                                                           GetBackgroundValue(), 
                                                           true, 
                                                           0); // min component size=0
+    DD(*firstIter);
+    DD(*secondIter);    
     // Check the value of the two skeleton points;
     in1[0] = (*firstIter)[0];
     in1[1] = (*firstIter)[1];
@@ -283,6 +293,9 @@ TrackFromThisIndex(std::vector<BifurcationType> & listOfBifurcations,
       if (listOfTrackedPoint.size() == 2) {
         // m_SkeletonTree->Add(listOfTrackedPoint[0], index); // the parent is 'index'
         // m_SkeletonTree->Add(listOfTrackedPoint[1], index); // the parent is 'index'
+        DD("BifurcationType");
+        DD(listOfTrackedPoint[0]);
+        DD(listOfTrackedPoint[1]);
         BifurcationType bif(index, label, label+1, label+2);
        bif.treeIter = currentNode;
         listOfBifurcations.push_back(bif);
index 1700413feaae8cb3e4378a81fd3e324c45a71ae7..cd737e7954fe8a4f7b33e9c231e8dc49a9f8706f 100644 (file)
@@ -15,7 +15,7 @@ section "I/O"
 
 option "input"         i       "Input image filename"            string        yes
 option "output"        o       "Output image filename"           string        yes
-#option "like"         l       "Resample like this image"        string        no
+option "afdb"           a      "Output Anatomical Feature DB (Carina position)"  string  no
 
 section "Smoothing (curvature anistropic diffusion)"
 
@@ -40,4 +40,4 @@ option "upper2"               -       "Upper threshold for RG"                double  no      default="1500"
 option "radius2"       -       "Neighborhood radius"                   int     no      multiple        default="1" 
 option "sampleRate2"   -       "Sample rate of label image for RG: number of voxels to skip between seeds"     int     no      default="0" 
 
-option "autoCrop"      -       "Crop final mask to BoundingBox"        flag    off
+option "noAutoCrop"    -       "If set : do no crop final mask to BoundingBox"                         flag    on
index 70daa482868c30f5725c1533cab5c9b5dba66bfe..e803e5a64fb6ce47f51613bd5d661fcf1c74dc41 100644 (file)
@@ -24,6 +24,7 @@
 #include "clitkDecomposeAndReconstructImageFilter.h"
 #include "clitkExplosionControlledThresholdConnectedImageFilter.h"
 #include "clitkSegmentationUtils.h"
+#include "clitkFilterWithAnatomicalFeatureDatabaseManagement.h"
 
 // itk
 #include "itkStatisticsImageFilter.h"
@@ -36,18 +37,21 @@ namespace clitk {
   */
   //--------------------------------------------------------------------
   
-  template <class TInputImageType, class TOutputImageType>
+  template <class TInputImageType>
   class ITK_EXPORT ExtractBonesFilter: 
-    public clitk::FilterBase, 
-    public itk::ImageToImageFilter<TInputImageType, TOutputImageType> 
+    public virtual clitk::FilterBase, 
+    public clitk::FilterWithAnatomicalFeatureDatabaseManagement,
+    public itk::ImageToImageFilter<TInputImageType, 
+                                   itk::Image<uchar, TInputImageType::ImageDimension> > 
   {
     
   public:
     /** Standard class typedefs. */
-    typedef ExtractBonesFilter              Self;
-    typedef itk::ImageToImageFilter<TInputImageType, TOutputImageType> Superclass;
-    typedef itk::SmartPointer<Self>         Pointer;
-    typedef itk::SmartPointer<const Self>   ConstPointer;
+    typedef itk::Image<uchar, TInputImageType::ImageDimension>      MaskImageType;
+    typedef ExtractBonesFilter                                      Self;
+    typedef itk::ImageToImageFilter<TInputImageType, MaskImageType> Superclass;
+    typedef itk::SmartPointer<Self>                                 Pointer;
+    typedef itk::SmartPointer<const Self>                           ConstPointer;
     
     /** Method for creation through the object factory. */
     itkNewMacro(Self);  
@@ -65,13 +69,12 @@ namespace clitk {
     typedef typename InputImageType::SizeType     InputImageSizeType; 
     typedef typename InputImageType::IndexType    InputImageIndexType; 
         
-    typedef TOutputImageType                       OutputImageType;
-    typedef typename OutputImageType::ConstPointer OutputImageConstPointer;
-    typedef typename OutputImageType::Pointer      OutputImagePointer;
-    typedef typename OutputImageType::RegionType   OutputImageRegionType; 
-    typedef typename OutputImageType::PixelType    OutputImagePixelType; 
-    typedef typename OutputImageType::SizeType     OutputImageSizeType; 
-    typedef typename OutputImageType::IndexType    OutputImageIndexType; 
+    typedef typename MaskImageType::ConstPointer MaskImageConstPointer;
+    typedef typename MaskImageType::Pointer      MaskImagePointer;
+    typedef typename MaskImageType::RegionType   MaskImageRegionType; 
+    typedef typename MaskImageType::PixelType    MaskImagePixelType; 
+    typedef typename MaskImageType::SizeType     MaskImageSizeType; 
+    typedef typename MaskImageType::IndexType    MaskImageIndexType; 
 
     itkStaticConstMacro(ImageDimension, unsigned int, InputImageType::ImageDimension);
     typedef int InternalPixelType;
@@ -88,12 +91,17 @@ namespace clitk {
       void SetArgsInfo(ArgsInfoType arg);
 
     // Background / Foreground
-    itkGetConstMacro(BackgroundValue, OutputImagePixelType);
-    itkGetConstMacro(ForegroundValue, OutputImagePixelType);
+    itkGetConstMacro(BackgroundValue, MaskImagePixelType);
+    itkGetConstMacro(ForegroundValue, MaskImagePixelType);
 
     itkSetMacro(MinimalComponentSize, int);
     itkGetConstMacro(MinimalComponentSize, int);
     GGO_DefineOption(minSize, SetMinimalComponentSize, int);
+    
+    // Output filename  (for AFBD)
+    itkSetMacro(OutputBonesFilename, std::string);
+    itkGetMacro(OutputBonesFilename, std::string);
+    GGO_DefineOption(output, SetOutputBonesFilename, std::string);
 
     // Step 0
     itkBooleanMacro(InitialSmoothing);
@@ -153,17 +161,17 @@ namespace clitk {
     itkSetMacro(AutoCrop, bool);
     itkGetConstMacro(AutoCrop, bool);
     itkBooleanMacro(AutoCrop);
-    GGO_DefineOption_Flag(autoCrop, SetAutoCrop);
+    GGO_DefineOption_Flag(noAutoCrop, SetAutoCrop);
 
   protected:
     ExtractBonesFilter();
     virtual ~ExtractBonesFilter() {}
     
     // Global options
-    itkSetMacro(BackgroundValue, OutputImagePixelType);
-    itkSetMacro(ForegroundValue, OutputImagePixelType);
-    OutputImagePixelType m_BackgroundValue;
-    OutputImagePixelType m_ForegroundValue;
+    itkSetMacro(BackgroundValue, MaskImagePixelType);
+    itkSetMacro(ForegroundValue, MaskImagePixelType);
+    MaskImagePixelType m_BackgroundValue;
+    MaskImagePixelType m_ForegroundValue;
     bool m_AutoCrop;
 
     // Step 0 : Initial Filtering
@@ -194,9 +202,10 @@ namespace clitk {
     void ExtractBones();
     void RemoveTrachea();
     void BonesSeparation();
+    std::string m_OutputBonesFilename;
     InputImageConstPointer input;
     InputImagePointer filtered_input;
-    OutputImageConstPointer patient;
+    MaskImageConstPointer patient;
     InputImagePointer working_input;
     typename InternalImageType::Pointer working_image;  
     typename InternalImageType::Pointer trachea;
index ef3f9445ad171b4970d2aa8faf4cae1d87231daf..3e8cc491c63e5c4200bca7f8d5c79f4b43229dc6 100644 (file)
 #include "itkCurvatureAnisotropicDiffusionImageFilter.h"
 
 //--------------------------------------------------------------------
-template <class TInputImageType, class TOutputImageType>
-clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+template <class TInputImageType>
+clitk::ExtractBonesFilter<TInputImageType>::
 ExtractBonesFilter():
   clitk::FilterBase(),
-  itk::ImageToImageFilter<TInputImageType, TOutputImageType>()
+  clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
+  itk::ImageToImageFilter<TInputImageType, MaskImageType>()
 {
   // Default global options
   this->SetNumberOfRequiredInputs(1);
@@ -61,15 +62,15 @@ ExtractBonesFilter():
   s.Fill(1);
   SetRadius2(s);
   SetSampleRate2(0);
-  AutoCropOff();
+  AutoCropOn();
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class TInputImageType, class TOutputImageType>
+template <class TInputImageType>
 void 
-clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+clitk::ExtractBonesFilter<TInputImageType>::
 SetInput(const TInputImageType * image) 
 {
   this->SetNthInput(0, const_cast<TInputImageType *>(image));
@@ -78,10 +79,10 @@ SetInput(const TInputImageType * image)
 
 
 //--------------------------------------------------------------------
-template <class TInputImageType, class TOutputImageType>
+template <class TInputImageType>
 template<class ArgsInfoType>
 void 
-clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+clitk::ExtractBonesFilter<TInputImageType>::
 SetArgsInfo(ArgsInfoType mArgsInfo)
 {
   SetVerboseOption_GGO(mArgsInfo);
@@ -89,6 +90,8 @@ SetArgsInfo(ArgsInfoType mArgsInfo)
   SetWriteStep_GGO(mArgsInfo);
   SetVerboseWarningOff_GGO(mArgsInfo);
   
+  SetOutputBonesFilename_GGO(mArgsInfo);
+
   SetInitialSmoothing_GGO(mArgsInfo);
   SetSmoothingConductanceParameter_GGO(mArgsInfo);
   SetSmoothingNumberOfIterations_GGO(mArgsInfo);
@@ -105,30 +108,35 @@ SetArgsInfo(ArgsInfoType mArgsInfo)
   SetRadius2_GGO(mArgsInfo);
   SetSampleRate2_GGO(mArgsInfo);
   SetAutoCrop_GGO(mArgsInfo);
+
+  SetAFDBFilename_GGO(mArgsInfo);
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class TInputImageType, class TOutputImageType>
+template <class TInputImageType>
 void 
-clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+clitk::ExtractBonesFilter<TInputImageType>::
 GenerateOutputInformation() { 
+
   // Get input pointers
   InputImagePointer input   = dynamic_cast<TInputImageType*>(itk::ProcessObject::GetInput(0));
-  //  InputImagePointer input = dynamic_cast<TInputImageType*>(itk::ProcessObject::GetInput(0));
   Superclass::GenerateOutputInformation();
-  OutputImagePointer outputImage = this->GetOutput(0);
+  MaskImagePointer outputImage = this->GetOutput(0);
   outputImage->SetRegions(input->GetLargestPossibleRegion());
 
+  // Read DB
+  LoadAFDB();
+
   // typedefs
   typedef itk::BinaryThresholdImageFilter<InputImageType, InternalImageType> InputBinarizeFilterType;
   typedef itk::BinaryThresholdImageFilter<InternalImageType, InternalImageType> BinarizeFilterType;
   typedef itk::ConnectedComponentImageFilter<InternalImageType, InternalImageType> ConnectFilterType;
   typedef itk::RelabelComponentImageFilter<InternalImageType, InternalImageType> RelabelFilterType;
   typedef clitk::SetBackgroundImageFilter<InternalImageType,InternalImageType, InternalImageType> SetBackgroundFilterType; 
-  typedef itk::CastImageFilter<InternalImageType,OutputImageType> CastImageFilterType; 
-  typedef itk::ImageFileWriter<OutputImageType> WriterType; 
+  typedef itk::CastImageFilter<InternalImageType,MaskImageType> CastImageFilterType; 
+  typedef itk::ImageFileWriter<MaskImageType> WriterType; 
 
   //---------------------------------
   // Smoothing [Optional]
@@ -274,20 +282,23 @@ GenerateOutputInformation() {
 
 
 //--------------------------------------------------------------------
-template <class TInputImageType, class TOutputImageType>
+template <class TInputImageType>
 void 
-clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+clitk::ExtractBonesFilter<TInputImageType>::
 GenerateData() {
 
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
   // Final Cast 
-  typedef itk::CastImageFilter<InternalImageType, OutputImageType> CastImageFilterType;
+  typedef itk::CastImageFilter<InternalImageType, MaskImageType> CastImageFilterType;
   typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
   caster->SetInput(output);
   caster->Update();
-  //this->SetNthOutput(0, caster->GetOutput());
   this->GraftOutput(caster->GetOutput());
+
+  // Store image filenames into AFDB 
+  GetAFDB()->SetImageFilename("bones", this->GetOutputBonesFilename());  
+  WriteAFDB();
   return;
 }
 //--------------------------------------------------------------------
index dd8563474dcce185f9e7623c81fe34a9389e22b0..285842e5c0d5672aac8f981a9f84dc0aa1005d0f 100644 (file)
@@ -66,13 +66,13 @@ template<class ImageType>
 void clitk::ExtractBonesGenericFilter<ArgsInfoType>::UpdateWithInputImageType() 
 { 
   // Mask & output image type
-  typedef itk::Image<uchar, ImageType::ImageDimension> OutputImageType;
+  typedef itk::Image<uchar, ImageType::ImageDimension> MaskImageType;
 
   // Reading input
   typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
 
   // Create filter
-  typedef clitk::ExtractBonesFilter<ImageType, OutputImageType> FilterType;
+  typedef clitk::ExtractBonesFilter<ImageType> FilterType;
   typename FilterType::Pointer filter = FilterType::New();
     
   // Set global Options 
@@ -83,8 +83,8 @@ void clitk::ExtractBonesGenericFilter<ArgsInfoType>::UpdateWithInputImageType()
   filter->Update();
   
   // Write/Save results
-  typename OutputImageType::Pointer output = filter->GetOutput();
-  this->template SetNextOutput<OutputImageType>(output); 
+  typename MaskImageType::Pointer output = filter->GetOutput();
+  this->template SetNextOutput<MaskImageType>(output); 
 }
 //--------------------------------------------------------------------
 
index 37eada2dd12a346073b2ac297734c6d25443358c..ddc1fe71bb1c9a1b33b5c3cfa26651193bf837b0 100644 (file)
@@ -14,8 +14,7 @@ option "verboseWarningOff" -  "Do not display warning"    flag          off
 section "I/O"
 
 option "input"         i       "Input CT image filename"         string        yes
-option "patient"       p       "Input patient mask filename"     string        yes
-option "patientBG"     -       "Patient Background"              int           default="0" no
+option "afdb"          a       "Output Anatomical Feature DB (Carina position)"  string  no
 option "output"        o       "Output lungs mask filename"      string        yes
 option "outputTrachea" t       "Output trachea mask filename"    string        no
 
@@ -50,6 +49,11 @@ option "remove3"     -       "Labels not to keep in lungs mask (trachea)"    int             no
 option "firstKeep3"  - "First label to keep"                     int           no      default="1"
 option "lastKeep3"   - "Last label to keep"                      int           no      default="2"
 
-section "Step 5 : openclose"
-option "openclose"             -  "Final OpenClose"            flag off
-option "opencloseRadius"       -  "Final OpenClose radius"     int no default="1"
+section "Step 5 : [optional] openclose"
+option "openclose"             -  "Perform an OpenClose operation"             flag off
+option "opencloseRadius"       -  "OpenClose radius"                           int no default="1"
+
+section "Step 6 : fill holes"
+option "doNotFillHoles"                -  "Do not fill holes if set"                 flag on
+option "dir"                   d  "Directions (axes) to perform filling (defaults to 2,1,0)"   int multiple no
+
index 6ec698d3a204bc98dddd17190dafa44ba8e83209..3183457dde0a6eb7ff06d445670cb132523a2ae8 100644 (file)
@@ -24,6 +24,7 @@
 #include "clitkDecomposeAndReconstructImageFilter.h"
 #include "clitkExplosionControlledThresholdConnectedImageFilter.h"
 #include "clitkSegmentationUtils.h"
+#include "clitkFilterWithAnatomicalFeatureDatabaseManagement.h"
 
 // itk
 #include "itkStatisticsImageFilter.h"
@@ -55,15 +56,17 @@ namespace clitk {
   //--------------------------------------------------------------------
   
   //--------------------------------------------------------------------
-  template <class TImageType, class TMaskImageType>
+  template <class TImageType>
   class ITK_EXPORT ExtractLungFilter: 
     public virtual clitk::FilterBase, 
-    public itk::ImageToImageFilter<TImageType, TMaskImageType> 
+    public clitk::FilterWithAnatomicalFeatureDatabaseManagement,
+    public itk::ImageToImageFilter<TImageType, itk::Image<uchar, TImageType::ImageDimension> > 
   {
     
   public:
     /** Standard class typedefs. */
-    typedef itk::ImageToImageFilter<TImageType, TMaskImageType> Superclass;
+    typedef itk::Image<uchar, TImageType::ImageDimension> MaskImageType;
+    typedef itk::ImageToImageFilter<TImageType, MaskImageType> Superclass;
     typedef ExtractLungFilter              Self;
     typedef itk::SmartPointer<Self>        Pointer;
     typedef itk::SmartPointer<const Self>  ConstPointer;
@@ -85,7 +88,6 @@ namespace clitk {
     typedef typename ImageType::IndexType    InputImageIndexType; 
     typedef typename ImageType::PointType    InputImagePointType; 
         
-    typedef TMaskImageType                       MaskImageType;
     typedef typename MaskImageType::ConstPointer MaskImageConstPointer;
     typedef typename MaskImageType::Pointer      MaskImagePointer;
     typedef typename MaskImageType::RegionType   MaskImageRegionType; 
@@ -103,11 +105,19 @@ namespace clitk {
     
     /** Connect inputs */
     void SetInput(const ImageType * image);
-    void SetInputPatientMask(MaskImageType * mask, MaskImagePixelType BG);
     itkSetMacro(PatientMaskBackgroundValue, MaskImagePixelType);
     itkGetConstMacro(PatientMaskBackgroundValue, MaskImagePixelType);
     GGO_DefineOption(patientBG, SetPatientMaskBackgroundValue, MaskImagePixelType);
 
+    // Output filename  (for AFBD)
+    itkSetMacro(OutputLungFilename, std::string);
+    itkGetMacro(OutputLungFilename, std::string);
+    GGO_DefineOption(output, SetOutputLungFilename, std::string);
+
+    itkSetMacro(OutputTracheaFilename, std::string);
+    itkGetMacro(OutputTracheaFilename, std::string);
+    GGO_DefineOption(outputTrachea, SetOutputTracheaFilename, std::string);
+
     // Set all options at a time
     template<class ArgsInfoType>
       void SetArgsInfo(ArgsInfoType arg);
@@ -180,14 +190,20 @@ namespace clitk {
     GGO_DefineOption_LabelParam(3, SetLabelizeParameters3, LabelParamType);
 
     // Step 5 final openclose
-    itkSetMacro(FinalOpenClose, bool);
-    itkGetConstMacro(FinalOpenClose, bool);
-    itkBooleanMacro(FinalOpenClose);
-    GGO_DefineOption_Flag(openclose, SetFinalOpenClose);
-
-    itkSetMacro(FinalOpenCloseRadius, int);
-    itkGetConstMacro(FinalOpenCloseRadius, int);
-    GGO_DefineOption(opencloseRadius, SetFinalOpenCloseRadius, int);
+    itkSetMacro(OpenClose, bool);
+    itkGetConstMacro(OpenClose, bool);
+    itkBooleanMacro(OpenClose);
+    GGO_DefineOption_Flag(openclose, SetOpenClose);
+
+    itkSetMacro(OpenCloseRadius, int);
+    itkGetConstMacro(OpenCloseRadius, int);
+    GGO_DefineOption(opencloseRadius, SetOpenCloseRadius, int);
+    
+    // Step 6 fill holes
+    itkSetMacro(FillHoles, bool);
+    itkGetConstMacro(FillHoles, bool);
+    itkBooleanMacro(FillHoles);
+    GGO_DefineOption_Flag(doNotFillHoles, SetFillHoles);
 
   protected:
     ExtractLungFilter();
@@ -197,6 +213,8 @@ namespace clitk {
     InputImageConstPointer input;
     MaskImageConstPointer patient;
     InputImagePointer working_input;
+    std::string m_OutputLungFilename;
+    std::string m_OutputTracheaFilename;
     typename InternalImageType::Pointer working_image;  
     typename InternalImageType::Pointer trachea_tmp;
     MaskImagePointer trachea;
@@ -233,8 +251,12 @@ namespace clitk {
     LabelParamType* m_LabelizeParameters3;
 
     // Step 5
-    bool m_FinalOpenClose;    
-    int m_FinalOpenCloseRadius;
+    bool m_OpenClose;    
+    int m_OpenCloseRadius;
+
+    // Step 6
+    bool m_FillHoles;    
+    InputImageSizeType m_FillHolesDirections;
 
     // Main functions
     virtual void GenerateOutputInformation();
index 3de027cc3b8210d0dbbac0e5d2a24d1a4aa02cfa..2147b881681934dfd48ae0242c47d0b14c811969 100644 (file)
@@ -24,6 +24,8 @@
 #include "clitkSetBackgroundImageFilter.h"
 #include "clitkSegmentationUtils.h"
 #include "clitkAutoCropFilter.h"
+#include "clitkCropLikeImageFilter.h"
+#include "clitkFillMaskFilter.h"
 
 // itk
 #include "itkBinaryThresholdImageFilter.h"
 #include "itkBinaryMorphologicalClosingImageFilter.h"
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+template <class ImageType>
+clitk::ExtractLungFilter<ImageType>::
 ExtractLungFilter():
   clitk::FilterBase(),
+  clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
   itk::ImageToImageFilter<ImageType, MaskImageType>()
 {
   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 <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));
@@ -103,21 +109,9 @@ SetInput(const ImageType * image)
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
-void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
-SetInputPatientMask(MaskImageType * image, MaskImagePixelType bg ) 
-{
-  this->SetNthInput(1, const_cast<MaskImageType *>(image));
-  SetPatientMaskBackgroundValue(bg);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 AddSeed(InternalIndexType s) 
 { 
   m_Seeds.push_back(s);
@@ -126,10 +120,10 @@ AddSeed(InternalIndexType s)
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 template<class ArgsInfoType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 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,46 @@ 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 <class ImageType, class MaskImageType>
+template <class ImageType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 GenerateOutputInformation() 
 { 
   Superclass::GenerateOutputInformation();
+  
+  // 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");  
 
-  // Check image
-  if (!HaveSameSizeAndSpacing<ImageType, MaskImageType>(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<ImageType> CropImageFilter;
+  typename CropImageFilter::Pointer cropFilter = CropImageFilter::New();
+  cropFilter->SetInput(input);
+  cropFilter->SetCropLikeImage(patient);
+  cropFilter->Update();
+  working_input = cropFilter->GetOutput();
+  StopCurrentStep<ImageType>(working_input);
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
   StartNewStep("Set background to initial image");
   working_input = SetBackground<ImageType, MaskImageType>
-    (input, patient, GetPatientMaskBackgroundValue(), -1000);
+    (working_input, patient, GetPatientMaskBackgroundValue(), -1000);
   StopCurrentStep<ImageType>(working_input);
 
   //--------------------------------------------------------------------
@@ -313,15 +323,15 @@ GenerateOutputInformation()
 
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
-  typedef clitk::AutoCropFilter<InternalImageType> CropFilterType;
-  typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+  typedef clitk::AutoCropFilter<InternalImageType> 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<InternalImageType, MaskImageType> CastImageFilterType;
     typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
-    caster->SetInput(cropFilter->GetOutput());
+    caster->SetInput(autocropFilter->GetOutput());
     caster->Update();   
     trachea = caster->GetOutput();
     StopCurrentStep<MaskImageType>(trachea);  
@@ -329,23 +339,23 @@ 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();
   StopCurrentStep<InternalImageType>(working_image);
 
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
   // Final OpenClose
-  if (GetFinalOpenClose()) {
+  if (GetOpenClose()) {
     StartNewStep("Open/Close"); 
 
     // Structuring element
     typedef itk::BinaryBallStructuringElement<InternalPixelType, ImageDimension> KernelType;
     KernelType structuringElement;
-    structuringElement.SetRadius(GetFinalOpenCloseRadius());
+    structuringElement.SetRadius(GetOpenCloseRadius());
     structuringElement.CreateStructuringElement();
        
     // Open
@@ -367,6 +377,20 @@ GenerateOutputInformation()
     working_image = closeFilter->GetOutput();
   }
 
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // Fill Lungs
+  if (GetFillHoles()) {
+    StartNewStep("Fill Holes");
+    /*
+    typename FillMaskFilterType::Pointer fillMaskFilter = FillMaskFilterType::New();
+    fillMaskFilter(working_image);
+    fillMaskFilter->Update();   
+    working_image = fillMaskFilter->GetOutput();
+    StopCurrentStep<InternalImageType>(working_image);
+    */
+  }
+
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
   StartNewStep("Separate Left/Right lungs");
@@ -426,28 +450,30 @@ GenerateOutputInformation()
 
   // Update output info
   this->GetOutput(0)->SetRegions(output->GetLargestPossibleRegion());
-
-
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 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 <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)    
@@ -495,9 +521,9 @@ SearchForTracheaSeed(int skip)
 
   
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 TracheaRegionGrowing()
 {
   // Explosion controlled region growing
@@ -536,9 +562,9 @@ TracheaRegionGrowing()
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 double 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 ComputeTracheaVolume()
 {
   typedef itk::ImageRegionConstIterator<InternalImageType> IteratorType;
@@ -557,9 +583,9 @@ ComputeTracheaVolume()
 
 
 //--------------------------------------------------------------------
-template <class ImageType, class MaskImageType>
+template <class ImageType>
 void 
-clitk::ExtractLungFilter<ImageType, MaskImageType>::
+clitk::ExtractLungFilter<ImageType>::
 SearchForTrachea()
 {
   // Search for seed among n slices, skip some slices before starting
index 7d6306b5b20d233991810b7a4a0b0a9e1e703271..bc7b581c0188236873918aceace7b530086d3036 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef CLITKEXTRACTLUNGSGENERICFILTER_H
 #define CLITKEXTRACTLUNGSGENERICFILTER_H
 
+// clitk
 #include "clitkIO.h"
 #include "clitkImageToImageGenericFilter.h"
 #include "clitkExtractLungFilter.h"
@@ -26,7 +27,6 @@
 //--------------------------------------------------------------------
 namespace clitk 
 {
-  
   template<class ArgsInfoType>
   class ITK_EXPORT ExtractLungGenericFilter: 
     public ImageToImageGenericFilter<ExtractLungGenericFilter<ArgsInfoType> >
index 74317ed55f03f360edc78ccfb9516bdc77835454..64e7fb85f36513f3aa75febcddfc2a965bb2098f 100644 (file)
@@ -54,7 +54,6 @@ void clitk::ExtractLungGenericFilter<ArgsInfoType>::SetArgsInfo(const ArgsInfoTy
   SetIOVerbose(mArgsInfo.verbose_flag);
   if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
   if (mArgsInfo.input_given)   AddInputFilename(mArgsInfo.input_arg);
-  if (mArgsInfo.patient_given) AddInputFilename(mArgsInfo.patient_arg);
   if (mArgsInfo.output_given)  AddOutputFilename(mArgsInfo.output_arg);
   if (mArgsInfo.outputTrachea_given)  AddOutputFilename(mArgsInfo.outputTrachea_arg);
 }
@@ -69,15 +68,13 @@ template<class ImageType>
 void clitk::ExtractLungGenericFilter<ArgsInfoType>::UpdateWithInputImageType() 
 { 
   // Mask & output image type
-  typedef itk::Image<uchar, ImageType::ImageDimension> OutputImageType;
   typedef itk::Image<uchar, ImageType::ImageDimension> MaskImageType;
 
   // Reading input
   typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
-  typename MaskImageType::Pointer patient = this->template GetInput<MaskImageType>(1);
 
   // Create filter
-  typedef clitk::ExtractLungFilter<ImageType, MaskImageType> FilterType;
+  typedef clitk::ExtractLungFilter<ImageType> FilterType;
   typename FilterType::Pointer filter = FilterType::New();
 
   // Set the filter (needed for example for threaded monitoring)
@@ -86,14 +83,13 @@ void clitk::ExtractLungGenericFilter<ArgsInfoType>::UpdateWithInputImageType()
   // Set global Options 
   filter->SetArgsInfo(mArgsInfo);
   filter->SetInput(input);
-  filter->SetInputPatientMask(patient, mArgsInfo.patientBG_arg);
 
   // Go !
   filter->Update();
   
   // Write/Save results
-  typename OutputImageType::Pointer output = filter->GetOutput();
-  this->template SetNextOutput<OutputImageType>(output); 
+  typename MaskImageType::Pointer output = filter->GetOutput();
+  this->template SetNextOutput<MaskImageType>(output); 
   this->template SetNextOutput<typename FilterType::MaskImageType>(filter->GetTracheaImage()); 
 }
 //--------------------------------------------------------------------
index 7f5ca18aec5fccdf23411fd5ae39bc06612b6a87..b76e617946593c7faaca4924beb61f6d7a43e796 100644 (file)
@@ -25,6 +25,7 @@
 #include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
 #include "clitkSegmentationUtils.h"
 #include "clitkExtractAirwaysTreeInfoFilter.h"
+#include "clitkCropLikeImageFilter.h"
 
 // std
 #include <deque>
@@ -138,6 +139,8 @@ SetArgsInfo(ArgsInfoType mArgsInfo)
   SetFuzzyThreshold1_GGO(mArgsInfo);
   SetFuzzyThreshold2_GGO(mArgsInfo);
   SetFuzzyThreshold3_GGO(mArgsInfo);
+
+  SetAFDBFilename_GGO(mArgsInfo);
 }
 //--------------------------------------------------------------------
 
@@ -162,11 +165,13 @@ GenerateInputRequestedRegion()
 {
   // Call default
   Superclass::GenerateInputRequestedRegion();  
-  // Get input pointers
-  ImagePointer patient = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
-  ImagePointer lung    = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
-  ImagePointer bones   = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(2));
-  ImagePointer trachea = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(3));
+
+  // Get input pointers  
+  LoadAFDB();
+  ImagePointer patient = GetAFDB()->template GetImage <ImageType>("patient");  
+  ImagePointer lung = GetAFDB()->template GetImage <ImageType>("lungs");  
+  ImagePointer bones = GetAFDB()->template GetImage <ImageType>("bones");  
+  ImagePointer trachea = GetAFDB()->template GetImage <ImageType>("trachea");  
     
   patient->SetRequestedRegion(patient->GetLargestPossibleRegion());
   lung->SetRequestedRegion(lung->GetLargestPossibleRegion());
@@ -183,20 +188,39 @@ clitk::ExtractMediastinumFilter<ImageType>::
 GenerateData() 
 {
   // Get input pointers
-  ImageConstPointer patient = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
-  ImageConstPointer lung    = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(1));
-  ImageConstPointer bones   = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(2));
-  ImageConstPointer trachea = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(3));
+  ImagePointer patient = GetAFDB()->template GetImage <ImageType>("patient");  
+  ImagePointer lung = GetAFDB()->template GetImage <ImageType>("lungs");  
+  ImagePointer bones = GetAFDB()->template GetImage <ImageType>("bones");  
+  ImagePointer trachea = GetAFDB()->template GetImage <ImageType>("trachea");  
     
   // Get output pointer
   ImagePointer output;
 
+  // Step 0: Crop support (patient) to lung extend in RL
+  StartNewStep("Crop support like lungs along LR");
+  typedef clitk::CropLikeImageFilter<ImageType> CropFilterType;
+  typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+  cropFilter->SetInput(patient);
+  cropFilter->SetCropLikeImage(lung, 0);// Indicate that we only crop in X (Left-Right) axe
+  cropFilter->Update();
+  output = cropFilter->GetOutput();
+  this->template StopCurrentStep<ImageType>(output);
+
+  // Step 0: Crop support (previous) to bones extend in AP
+  StartNewStep("Crop support like bones along AP");
+  cropFilter = CropFilterType::New();
+  cropFilter->SetInput(output);
+  cropFilter->SetCropLikeImage(bones, 1);// Indicate that we only crop in Y (Ant-Post) axe
+  cropFilter->Update();
+  output = cropFilter->GetOutput();
+  this->template StopCurrentStep<ImageType>(output);
+
   // Step 1: patient minus lungs, minus bones
   StartNewStep("Patient contours minus lungs and minus bones");
   typedef clitk::BooleanOperatorLabelImageFilter<ImageType> BoolFilterType;
   typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); 
   boolFilter->InPlaceOn();
-  boolFilter->SetInput1(patient);
+  boolFilter->SetInput1(output);
   boolFilter->SetInput2(lung);    
   boolFilter->SetOperationType(BoolFilterType::AndNot);
   boolFilter->Update();    
@@ -213,13 +237,14 @@ GenerateData()
   // Step 2: LR limits from lung (need separate lung ?)
   StartNewStep("Left/Right limits with lungs");
 
-  /* // WE DO NOT NEED THE FOLLOWING
-     // Get separate lung images to get only the right and left lung
-     // (label must be '1' because right is greater than left).
-     ImagePointer right_lung = clitk::SetBackground<ImageType, ImageType>(lung, lung, 2, 0);
-     ImagePointer left_lung = clitk::SetBackground<ImageType, ImageType>(lung, lung, 1, 0);
-     writeImage<ImageType>(right_lung, "right.mhd");
-     writeImage<ImageType>(left_lung, "left.mhd");
+  /*
+  // WE DO NOT NEED THE FOLLOWING ?
+  // Get separate lung images to get only the right and left lung (because RelativePositionPropImageFilter only consider fg=1);
+  // (label must be '1' because right is greater than left).
+  ImagePointer right_lung = clitk::SetBackground<ImageType, ImageType>(lung, lung, 2, 0);
+  ImagePointer left_lung = clitk::SetBackground<ImageType, ImageType>(lung, lung, 1, 0);
+  writeImage<ImageType>(right_lung, "right.mhd");
+  writeImage<ImageType>(left_lung, "left.mhd");
   */
 
   typedef clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType> RelPosFilterType;
@@ -228,28 +253,26 @@ GenerateData()
   relPosFilter->VerboseStepOff();
   relPosFilter->WriteStepOff();
   relPosFilter->SetInput(output); 
-  DD(output->GetLargestPossibleRegion().GetIndex());
-  //  relPosFilter->SetInputObject(left_lung); 
+  //relPosFilter->SetInputObject(left_lung); 
   relPosFilter->SetInputObject(lung); 
   relPosFilter->SetOrientationType(RelPosFilterType::LeftTo); // warning left lung is at right ;)
   relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
   relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
   relPosFilter->Update();
   output = relPosFilter->GetOutput();
-  DD(output->GetLargestPossibleRegion());
+  // writeImage<ImageType>(right_lung, "step4-left.mhd");
 
   relPosFilter->SetInput(output); 
   relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
   relPosFilter->VerboseStepOff();
   relPosFilter->WriteStepOff();
-  //  relPosFilter->SetInputObject(right_lung);
+  //relPosFilter->SetInputObject(right_lung);
   relPosFilter->SetInputObject(lung); 
   relPosFilter->SetOrientationType(RelPosFilterType::RightTo);
   relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
   relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
   relPosFilter->Update();   
   output = relPosFilter->GetOutput();
-  DD(output->GetLargestPossibleRegion());
   this->template StopCurrentStep<ImageType>(output);
 
   // Step 3: AP limits from bones
@@ -268,37 +291,37 @@ GenerateData()
   DD(index_trachea);
   
   // Split bone image first into two parts (ant and post)
-  typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> CropFilterType;
-  //  typedef itk::ExtractImageFilter<ImageType, ImageType> CropFilterType;
-  typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+  typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> ROIFilterType;
+  //  typedef itk::ExtractImageFilter<ImageType, ImageType> ROIFilterType;
+  typename ROIFilterType::Pointer roiFilter = ROIFilterType::New();
   ImageRegionType region = bones->GetLargestPossibleRegion();
   ImageSizeType size = region.GetSize();
   DD(size);
   size[1] =  index_trachea[1]; //size[1]/2.0;
   DD(size);
   region.SetSize(size);
-  cropFilter->SetInput(bones);
-  //  cropFilter->SetExtractionRegion(region);
-  cropFilter->SetRegionOfInterest(region);
-  cropFilter->ReleaseDataFlagOff();
-  cropFilter->Update();
-  bones_ant = cropFilter->GetOutput();
+  roiFilter->SetInput(bones);
+  //  roiFilter->SetExtractionRegion(region);
+  roiFilter->SetRegionOfInterest(region);
+  roiFilter->ReleaseDataFlagOff();
+  roiFilter->Update();
+  bones_ant = roiFilter->GetOutput();
   writeImage<ImageType>(bones_ant, "b_ant.mhd");
   
-  //  cropFilter->ResetPipeline();// = CropFilterType::New();  
-  cropFilter = CropFilterType::New();  
+  //  roiFilter->ResetPipeline();// = ROIFilterType::New();  
+  roiFilter = ROIFilterType::New();  
   ImageIndexType index = region.GetIndex();
   index[1] = bones->GetLargestPossibleRegion().GetIndex()[1] + size[1]-1;
   size[1] =  bones->GetLargestPossibleRegion().GetSize()[1] - size[1];
   DD(size);
   region.SetIndex(index);
   region.SetSize(size);
-  cropFilter->SetInput(bones);
-  //  cropFilter->SetExtractionRegion(region);
-  cropFilter->SetRegionOfInterest(region);
-  cropFilter->ReleaseDataFlagOff();
-  cropFilter->Update();
-  bones_post = cropFilter->GetOutput();
+  roiFilter->SetInput(bones);
+  //  roiFilter->SetExtractionRegion(region);
+  roiFilter->SetRegionOfInterest(region);
+  roiFilter->ReleaseDataFlagOff();
+  roiFilter->Update();
+  bones_post = roiFilter->GetOutput();
   writeImage<ImageType>(bones_post, "b_post.mhd");
 
   // Go ! 
@@ -328,12 +351,14 @@ GenerateData()
   relPosFilter->Update();   
   output = relPosFilter->GetOutput();
   this->template StopCurrentStep<ImageType>(output);
+
   // Get CCL
-  output = clitk::Labelize<ImageType>(output, GetBackgroundValue(), true, 100);
+  StartNewStep("Keep main connected component");
+  output = clitk::Labelize<ImageType>(output, GetBackgroundValue(), true, 500);
   // output = RemoveLabels<ImageType>(output, BG, param->GetLabelsToRemove());
   output = clitk::KeepLabels<ImageType>(output, GetBackgroundValue(), 
                                         GetForegroundValue(), 1, 1, 0);
-
+  this->template StopCurrentStep<ImageType>(output);
 
   // Step : Lower limits from lung (need separate lung ?)
   StartNewStep("Lower limits with lungs");
@@ -353,10 +378,10 @@ GenerateData()
   DD(output->GetLargestPossibleRegion());
 
   output = clitk::AutoCrop<ImageType>(output, GetBackgroundValue()); 
-  //  cropFilter = CropFilterType::New();
-  //cropFilter->SetInput(output);
-  //cropFilter->Update();   
-  //output = cropFilter->GetOutput();
+  //  roiFilter = ROIFilterType::New();
+  //roiFilter->SetInput(output);
+  //roiFilter->Update();   
+  //output = roiFilter->GetOutput();
 
   // Final Step -> set output
   this->SetNthOutput(0, output);
index 3a239e7df6a7f4a14a827cb8669be86832718ef2..6b15a6af14e7e167e2687bea3556f124a52b4906 100644 (file)
@@ -1,7 +1,7 @@
 #File clitkExtractPatient.ggo
 package "clitkExtractPatient"
 version "1.0"
-purpose "Prefer high resolution input and resample (NN) output at the end (like). Input is binarized using initial thresholds, connected components are labeled (firstLabel). The air label (1) is removed. The remaining is binarized and relabeled, patient should now be the principal label (secondLabel). Two mechanismes are provided to influence the label images. Crop to reduce connectivity (image is restored to original size), eg for SBF. Decomposition through ersion and reconstruction through dilation (slow), eg for Pulmo bellows. Choose which labels to keep from second Label image. Final mask is cleaned by opening and closing."
+purpose "Input is binarized using initial thresholds, connected components are labeled (firstLabel). The air label (1) is removed. The remaining is binarized and relabeled, patient should now be the principal label (secondLabel). Two mechanismes are provided to influence the label images. Crop to reduce connectivity (image is restored to original size), eg for SBF. Decomposition through ersion and reconstruction through dilation (slow), eg for Pulmo bellows. Choose which labels to keep from second Label image. Final mask is cleaned by opening and closing."
 
 option "config"                -  "Config file"                  string        no
 option "imagetypes"     -  "Display allowed image types"  flag          off
@@ -13,8 +13,9 @@ option "verboseWarningOff" -  "Do not display warning"    flag          off
 
 section "I/O"
 
-option "input"         i       "Input image filename"            string        yes
-option "output"        o       "Output image filename"           string        yes
+option "input"   i     "Input image filename"               string  yes
+option "afdb"    a     "Output Anatomical Feature in a DB"  string  no
+option "output"  o     "Output image filename"              string  yes
 
 section "Binarize"
 
@@ -47,7 +48,7 @@ option  "remove"      -               "Labels to remove"                      int     no      multiple
 
 section "Clean-up"
 
-option "openClose"     -       "Perform morphological opening and closing with unit radius"    flag    on
-option "autoCrop"      -       "Crop final mask to BoundingBox"                                flag    off
+option "openClose"     -       "Perform morphological opening and closing with unit radius"    flag    off
+option "noAutoCrop"    -       "If set : do no crop final mask to BoundingBox"                         flag    on
 
 
index 9346d9a9c01a4eeadcb635c8511c54e0c1b5129c..b4717477dee9aa52c033701fc78e188e89c7538e 100644 (file)
@@ -20,6 +20,7 @@
 #define CLITKEXTRACTPATIENTFILTER_H
 
 #include "clitkFilterBase.h"
+#include "clitkFilterWithAnatomicalFeatureDatabaseManagement.h"
 
 namespace clitk {
   
@@ -42,17 +43,20 @@ namespace clitk {
   */
   //--------------------------------------------------------------------
   
-  template <class TInputImageType, class TOutputImageType>
+  template <class TInputImageType>
   class ITK_EXPORT ExtractPatientFilter: 
-    public clitk::FilterBase, 
-    public itk::ImageToImageFilter<TInputImageType, TOutputImageType> 
+    public virtual clitk::FilterBase, 
+    public clitk::FilterWithAnatomicalFeatureDatabaseManagement,
+    public itk::ImageToImageFilter<TInputImageType, 
+                                   itk::Image<uchar, TInputImageType::ImageDimension> > 
   {
   public:
     /** Standard class typedefs. */
-    typedef ExtractPatientFilter            Self;
-    typedef itk::ImageToImageFilter<TInputImageType, TOutputImageType> Superclass;
-    typedef itk::SmartPointer<Self>         Pointer;
-    typedef itk::SmartPointer<const Self>   ConstPointer;
+    typedef itk::Image<uchar, TInputImageType::ImageDimension>      MaskImageType;
+    typedef ExtractPatientFilter                                    Self;
+    typedef itk::ImageToImageFilter<TInputImageType, MaskImageType> Superclass;
+    typedef itk::SmartPointer<Self>                                 Pointer;
+    typedef itk::SmartPointer<const Self>                           ConstPointer;
     
     /** Method for creation through the object factory. */
     itkNewMacro(Self);
@@ -70,13 +74,12 @@ namespace clitk {
     typedef typename InputImageType::SizeType     InputImageSizeType; 
     typedef typename InputImageType::IndexType    InputImageIndexType; 
         
-    typedef TOutputImageType                       OutputImageType;
-    typedef typename OutputImageType::ConstPointer OutputImageConstPointer;
-    typedef typename OutputImageType::Pointer      OutputImagePointer;
-    typedef typename OutputImageType::RegionType   OutputImageRegionType; 
-    typedef typename OutputImageType::PixelType    OutputImagePixelType; 
-    typedef typename OutputImageType::SizeType     OutputImageSizeType; 
-    typedef typename OutputImageType::IndexType    OutputImageIndexType; 
+    typedef typename MaskImageType::ConstPointer MaskImageConstPointer;
+    typedef typename MaskImageType::Pointer      MaskImagePointer;
+    typedef typename MaskImageType::RegionType   MaskImageRegionType; 
+    typedef typename MaskImageType::PixelType    MaskImagePixelType; 
+    typedef typename MaskImageType::SizeType     MaskImageSizeType; 
+    typedef typename MaskImageType::IndexType    MaskImageIndexType; 
 
     itkStaticConstMacro(ImageDimension, unsigned int, InputImageType::ImageDimension);
     typedef int InternalPixelType;
@@ -85,6 +88,9 @@ namespace clitk {
     
     /** Connect inputs */
     void SetInput(const TInputImageType * image);
+    itkSetMacro(OutputPatientFilename, std::string);
+    itkGetMacro(OutputPatientFilename, std::string);
+    GGO_DefineOption(output, SetOutputPatientFilename, std::string);
 
     // Set all options at a time
     template<class ArgsInfoType>
@@ -157,19 +163,20 @@ namespace clitk {
     itkSetMacro(AutoCrop, bool);
     itkGetConstMacro(AutoCrop, bool);
     itkBooleanMacro(AutoCrop);
-    GGO_DefineOption_Flag(autoCrop, SetAutoCrop);
+    GGO_DefineOption_Flag(noAutoCrop, SetAutoCrop);
 
   protected:
     ExtractPatientFilter();
     virtual ~ExtractPatientFilter() {}
     
-    itkSetMacro(BackgroundValue, OutputImagePixelType);
-    itkSetMacro(ForegroundValue, OutputImagePixelType);
-    itkGetConstMacro(BackgroundValue, OutputImagePixelType);
-    itkGetConstMacro(ForegroundValue, OutputImagePixelType);
-    OutputImagePixelType m_BackgroundValue;
-    OutputImagePixelType m_ForegroundValue;
-
+    itkSetMacro(BackgroundValue, MaskImagePixelType);
+    itkSetMacro(ForegroundValue, MaskImagePixelType);
+    itkGetConstMacro(BackgroundValue, MaskImagePixelType);
+    itkGetConstMacro(ForegroundValue, MaskImagePixelType);
+    MaskImagePixelType m_BackgroundValue;
+    MaskImagePixelType m_ForegroundValue;
+
+    std::string m_OutputPatientFilename;
     InputImagePixelType m_UpperThreshold;
     InputImagePixelType m_LowerThreshold;
     bool m_UseLowerThreshold;
@@ -190,7 +197,7 @@ namespace clitk {
     virtual void GenerateData();
     
     InputImageConstPointer input;
-    OutputImagePointer output;
+    MaskImagePointer output;
     typename InternalImageType::Pointer working_image;
         
   private:
index e9dd6fe57bd8da7f034b7c27634c99376ebbccad..bf84ef79de31c6a8077005af82034aa005371b09 100644 (file)
 #include "itkCastImageFilter.h"
 
 //--------------------------------------------------------------------
-template <class TInputImageType, class TOutputImageType>
-clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+template <class TInputImageType>
+clitk::ExtractPatientFilter<TInputImageType>::
 ExtractPatientFilter():
   clitk::FilterBase(),
-  itk::ImageToImageFilter<TInputImageType, TOutputImageType>()
+  clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
+  itk::ImageToImageFilter<TInputImageType, MaskImageType>()
 {
   this->SetNumberOfRequiredInputs(1);
   SetBackgroundValue(0); // Must be zero
@@ -71,16 +72,16 @@ ExtractPatientFilter():
   SetLastKeep(1);
   
   // Step 4: OpenClose (option)
-  FinalOpenCloseOn();
-  AutoCropOff();
+  FinalOpenCloseOff();
+  AutoCropOn();
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class TInputImageType, class TOutputImageType>
+template <class TInputImageType>
 void 
-clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+clitk::ExtractPatientFilter<TInputImageType>::
 SetInput(const TInputImageType * image) 
 {
   this->SetNthInput(0, const_cast<TInputImageType *>(image));
@@ -89,10 +90,10 @@ SetInput(const TInputImageType * image)
 
 
 //--------------------------------------------------------------------
-template <class TInputImageType, class TOutputImageType>
+template <class TInputImageType>
 template<class ArgsInfoType>
 void 
-clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+clitk::ExtractPatientFilter<TInputImageType>::
 SetArgsInfo(ArgsInfoType arg)
 {
   SetVerboseOption_GGO(arg);
@@ -100,6 +101,8 @@ SetArgsInfo(ArgsInfoType arg)
   SetWriteStep_GGO(arg);
   SetVerboseWarningOff_GGO(arg);
 
+  SetOutputPatientFilename_GGO(arg);
+
   SetUpperThreshold_GGO(arg);
   SetLowerThreshold_GGO(arg);
 
@@ -118,20 +121,22 @@ SetArgsInfo(ArgsInfoType arg)
 
   SetFinalOpenClose_GGO(arg);
   SetAutoCrop_GGO(arg);
+
+  SetAFDBFilename_GGO(arg);
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class TInputImageType, class TOutputImageType>
+template <class TInputImageType>
 void 
-clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+clitk::ExtractPatientFilter<TInputImageType>::
 GenerateOutputInformation() { 
 
   Superclass::GenerateOutputInformation();
   input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
 
-  // OutputImagePointer outputImage = this->GetOutput(0);
+  // MaskImagePointer outputImage = this->GetOutput(0);
 //   outputImage->SetRegions(input->GetLargestPossibleRegion());
 
   // Get input pointers
@@ -209,6 +214,10 @@ GenerateOutputInformation() {
   relabelFilter2->SetInput(connectFilter2->GetOutput());
   relabelFilter2->Update();
   working_image = relabelFilter2->GetOutput();
+  
+  // Keep main label
+  working_image = KeepLabels<InternalImageType>
+    (working_image, GetBackgroundValue(), GetForegroundValue(), 1, 1, true);  
   StopCurrentStep<InternalImageType>(working_image);
 
   //--------------------------------------------------------------------
@@ -263,7 +272,7 @@ GenerateOutputInformation() {
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
   // Final Cast 
-  typedef itk::CastImageFilter<InternalImageType, OutputImageType> CastImageFilterType;
+  typedef itk::CastImageFilter<InternalImageType, MaskImageType> CastImageFilterType;
   typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
   caster->SetInput(working_image);
   caster->Update();
@@ -274,25 +283,28 @@ GenerateOutputInformation() {
   // [Optional]
   if (GetAutoCrop()) {
   StartNewStep("AutoCrop");
-    typedef clitk::AutoCropFilter<OutputImageType> CropFilterType;
+    typedef clitk::AutoCropFilter<MaskImageType> CropFilterType;
     typename CropFilterType::Pointer cropFilter = CropFilterType::New();
     cropFilter->SetInput(output);
     cropFilter->SetBackgroundValue(GetBackgroundValue());
     cropFilter->Update();   
     output = cropFilter->GetOutput();
-    StopCurrentStep<OutputImageType>(output);
+    StopCurrentStep<MaskImageType>(output);
   }
 }
 //--------------------------------------------------------------------
 
 
 //--------------------------------------------------------------------
-template <class TInputImageType, class TOutputImageType>
+template <class TInputImageType>
 void 
-clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+clitk::ExtractPatientFilter<TInputImageType>::
 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();
 }
 //--------------------------------------------------------------------
   
index 7fc07407b6c035762d5b8cc3ba0dd7a74997e720..e2b2e976e501529c85150a346f0c74523154ae26 100644 (file)
@@ -69,7 +69,7 @@ void clitk::ExtractPatientGenericFilter<ArgsInfoType>::UpdateWithInputImageType(
   typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
 
   // Create filter
-  typedef clitk::ExtractPatientFilter<ImageType, OutputImageType> FilterType;
+  typedef clitk::ExtractPatientFilter<ImageType> FilterType;
   typename FilterType::Pointer filter = FilterType::New();
     
   // Set the filter (needed for example for threaded monitoring)
@@ -81,13 +81,6 @@ void clitk::ExtractPatientGenericFilter<ArgsInfoType>::UpdateWithInputImageType(
 
   // Go !
   filter->Update();
-  
-  // // Check if error
-  // if (filter->HasError()) {
-  //   SetLastError(filter->GetLastError());
-  //   // No output
-  //   return;
-  // }
 
   // Write/Save results
   typename OutputImageType::Pointer output = filter->GetOutput();