]> Creatis software - clitk.git/commitdiff
some segmentation tools (most from jef)
authordsarrut <dsarrut>
Wed, 30 Jun 2010 06:09:06 +0000 (06:09 +0000)
committerdsarrut <dsarrut>
Wed, 30 Jun 2010 06:09:06 +0000 (06:09 +0000)
45 files changed:
segmentation/CMakeLists.txt [new file with mode: 0644]
segmentation/clitkConnectedComponentLabeling.cxx [new file with mode: 0644]
segmentation/clitkConnectedComponentLabeling.ggo [new file with mode: 0644]
segmentation/clitkConnectedComponentLabelingGenericFilter.h [new file with mode: 0644]
segmentation/clitkConnectedComponentLabelingGenericFilter.txx [new file with mode: 0644]
segmentation/clitkExtractBones.cxx [new file with mode: 0644]
segmentation/clitkExtractBones.ggo [new file with mode: 0644]
segmentation/clitkExtractBonesFilter.h [new file with mode: 0644]
segmentation/clitkExtractBonesFilter.txx [new file with mode: 0644]
segmentation/clitkExtractBonesGenericFilter.h [new file with mode: 0644]
segmentation/clitkExtractBonesGenericFilter.txx [new file with mode: 0644]
segmentation/clitkExtractImageFilter.h [new file with mode: 0644]
segmentation/clitkExtractImageFilter.txx [new file with mode: 0644]
segmentation/clitkExtractLung.cxx [new file with mode: 0644]
segmentation/clitkExtractLung.ggo [new file with mode: 0644]
segmentation/clitkExtractLungFilter.h [new file with mode: 0644]
segmentation/clitkExtractLungFilter.txx [new file with mode: 0644]
segmentation/clitkExtractLungGenericFilter.h [new file with mode: 0644]
segmentation/clitkExtractLungGenericFilter.txx [new file with mode: 0644]
segmentation/clitkExtractLymphStations.cxx [new file with mode: 0644]
segmentation/clitkExtractLymphStations.ggo [new file with mode: 0644]
segmentation/clitkExtractLymphStationsFilter.h [new file with mode: 0644]
segmentation/clitkExtractLymphStationsFilter.txx [new file with mode: 0644]
segmentation/clitkExtractLymphStationsGenericFilter.h [new file with mode: 0644]
segmentation/clitkExtractLymphStationsGenericFilter.txx [new file with mode: 0644]
segmentation/clitkExtractMediastinum.cxx [new file with mode: 0644]
segmentation/clitkExtractMediastinum.ggo [new file with mode: 0644]
segmentation/clitkExtractMediastinumFilter.h [new file with mode: 0644]
segmentation/clitkExtractMediastinumFilter.txx [new file with mode: 0644]
segmentation/clitkExtractMediastinumGenericFilter.h [new file with mode: 0644]
segmentation/clitkExtractMediastinumGenericFilter.txx [new file with mode: 0644]
segmentation/clitkExtractPatient.cxx [new file with mode: 0644]
segmentation/clitkExtractPatient.ggo [new file with mode: 0644]
segmentation/clitkExtractPatientFilter.h [new file with mode: 0644]
segmentation/clitkExtractPatientFilter.txx [new file with mode: 0644]
segmentation/clitkExtractPatientGenericFilter.cxx [new file with mode: 0644]
segmentation/clitkExtractPatientGenericFilter.h [new file with mode: 0644]
segmentation/clitkExtractPatientGenericFilter.txx [new file with mode: 0644]
segmentation/clitkFillMask.cxx [new file with mode: 0644]
segmentation/clitkFillMask.ggo [new file with mode: 0644]
segmentation/clitkFillMaskGenericFilter.cxx [new file with mode: 0644]
segmentation/clitkFillMaskGenericFilter.h [new file with mode: 0644]
segmentation/clitkFillMaskGenericFilter.txx [new file with mode: 0644]
segmentation/clitkTestFilter.cxx [new file with mode: 0644]
segmentation/clitkTestFilter.ggo [new file with mode: 0644]

diff --git a/segmentation/CMakeLists.txt b/segmentation/CMakeLists.txt
new file mode 100644 (file)
index 0000000..dfa795b
--- /dev/null
@@ -0,0 +1,51 @@
+#=========================================================
+
+INCLUDE(${PROJECT_SOURCE_DIR}/cmake/common.cmake)
+
+#=========================================================
+
+SET( CMAKE_VERBOSE_MAKEFILE off)
+
+#=========================================================
+
+WRAP_GGO(clitkSegmentationFilters_GGO_C
+  clitkFillMask.ggo
+  clitkConnectedComponentLabeling.ggo
+  clitkExtractLung.ggo
+  clitkExtractPatient.ggo
+  clitkExtractBones.ggo
+  clitkExtractMediastinum.ggo
+  clitkExtractLymphStations.ggo
+)
+
+SET(clitkSegmentationFilters_SRC
+  ${clitkSegmentationFilters_GGO_C}
+)  
+
+ADD_LIBRARY(clitkSegmentationFilters STATIC ${clitkSegmentationFilters_SRC})
+
+ADD_EXECUTABLE(clitkTestFilter clitkTestFilter.cxx clitkTestFilter_ggo.c)
+TARGET_LINK_LIBRARIES(clitkTestFilter clitkCommon ITKIO clitkSegmentationFilters ITKStatistics)
+
+## Segmentation part
+
+ADD_EXECUTABLE(clitkConnectedComponentLabeling clitkConnectedComponentLabeling.cxx)
+TARGET_LINK_LIBRARIES(clitkConnectedComponentLabeling clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkFillMask clitkFillMask.cxx clitkFillMaskGenericFilter.cxx)
+TARGET_LINK_LIBRARIES(clitkFillMask clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkExtractPatient clitkExtractPatient.cxx)
+TARGET_LINK_LIBRARIES(clitkExtractPatient clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkExtractLung clitkExtractLung.cxx)
+TARGET_LINK_LIBRARIES(clitkExtractLung clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkExtractBones clitkExtractBones.cxx)
+TARGET_LINK_LIBRARIES(clitkExtractBones clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkExtractMediastinum clitkExtractMediastinum.cxx)
+TARGET_LINK_LIBRARIES(clitkExtractMediastinum clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkExtractLymphStations clitkExtractLymphStations.cxx)
+TARGET_LINK_LIBRARIES(clitkExtractLymphStations clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
diff --git a/segmentation/clitkConnectedComponentLabeling.cxx b/segmentation/clitkConnectedComponentLabeling.cxx
new file mode 100644 (file)
index 0000000..620c5c4
--- /dev/null
@@ -0,0 +1,44 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkConnectedComponentLabeling_ggo.h"
+#include "clitkConnectedComponentLabelingGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+  // Init command line
+  GGO(clitkConnectedComponentLabeling, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::ConnectedComponentLabelingGenericFilter<args_info_clitkConnectedComponentLabeling> FilterType;
+  FilterType::Pointer filter = FilterType::New();
+
+  filter->SetArgsInfo(args_info);
+  filter->Update();
+
+  if (filter->HasError()) {
+    std::cout << filter->GetLastError() << std::endl;
+  }
+
+  return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
diff --git a/segmentation/clitkConnectedComponentLabeling.ggo b/segmentation/clitkConnectedComponentLabeling.ggo
new file mode 100644 (file)
index 0000000..7777010
--- /dev/null
@@ -0,0 +1,20 @@
+#File clitkConnectedComponentLabeling.ggo
+package "clitkConnectedComponentLabeling"
+version "1.0"
+purpose "Basic segmentation : connected component labeling "
+
+option "config"                -  "Config file"                  string        no
+option "verbose"        v  "Verbose"                     flag          off
+option "imagetypes"     -  "Display allowed image types"  flag          off
+option "verboseOption"  -  "Display options values"       flag          off
+
+section "I/O"
+
+option "input"       i "Input image filename"            string        yes
+option "inputBG"     - "Input Background"                int           default="0" no
+option "output"      o         "Output filename"                 string        yes
+
+section "Labelize"
+
+option "minSize"     - "Minimum component size in voxels"        int  no   default="100"
+option "full"        - "Full connecticity"                       flag off  
diff --git a/segmentation/clitkConnectedComponentLabelingGenericFilter.h b/segmentation/clitkConnectedComponentLabelingGenericFilter.h
new file mode 100644 (file)
index 0000000..82917d1
--- /dev/null
@@ -0,0 +1,76 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_H
+#define CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_H
+
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "itkMacro.h"
+
+//--------------------------------------------------------------------
+namespace clitk 
+{
+  
+  template<class ArgsInfoType>
+  class ITK_EXPORT ConnectedComponentLabelingGenericFilter: 
+    public ImageToImageGenericFilter<ConnectedComponentLabelingGenericFilter<ArgsInfoType> >
+  {
+    
+  public:
+    //--------------------------------------------------------------------
+    ConnectedComponentLabelingGenericFilter();
+
+    //--------------------------------------------------------------------
+    typedef ConnectedComponentLabelingGenericFilter Self;
+    typedef itk::SmartPointer<Self>                 Pointer;
+    typedef itk::SmartPointer<const Self>           ConstPointer;
+
+    //--------------------------------------------------------------------
+    itkNewMacro(Self);  
+    itkTypeMacro(ConnectedComponentLabelingGenericFilter, LightObject);
+
+    //--------------------------------------------------------------------
+    void SetArgsInfo(const ArgsInfoType & a);
+    std::vector<float> GetSizeOfObjectsInPixels() const { return m_SizeOfObjectsInPixels; }
+    std::vector<float> GetSizeOfObjectsInPhysicalUnits() const { return m_SizeOfObjectsInPhysicalUnits; }
+    itkGetConstMacro(OriginalNumberOfObjects, unsigned long int);
+
+    //--------------------------------------------------------------------
+    // Main function called each time the filter is updated
+    template<class ImageType>  
+    void UpdateWithInputImageType();
+
+  protected:
+    void Modified() {} // Need for using itkMacros
+    template<unsigned int Dim> void InitializeImageType();
+    ArgsInfoType mArgsInfo;
+    std::vector<float> m_SizeOfObjectsInPixels;
+    std::vector<float> m_SizeOfObjectsInPhysicalUnits;
+    unsigned long int m_OriginalNumberOfObjects;
+    
+  }; // end class
+  //--------------------------------------------------------------------
+    
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkConnectedComponentLabelingGenericFilter.txx"
+#endif
+
+#endif // #define CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_H
diff --git a/segmentation/clitkConnectedComponentLabelingGenericFilter.txx b/segmentation/clitkConnectedComponentLabelingGenericFilter.txx
new file mode 100644 (file)
index 0000000..caf5cdf
--- /dev/null
@@ -0,0 +1,120 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_TXX
+#define CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_TXX
+
+// clitk
+#include "clitkImageCommon.h"
+
+// itk
+#include "itkConnectedComponentImageFilter.h"
+#include "itkRelabelComponentImageFilter.h"
+  
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ConnectedComponentLabelingGenericFilter<ArgsInfoType>::ConnectedComponentLabelingGenericFilter():
+  ImageToImageGenericFilter<Self>("ConnectedComponentLabeling") 
+{
+  //  InitializeImageType<2>();
+  InitializeImageType<3>();
+  //InitializeImageType<4>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ConnectedComponentLabelingGenericFilter<ArgsInfoType>::InitializeImageType() 
+{  
+  ADD_IMAGE_TYPE(Dim, uchar);
+  ADD_IMAGE_TYPE(Dim, short);
+  // ADD_IMAGE_TYPE(Dim, int);
+  // ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::ConnectedComponentLabelingGenericFilter<ArgsInfoType>::SetArgsInfo(const ArgsInfoType & a) 
+{
+  mArgsInfo=a;
+  SetIOVerbose(mArgsInfo.verbose_flag);
+  if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
+  if (mArgsInfo.input_given)   AddInputFilename(mArgsInfo.input_arg);
+  if (mArgsInfo.output_given)  SetOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::ConnectedComponentLabelingGenericFilter<ArgsInfoType>::UpdateWithInputImageType() 
+{ 
+  DD("UpdateWithInputImageType");
+
+  // Reading input
+  typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
+
+  // Output image type
+  typedef itk::Image<int, ImageType::ImageDimension> OutputImageType;
+
+  // Create CCL filter
+  DD("CCL");
+  typedef itk::ConnectedComponentImageFilter<ImageType, OutputImageType> ConnectFilterType;
+  typename ConnectFilterType::Pointer connectFilter = ConnectFilterType::New();
+  connectFilter->SetInput(input);
+  connectFilter->SetBackgroundValue(mArgsInfo.inputBG_arg);
+  connectFilter->SetFullyConnected(mArgsInfo.full_flag);
+
+  // TODO SetBackgroud to zero forr relabel ?
+
+
+  // Sort by size and remove too small area.
+  typedef itk::RelabelComponentImageFilter<OutputImageType, OutputImageType> RelabelFilterType;
+  typename RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New();
+  //  relabelFilter->InPlaceOn();
+  relabelFilter->SetInput(connectFilter->GetOutput());
+  relabelFilter->SetMinimumObjectSize(mArgsInfo.minSize_arg);
+  relabelFilter->Update();
+
+  DD(mArgsInfo.inputBG_arg);
+  DD(mArgsInfo.full_flag);
+  DD(mArgsInfo.minSize_arg);
+  
+  // Set information
+  const std::vector<typename RelabelFilterType::ObjectSizeType> & a = relabelFilter->GetSizeOfObjectsInPixels();
+  m_SizeOfObjectsInPixels.resize(a.size());
+  for(unsigned int i=0; i<a.size(); i++) m_SizeOfObjectsInPixels[i] = a[i];
+  m_SizeOfObjectsInPhysicalUnits = relabelFilter->GetSizeOfObjectsInPhysicalUnits();
+  m_OriginalNumberOfObjects = relabelFilter->GetOriginalNumberOfObjects();
+  DD(m_OriginalNumberOfObjects);
+  DD(m_SizeOfObjectsInPhysicalUnits.size());
+
+  // Write/Save results
+  typename OutputImageType::Pointer output = relabelFilter->GetOutput();
+  this->template SetNextOutput<OutputImageType>(output); 
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_TXX
diff --git a/segmentation/clitkExtractBones.cxx b/segmentation/clitkExtractBones.cxx
new file mode 100644 (file)
index 0000000..2122fc7
--- /dev/null
@@ -0,0 +1,40 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkExtractBones_ggo.h"
+#include "clitkExtractBonesGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+  // Init command line
+  GGO(clitkExtractBones, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::ExtractBonesGenericFilter<args_info_clitkExtractBones> FilterType;
+  FilterType::Pointer filter = FilterType::New();
+
+  filter->SetArgsInfo(args_info);
+  filter->Update();
+
+  return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
diff --git a/segmentation/clitkExtractBones.ggo b/segmentation/clitkExtractBones.ggo
new file mode 100644 (file)
index 0000000..581392b
--- /dev/null
@@ -0,0 +1,34 @@
+#File clitkExtractBones.ggo
+package "clitkExtractBones"
+version "1.0"
+purpose "Extract bony anatomy through thresholding and connected component labelling. Resample mask afterwards (interp= NN) to match another one (like)"
+
+option "config"                -  "Config file"                  string        no
+option "imagetypes"     -  "Display allowed image types"  flag          off
+option "verbose"        v  "Verbose"                     flag          off
+option "verboseStep"    -  "Verbose each step"           flag          off
+option "writeStep"      w  "Write image at each step"    flag          off
+option "verboseOption"  -  "Display options values"       flag          off
+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 "like"          l       "Resample like this image"        string        no
+
+section "Initial connected component labelling (CCL)"
+
+option "lower1"                        -       "Lower threshold for CCL"                       double  no default="100" 
+option "upper1"                        -       "Upper threshold for CCL"                       double  no default="1500" 
+option "minSize"               -       "Minimal Component Size for CCL"                int     no default="100" 
+option "full"                  -       "Use full connectivity (one side is enough)"    flag    off 
+
+section "Neighborhood Connected Region Growing (RG)"
+
+option "lower2"                -       "Lower threshold for RG"                double  no      default="10" 
+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
diff --git a/segmentation/clitkExtractBonesFilter.h b/segmentation/clitkExtractBonesFilter.h
new file mode 100644 (file)
index 0000000..b483f37
--- /dev/null
@@ -0,0 +1,189 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTBONESSFILTER_H
+#define CLITKEXTRACTBONESSFILTER_H
+
+// clitk 
+#include "clitkFilterBase.h"
+#include "clitkDecomposeAndReconstructImageFilter.h"
+#include "clitkExplosionControlledThresholdConnectedImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+
+// itk
+#include "itkStatisticsImageFilter.h"
+
+namespace clitk {
+  
+  //--------------------------------------------------------------------
+  /*
+    Extract bony anatomy through thresholding and connected component labelling.
+  */
+  //--------------------------------------------------------------------
+  
+  template <class TInputImageType, class TOutputImageType>
+  class ITK_EXPORT ExtractBonesFilter: 
+    public clitk::FilterBase, 
+    public itk::ImageToImageFilter<TInputImageType, TOutputImageType> 
+  {
+    
+  public:
+    /** Standard class typedefs. */
+    typedef ExtractBonesFilter              Self;
+    typedef itk::ImageToImageFilter<TInputImageType, TOutputImageType> Superclass;
+    typedef itk::SmartPointer<Self>         Pointer;
+    typedef itk::SmartPointer<const Self>   ConstPointer;
+    
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);  
+    
+    /** Run-time type information (and related methods). */
+    itkTypeMacro(ExtractBonesFilter, ImageToImageFilter);
+    FILTERBASE_INIT;
+
+    /** Some convenient typedefs */
+    typedef TInputImageType                       InputImageType;
+    typedef typename InputImageType::ConstPointer InputImageConstPointer;
+    typedef typename InputImageType::Pointer      InputImagePointer;
+    typedef typename InputImageType::RegionType   InputImageRegionType; 
+    typedef typename InputImageType::PixelType    InputImagePixelType; 
+    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; 
+
+    itkStaticConstMacro(ImageDimension, unsigned int, InputImageType::ImageDimension);
+    typedef int InternalPixelType;
+    typedef itk::Image<InternalPixelType, InputImageType::ImageDimension> InternalImageType;
+    typedef typename InternalImageType::Pointer                           InternalImagePointer;
+    typedef typename InternalImageType::IndexType                         InternalIndexType;
+    typedef LabelizeParameters<InternalPixelType>                         LabelParamType;
+    
+    /** Connect inputs */
+    void SetInput(const InputImageType * image);
+    // Set all options at a time
+    template<class ArgsInfoType>
+      void SetArgsInfo(ArgsInfoType arg);
+
+    // Background / Foreground
+    itkGetConstMacro(BackgroundValue, OutputImagePixelType);
+    itkGetConstMacro(ForegroundValue, OutputImagePixelType);
+
+    itkSetMacro(MinimalComponentSize, int);
+    itkGetConstMacro(MinimalComponentSize, int);
+    GGO_DefineOption(minSize, SetMinimalComponentSize, int);
+
+    // Step 1 
+    itkSetMacro(UpperThreshold1, InputImagePixelType);
+    itkGetMacro(UpperThreshold1, InputImagePixelType);
+    GGO_DefineOption(upper1, SetUpperThreshold1, InputImagePixelType);
+
+    itkSetMacro(LowerThreshold1, InputImagePixelType);
+    itkGetMacro(LowerThreshold1, InputImagePixelType);
+    GGO_DefineOption(lower1, SetLowerThreshold1, InputImagePixelType);
+
+    itkSetMacro(FullConnectivity, bool);
+    itkGetConstMacro(FullConnectivity, bool);
+    itkBooleanMacro(FullConnectivity);
+    GGO_DefineOption_Flag(full, SetFullConnectivity);
+
+    // Step 2 
+    itkSetMacro(UpperThreshold2, InputImagePixelType);
+    itkGetMacro(UpperThreshold2, InputImagePixelType);
+    GGO_DefineOption(upper2, SetUpperThreshold2, InputImagePixelType);
+
+    itkSetMacro(LowerThreshold2, InputImagePixelType);
+    itkGetMacro(LowerThreshold2, InputImagePixelType);
+    GGO_DefineOption(lower2, SetLowerThreshold2, InputImagePixelType);
+
+    itkSetMacro(Radius2, InputImageSizeType);
+    itkGetConstMacro(Radius2, InputImageSizeType);
+    GGO_DefineOption_Vector(radius2, SetRadius2, InputImageSizeType, ImageDimension, true);
+
+    itkSetMacro(SampleRate2, int);
+    itkGetConstMacro(SampleRate2, int);
+    GGO_DefineOption(sampleRate2, SetSampleRate2, int);
+
+    // Final Step
+    itkSetMacro(AutoCrop, bool);
+    itkGetConstMacro(AutoCrop, bool);
+    itkBooleanMacro(AutoCrop);
+    GGO_DefineOption_Flag(autoCrop, SetAutoCrop);
+
+  protected:
+    ExtractBonesFilter();
+    virtual ~ExtractBonesFilter() {}
+    
+    // Global options
+    itkSetMacro(BackgroundValue, OutputImagePixelType);
+    itkSetMacro(ForegroundValue, OutputImagePixelType);
+    OutputImagePixelType m_BackgroundValue;
+    OutputImagePixelType m_ForegroundValue;
+
+    // Step 1
+    InputImagePixelType m_UpperThreshold1;
+    InputImagePixelType m_LowerThreshold1;
+    int m_MinimalComponentSize;
+    bool m_FullConnectivity;
+
+    // Step 2
+    InputImagePixelType m_UpperThreshold2;
+    InputImagePixelType m_LowerThreshold2;
+    InputImageSizeType m_Radius2;
+    int m_SampleRate2;
+    
+    bool m_AutoCrop;
+
+    virtual void GenerateOutputInformation();
+    virtual void GenerateData();
+
+    // Steps
+    void RemoveAir();
+    void FindTrachea();
+    void ExtractBones();
+    void RemoveTrachea();
+    void BonesSeparation();
+    InputImageConstPointer input;
+    OutputImageConstPointer patient;
+    InputImagePointer working_input;
+    typename InternalImageType::Pointer working_image;  
+    typename InternalImageType::Pointer trachea;
+    typename InternalImageType::Pointer output;
+        
+  private:
+    ExtractBonesFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractBonesFilter.txx"
+#endif
+
+#endif
diff --git a/segmentation/clitkExtractBonesFilter.txx b/segmentation/clitkExtractBonesFilter.txx
new file mode 100644 (file)
index 0000000..db29cc7
--- /dev/null
@@ -0,0 +1,263 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTBONESSFILTER_TXX
+#define CLITKEXTRACTBONESSFILTER_TXX
+
+// clitk
+#include "clitkImageCommon.h"
+#include "clitkSetBackgroundImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+#include "clitkAutoCropFilter.h"
+
+// itk
+#include "itkBinaryThresholdImageFilter.h"
+#include "itkConnectedComponentImageFilter.h"
+#include "itkRelabelComponentImageFilter.h"
+#include "itkNeighborhoodConnectedImageFilter.h"
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+ExtractBonesFilter():
+  clitk::FilterBase(),
+  itk::ImageToImageFilter<TInputImageType, TOutputImageType>()
+{
+  // Default global options
+  this->SetNumberOfRequiredInputs(1);
+  SetBackgroundValue(0); // Must be zero
+  SetForegroundValue(1);
+
+  SetMinimalComponentSize(100);
+  SetUpperThreshold1(1500);
+  SetLowerThreshold1(100);
+  SetFullConnectivity(false);
+
+  SetUpperThreshold2(1500);
+  SetLowerThreshold2(10);
+  InputImageSizeType s;
+  s.Fill(1);
+  SetRadius2(s);
+  SetSampleRate2(0);
+  AutoCropOff();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void 
+clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+SetInput(const TInputImageType * image) 
+{
+  this->SetNthInput(0, const_cast<TInputImageType *>(image));
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+template<class ArgsInfoType>
+void 
+clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+SetArgsInfo(ArgsInfoType mArgsInfo)
+{
+  SetVerboseOption_GGO(mArgsInfo);
+  SetVerboseStep_GGO(mArgsInfo);
+  SetWriteStep_GGO(mArgsInfo);
+  SetVerboseWarningOff_GGO(mArgsInfo);
+
+  SetMinimalComponentSize_GGO(mArgsInfo);
+  SetUpperThreshold1_GGO(mArgsInfo);
+  SetLowerThreshold1_GGO(mArgsInfo);
+  SetFullConnectivity_GGO(mArgsInfo);
+
+  SetUpperThreshold2_GGO(mArgsInfo);
+  SetLowerThreshold2_GGO(mArgsInfo);
+  SetRadius2_GGO(mArgsInfo);
+  SetSampleRate2_GGO(mArgsInfo);
+  SetAutoCrop_GGO(mArgsInfo);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void 
+clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+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);
+  outputImage->SetRegions(input->GetLargestPossibleRegion());
+
+  // 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; 
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Initial Labeling");
+
+  typename InternalImageType::Pointer firstLabelImage;
+    
+  //---------------------------------
+  // Binarize the image
+  //---------------------------------
+  typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New();
+  binarizeFilter->SetInput(input);
+  binarizeFilter->SetLowerThreshold(GetLowerThreshold1());
+  binarizeFilter->SetUpperThreshold(GetUpperThreshold1());
+  binarizeFilter->SetInsideValue(this->GetForegroundValue());
+  binarizeFilter->SetOutsideValue(this->GetBackgroundValue());
+
+  //---------------------------------
+  // Label the connected components
+  //---------------------------------
+  typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
+  connectFilter->SetInput(binarizeFilter->GetOutput());
+  connectFilter->SetBackgroundValue(this->GetBackgroundValue());
+  connectFilter->SetFullyConnected(GetFullConnectivity());
+
+  //---------------------------------
+  // Sort the labels according to size
+  //---------------------------------
+  typename RelabelFilterType::Pointer relabelFilter=RelabelFilterType::New();
+  relabelFilter->SetInput(connectFilter->GetOutput());
+  relabelFilter->SetMinimumObjectSize(GetMinimalComponentSize());
+    
+  //---------------------------------
+  // Keep the label
+  //---------------------------------
+  typename BinarizeFilterType::Pointer binarizeFilter2=BinarizeFilterType::New();
+  binarizeFilter2->SetInput(relabelFilter->GetOutput());
+  binarizeFilter2->SetLowerThreshold(1);
+  binarizeFilter2->SetUpperThreshold(1);
+  binarizeFilter2->SetInsideValue(this->GetForegroundValue());
+  binarizeFilter2->SetOutsideValue(this->GetBackgroundValue());
+  binarizeFilter2->Update();
+
+  firstLabelImage = binarizeFilter2->GetOutput();
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Neighborhood connected filter");
+  typename InternalImageType::Pointer secondLabelImage;
+    
+  //---------------------------------
+  //Neighborhood connected RG 
+  //---------------------------------
+  typedef itk::NeighborhoodConnectedImageFilter<InputImageType, InternalImageType> 
+    NeighborhoodConnectedImageFilterType;
+  typename NeighborhoodConnectedImageFilterType::Pointer neighborhoodConnectedImageFilter= 
+    NeighborhoodConnectedImageFilterType::New();
+  
+  // thresholds
+  neighborhoodConnectedImageFilter->SetLower(GetLowerThreshold2());
+  neighborhoodConnectedImageFilter->SetUpper(GetUpperThreshold2());
+  neighborhoodConnectedImageFilter->SetReplaceValue(this->GetForegroundValue());
+  neighborhoodConnectedImageFilter->SetRadius(GetRadius2());
+  neighborhoodConnectedImageFilter->SetInput(input);
+
+  // Seeds from label image
+  typedef itk::ImageRegionIteratorWithIndex<InternalImageType> IteratorType;
+  IteratorType it(firstLabelImage, firstLabelImage->GetLargestPossibleRegion());
+  typename InputImageType::IndexType index;
+  unsigned int counter=0;
+  while (!it.IsAtEnd())
+    {
+      if (it.Get()==this->GetForegroundValue())
+       {
+         counter++;
+         index=it.GetIndex();
+         neighborhoodConnectedImageFilter->AddSeed(index);
+         ++it;
+         unsigned int i=0;
+         while (!it.IsAtEnd()  &&  i< (unsigned int) GetSampleRate2())
+           {        
+             ++it;
+             i++;
+           }
+       }
+      else ++it;
+    }
+
+  neighborhoodConnectedImageFilter->Update();
+  secondLabelImage = neighborhoodConnectedImageFilter->GetOutput();
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Combine de images");
+  typedef clitk::SetBackgroundImageFilter<InternalImageType, InternalImageType, InternalImageType> 
+    SetBackgroundImageFilterType;
+  typename SetBackgroundImageFilterType::Pointer setBackgroundFilter=SetBackgroundImageFilterType::New();
+  setBackgroundFilter->SetInput(firstLabelImage);
+  setBackgroundFilter->SetInput2(secondLabelImage);
+  setBackgroundFilter->SetMaskValue(this->GetForegroundValue());
+  setBackgroundFilter->SetOutsideValue(this->GetForegroundValue());
+  setBackgroundFilter->Update();
+
+  output = setBackgroundFilter->GetOutput();
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // [Optional]
+  if (GetAutoCrop()) {
+    StartNewStep("AutoCrop");
+    typedef clitk::AutoCropFilter<InternalImageType> CropFilterType;
+    typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+    cropFilter->SetInput(output);
+    cropFilter->SetBackgroundValue(GetBackgroundValue());
+    cropFilter->Update();   
+    output = cropFilter->GetOutput();
+    StopCurrentStep<InternalImageType>(output);
+    outputImage->SetRegions(output->GetLargestPossibleRegion());
+  }
+
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void 
+clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+GenerateData() {
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // Final Cast 
+  typedef itk::CastImageFilter<InternalImageType, OutputImageType> CastImageFilterType;
+  typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
+  caster->SetInput(output);
+  caster->Update();
+  //this->SetNthOutput(0, caster->GetOutput());
+  this->GraftOutput(caster->GetOutput());
+  return;
+}
+//--------------------------------------------------------------------
+
+  
+#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
diff --git a/segmentation/clitkExtractBonesGenericFilter.h b/segmentation/clitkExtractBonesGenericFilter.h
new file mode 100644 (file)
index 0000000..9093ac6
--- /dev/null
@@ -0,0 +1,70 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKEXTRACTBONESSGENERICFILTER_H
+#define CLITKEXTRACTBONESSGENERICFILTER_H
+
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkExtractBonesFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk 
+{
+  
+  template<class ArgsInfoType>
+  class ITK_EXPORT ExtractBonesGenericFilter: 
+    public ImageToImageGenericFilter<ExtractBonesGenericFilter<ArgsInfoType> >
+  {
+    
+  public:
+    //--------------------------------------------------------------------
+    ExtractBonesGenericFilter();
+
+    //--------------------------------------------------------------------
+    typedef ExtractBonesGenericFilter      Self;
+    typedef ImageToImageGenericFilter<ExtractBonesGenericFilter<ArgsInfoType> > Superclass;
+    typedef itk::SmartPointer<Self>       Pointer;
+    typedef itk::SmartPointer<const Self> ConstPointer;
+
+    //--------------------------------------------------------------------
+    itkNewMacro(Self);  
+    itkTypeMacro(ExtractBonesGenericFilter, LightObject);
+
+    //--------------------------------------------------------------------
+    void SetArgsInfo(const ArgsInfoType & a);
+
+    //--------------------------------------------------------------------
+    // Main function called each time the filter is updated
+    template<class ImageType>  
+    void UpdateWithInputImageType();
+
+  protected:
+    template<unsigned int Dim> void InitializeImageType();
+    ArgsInfoType mArgsInfo;
+    
+  }; // end class
+  //--------------------------------------------------------------------
+    
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractBonesGenericFilter.txx"
+#endif
+
+#endif // #define CLITKEXTRACTBONESSGENERICFILTER_H
diff --git a/segmentation/clitkExtractBonesGenericFilter.txx b/segmentation/clitkExtractBonesGenericFilter.txx
new file mode 100644 (file)
index 0000000..5c72672
--- /dev/null
@@ -0,0 +1,98 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTBONESSGENERICFILTER_TXX
+#define CLITKEXTRACTBONESSGENERICFILTER_TXX
+
+#include "clitkImageCommon.h"
+  
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ExtractBonesGenericFilter<ArgsInfoType>::ExtractBonesGenericFilter():
+  ImageToImageGenericFilter<Self>("ExtractBones") 
+{
+  // Default values
+  cmdline_parser_clitkExtractBones_init(&mArgsInfo);
+  InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ExtractBonesGenericFilter<ArgsInfoType>::InitializeImageType() 
+{  
+  ADD_IMAGE_TYPE(Dim, short);
+  // ADD_IMAGE_TYPE(Dim, int);
+  // ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::ExtractBonesGenericFilter<ArgsInfoType>::SetArgsInfo(const ArgsInfoType & a) 
+{
+  mArgsInfo=a;
+  SetIOVerbose(mArgsInfo.verbose_flag);
+  if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
+  if (mArgsInfo.input_given)   AddInputFilename(mArgsInfo.input_arg);
+  if (mArgsInfo.output_given)  AddOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::ExtractBonesGenericFilter<ArgsInfoType>::UpdateWithInputImageType() 
+{ 
+  // Mask & output image type
+  typedef itk::Image<uchar, ImageType::ImageDimension> OutputImageType;
+
+  // Reading input
+  typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
+
+  // Create filter
+  typedef clitk::ExtractBonesFilter<ImageType, OutputImageType> FilterType;
+  typename FilterType::Pointer filter = FilterType::New();
+    
+  // Set global Options 
+  filter->SetArgsInfo(mArgsInfo);
+  filter->SetInput(input);
+
+  // Go !
+  filter->Update();
+  
+  // Check if error
+  if (filter->HasError()) {
+    SetLastError(filter->GetLastError());
+    // No output
+    return;
+  }
+
+  // Write/Save results
+  typename OutputImageType::Pointer output = filter->GetOutput();
+  this->template SetNextOutput<OutputImageType>(output); 
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKEXTRACTBONESSGENERICFILTER_TXX
diff --git a/segmentation/clitkExtractImageFilter.h b/segmentation/clitkExtractImageFilter.h
new file mode 100644 (file)
index 0000000..1d888f7
--- /dev/null
@@ -0,0 +1,98 @@
+
+#ifndef __clitkExtractImageFilter_h
+#define __clitkExtractImageFilter_h
+
+#include "itkImageToImageFilter.h"
+#include "itkSmartPointer.h"
+#include "itkExtractImageFilterRegionCopier.h"
+
+namespace clitk
+{
+
+template <class TInputImage, class TOutputImage>
+class ITK_EXPORT ExtractImageFilter:
+    public itk::ImageToImageFilter<TInputImage,TOutputImage>
+{
+public:
+  /** Standard class typedefs. */
+  typedef ExtractImageFilter         Self;
+  typedef itk::ImageToImageFilter<TInputImage,TOutputImage>  Superclass;
+  typedef itk::SmartPointer<Self>  Pointer;
+  typedef itk::SmartPointer<const Self>  ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);  
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(ExtractImageFilter, ImageToImageFilter);
+
+  /** Image type information. */
+  typedef TInputImage  InputImageType;
+  typedef TOutputImage OutputImageType;
+
+  /** Typedef to describe the output and input image region types. */
+  typedef typename TOutputImage::RegionType OutputImageRegionType;
+  typedef typename TInputImage::RegionType InputImageRegionType;
+
+  /** Typedef to describe the type of pixel. */
+  typedef typename TOutputImage::PixelType OutputImagePixelType;
+  typedef typename TInputImage::PixelType InputImagePixelType;
+
+  /** Typedef to describe the output and input image index and size types. */
+  typedef typename TOutputImage::IndexType OutputImageIndexType;
+  typedef typename TInputImage::IndexType InputImageIndexType;
+  typedef typename TOutputImage::SizeType OutputImageSizeType;
+  typedef typename TInputImage::SizeType InputImageSizeType;
+
+  /** ImageDimension enumeration */
+  itkStaticConstMacro(InputImageDimension, unsigned int,
+                      TInputImage::ImageDimension);
+  itkStaticConstMacro(OutputImageDimension, unsigned int,
+                      TOutputImage::ImageDimension);
+
+  typedef itk::ImageToImageFilterDetail::ExtractImageFilterRegionCopier<
+    itkGetStaticConstMacro(InputImageDimension), 
+    itkGetStaticConstMacro(OutputImageDimension)> ExtractImageFilterRegionCopierType;
+
+  void SetExtractionRegion(InputImageRegionType extractRegion);
+  itkGetMacro(ExtractionRegion, InputImageRegionType);
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+  /** Begin concept checking */
+  itkConceptMacro(InputCovertibleToOutputCheck,
+                 (itk::Concept::Convertible<InputImagePixelType, OutputImagePixelType>));
+  /** End concept checking */
+#endif
+
+protected:
+  ExtractImageFilter();
+  ~ExtractImageFilter() {};
+  void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+
+  virtual void GenerateOutputInformation();
+
+
+  virtual void CallCopyOutputRegionToInputRegion(InputImageRegionType &destRegion,
+                                                 const OutputImageRegionType &srcRegion);
+
+
+  void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
+                            int threadId );
+  InputImageRegionType m_ExtractionRegion;
+  OutputImageRegionType m_OutputImageRegion;
+
+private:
+  ExtractImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+};
+
+  
+} // end namespace itk
+  
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractImageFilter.txx"
+#endif
+  
+#endif
diff --git a/segmentation/clitkExtractImageFilter.txx b/segmentation/clitkExtractImageFilter.txx
new file mode 100644 (file)
index 0000000..020cbb1
--- /dev/null
@@ -0,0 +1,259 @@
+
+#ifndef _clitkExtractImageFilter_txx
+#define _clitkExtractImageFilter_txx
+
+#include "clitkExtractImageFilter.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkObjectFactory.h"
+#include "itkExtractImageFilterRegionCopier.h"
+#include "itkProgressReporter.h"
+
+
+namespace clitk
+{
+
+/**
+ *
+ */
+template <class TInputImage, class TOutputImage>
+ExtractImageFilter<TInputImage,TOutputImage>
+::ExtractImageFilter() 
+{
+}
+
+
+/**
+ *
+ */
+template <class TInputImage, class TOutputImage>
+void 
+ExtractImageFilter<TInputImage,TOutputImage>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os,indent);
+
+  os << indent << "ExtractionRegion: " << m_ExtractionRegion << std::endl;
+  os << indent << "OutputImageRegion: " << m_OutputImageRegion << std::endl;
+}
+
+
+template<class TInputImage, class TOutputImage>
+void 
+ExtractImageFilter<TInputImage,TOutputImage>
+::CallCopyOutputRegionToInputRegion(InputImageRegionType &destRegion,
+                                    const OutputImageRegionType &srcRegion)
+{
+  ExtractImageFilterRegionCopierType extractImageRegionCopier;
+  extractImageRegionCopier(destRegion, srcRegion, m_ExtractionRegion);
+}
+
+
+template <class TInputImage, class TOutputImage>
+void 
+ExtractImageFilter<TInputImage,TOutputImage>
+::SetExtractionRegion(InputImageRegionType extractRegion)
+{
+  m_ExtractionRegion = extractRegion;
+
+  unsigned int nonzeroSizeCount = 0;
+  InputImageSizeType inputSize = extractRegion.GetSize();
+  OutputImageSizeType outputSize;
+  OutputImageIndexType outputIndex;
+
+  /**
+   * check to see if the number of non-zero entries in the extraction region
+   * matches the number of dimensions in the output image.  
+   **/
+  for (unsigned int i = 0; i < InputImageDimension; ++i)
+    {
+    if (inputSize[i])
+      { 
+      outputSize[nonzeroSizeCount] = inputSize[i];    
+      outputIndex[nonzeroSizeCount] = extractRegion.GetIndex()[i];
+      nonzeroSizeCount++;
+      }
+    }
+    
+  if (nonzeroSizeCount != OutputImageDimension)
+    {
+    itkExceptionMacro("Extraction Region not consistent with output image");
+    }
+
+  m_OutputImageRegion.SetSize(outputSize);
+  m_OutputImageRegion.SetIndex(outputIndex);
+  this->Modified();
+}
+
+
+
+/** 
+ * ExtractImageFilter can produce an image which is a different resolution
+ * than its input image.  As such, ExtractImageFilter needs to provide an
+ * implementation for GenerateOutputInformation() in order to inform
+ * the pipeline execution model.  The original documentation of this
+ * method is below.
+ *
+ * \sa ProcessObject::GenerateOutputInformaton() 
+ */
+template <class TInputImage, class TOutputImage>
+void 
+ExtractImageFilter<TInputImage,TOutputImage>
+::GenerateOutputInformation()
+{
+  // do not call the superclass' implementation of this method since
+  // this filter allows the input and the output to be of different dimensions
+  // get pointers to the input and output
+  typename Superclass::OutputImagePointer      outputPtr = this->GetOutput();
+  typename Superclass::InputImageConstPointer  inputPtr  = this->GetInput();
+
+  if ( !outputPtr || !inputPtr)
+    {
+    return;
+    }
+
+  // Set the output image size to the same value as the extraction region.
+  outputPtr->SetLargestPossibleRegion( m_OutputImageRegion );
+
+  // Set the output spacing and origin
+  const itk::ImageBase<InputImageDimension> *phyData;
+
+  phyData
+    = dynamic_cast<const itk::ImageBase<InputImageDimension>*>(this->GetInput());
+
+  if (phyData)
+    {
+    // Copy what we can from the image from spacing and origin of the input
+    // This logic needs to be augmented with logic that select which
+    // dimensions to copy
+
+    unsigned int i;
+    const typename InputImageType::SpacingType& 
+      inputSpacing = inputPtr->GetSpacing();
+    const typename InputImageType::DirectionType&
+      inputDirection = inputPtr->GetDirection();
+    const typename InputImageType::PointType&
+      inputOrigin = inputPtr->GetOrigin();
+
+    typename OutputImageType::SpacingType outputSpacing;
+    typename OutputImageType::DirectionType outputDirection;
+    typename OutputImageType::PointType outputOrigin;
+
+    if ( static_cast<unsigned int>(OutputImageDimension) > 
+         static_cast<unsigned int>(InputImageDimension )    )
+      {
+      // copy the input to the output and fill the rest of the
+      // output with zeros.
+      for (i=0; i < InputImageDimension; ++i)
+        {
+        outputSpacing[i] = inputSpacing[i];
+        outputOrigin[i] = inputOrigin[i];
+        for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
+          {
+          outputDirection[i][dim] = inputDirection[i][dim];
+          }
+        }
+      for (; i < OutputImageDimension; ++i)
+        {
+        outputSpacing[i] = 1.0;
+        outputOrigin[i] = 0.0;
+        for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
+          {
+          outputDirection[i][dim] = 0.0;
+          }
+        outputDirection[i][i] = 1.0;
+        }
+      }
+    else
+      {
+      // copy the non-collapsed part of the input spacing and origing to the output
+      int nonZeroCount = 0;
+      for (i=0; i < InputImageDimension; ++i)
+        {
+        if (m_ExtractionRegion.GetSize()[i])
+          {
+          outputSpacing[nonZeroCount] = inputSpacing[i];
+          outputOrigin[nonZeroCount] = inputOrigin[i];
+          int nonZeroCount2 = 0;
+          for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
+            {
+            if (m_ExtractionRegion.GetSize()[dim])
+              {
+              outputDirection[nonZeroCount][nonZeroCount2] =
+                inputDirection[i][dim];
+              ++nonZeroCount2;
+              }
+            }
+          nonZeroCount++;
+          }
+        }
+      }
+
+    // set the spacing and origin
+    outputPtr->SetSpacing( outputSpacing );
+    outputPtr->SetDirection( outputDirection );
+    outputPtr->SetOrigin( outputOrigin );
+    outputPtr->SetNumberOfComponentsPerPixel(inputPtr->GetNumberOfComponentsPerPixel() );
+    }
+  else
+    {
+    // pointer could not be cast back down
+    itkExceptionMacro(<< "itk::ExtractImageFilter::GenerateOutputInformation "
+                      << "cannot cast input to "
+                      << typeid(itk::ImageBase<InputImageDimension>*).name() );
+    }
+}
+
+/** 
+   * ExtractImageFilter can be implemented as a multithreaded filter.
+   * Therefore, this implementation provides a ThreadedGenerateData()
+   * routine which is called for each processing thread. The output
+   * image data is allocated automatically by the superclass prior to
+   * calling ThreadedGenerateData().  ThreadedGenerateData can only
+   * write to the portion of the output image specified by the
+   * parameter "outputRegionForThread"
+   *
+   * \sa ImageToImageFilter::ThreadedGenerateData(),
+   *     ImageToImageFilter::GenerateData() 
+   */
+template <class TInputImage, class TOutputImage>
+void 
+ExtractImageFilter<TInputImage,TOutputImage>
+::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
+                       int threadId)
+{
+  itkDebugMacro(<<"Actually executing");
+
+  // Get the input and output pointers
+  typename Superclass::InputImageConstPointer  inputPtr = this->GetInput();
+  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
+
+  // support progress methods/callbacks
+ itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
+  
+  // Define the portion of the input to walk for this thread
+  InputImageRegionType inputRegionForThread;
+  this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);
+  
+  // Define the iterators.
+  typedef itk::ImageRegionIterator<TOutputImage> OutputIterator;
+  typedef itk::ImageRegionConstIterator<TInputImage> InputIterator;
+
+  OutputIterator outIt(outputPtr, outputRegionForThread);
+  InputIterator inIt(inputPtr, inputRegionForThread);
+
+  // walk the output region, and sample the input image
+  while( !outIt.IsAtEnd() )
+    {
+    // copy the input pixel to the output
+    outIt.Set( static_cast<OutputImagePixelType>(inIt.Get()));
+    ++outIt; 
+    ++inIt; 
+    progress.CompletedPixel();
+    }
+}
+
+} // end namespace clitk
+
+#endif
diff --git a/segmentation/clitkExtractLung.cxx b/segmentation/clitkExtractLung.cxx
new file mode 100644 (file)
index 0000000..01ed6a8
--- /dev/null
@@ -0,0 +1,44 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkExtractLung_ggo.h"
+#include "clitkExtractLungGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+  // Init command line
+  GGO(clitkExtractLung, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::ExtractLungGenericFilter<args_info_clitkExtractLung> FilterType;
+  FilterType::Pointer filter = FilterType::New();
+
+  filter->SetArgsInfo(args_info);
+  filter->Update();
+
+  if (filter->HasError()) {
+    std::cout << filter->GetLastError() << std::endl;
+  }
+
+  return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
diff --git a/segmentation/clitkExtractLung.ggo b/segmentation/clitkExtractLung.ggo
new file mode 100644 (file)
index 0000000..883a013
--- /dev/null
@@ -0,0 +1,51 @@
+#File clitkExtractLungs.ggo
+package "clitkExtractLungs"
+version "1.0"
+purpose "Segment lungs in CT image. Need 'patient' mask."
+
+option "config"                -  "Config file"                  string        no
+option "imagetypes"     -  "Display allowed image types"  flag          off
+option "verbose"        v  "Verbose"                     flag          off
+option "verboseStep"    -  "Verbose each step"           flag          off
+option "writeStep"      w  "Write image at each step"    flag          off
+option "verboseOption"  -  "Display options values"       flag          off
+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 "output"        o       "Output lungs mask filename"      string        yes
+option "outputTrachea" t       "Output trachea mask filename"    string        no
+
+section "Step 1 : Air remove"
+
+option "lower"      -  "Initial lower threshold"                 double        no      
+option "upper"      -  "Initial upper threshold"                 double        no      default="-300"
+option "minSize"     - "Minimum component size in voxels"        int           no      default="100"
+option "remove1"     - "Labels not to keep in air mask (lungs)"  int           no      multiple        default="2"
+option "firstKeep1"  - "First label to keep"                     int           no      default="1"
+option "lastKeep1"   - "Last label to keep"                      int           no      
+
+section "Step 2 : find trachea"
+
+option "upperThresholdForTrachea"    - "Initial upper threshold for trachea"  double   no  default="-900"
+option "multiplierForTrachea"       -  "Multiplier for the region growing"    double   no  default="5"
+option "thresholdStepSizeForTrachea" - "Threshold step size"                  int      no  default="64"
+option "seed"                        - "Index of the trachea seed point"      int      no  multiple
+
+section "Step 3 : auto extract lung"
+
+option "bins"       -  "Number of bins to use for the Otsu thresholding"       int             no      default="500"   
+option "remove2"     - "Labels not to keep in air mask (gas)"    int           no      multiple
+option "firstKeep2"  - "First label to keep"                     int           no      default="1"
+option "lastKeep2"   - "Last label to keep"                      int           no      
+
+section "Step 4 : remove trachea"
+
+option "radius"      -  "Radius for dilation"                     int           no      default="1"
+option "remove3"     - "Labels not to keep in lungs mask (trachea)"    int             no      multiple
+option "firstKeep3"  - "First label to keep"                     int           no      default="1"
+option "lastKeep3"   - "Last label to keep"                      int           no      default="2"
+
diff --git a/segmentation/clitkExtractLungFilter.h b/segmentation/clitkExtractLungFilter.h
new file mode 100644 (file)
index 0000000..1f6252d
--- /dev/null
@@ -0,0 +1,247 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLUNGSFILTER_H
+#define CLITKEXTRACTLUNGSFILTER_H
+
+// clitk 
+#include "clitkFilterBase.h"
+#include "clitkDecomposeAndReconstructImageFilter.h"
+#include "clitkExplosionControlledThresholdConnectedImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+
+// itk
+#include "itkStatisticsImageFilter.h"
+
+namespace clitk {
+  
+  //--------------------------------------------------------------------
+  /*
+    Try to extract the Lung part of a thorax CT. Inspired by
+    Rikxoort2009, Section IIA, MedPhys.
+
+    - First, all air besides lungs and thrachea is removed, by
+    removing the second largest label of the firstLabelImage and
+    setting the remainder to 0HU . This modified input is optimally
+    thresholded (Otsu1979).
+
+    - Trachea and bronchi are grown from seeds in the top of the image
+    by explosion controlled region growing, slightly dilated and
+    removed from the second label image.
+
+    - Left and right lung are separated (if necessary) by erosion and
+    reconstructed by conditional dilation. 
+
+    - TRACHEA is available at the end
+
+    TODO ********** Remaining holes can be       filled afterwards (clitkFillMask).
+
+  */
+  //--------------------------------------------------------------------
+  
+  template <class TInputImageType, class TMaskImageType>
+  class ITK_EXPORT ExtractLungFilter: 
+    public clitk::FilterBase, 
+    public itk::ImageToImageFilter<TInputImageType, TMaskImageType> 
+  {
+    
+  public:
+    /** Standard class typedefs. */
+    typedef itk::ImageToImageFilter<TInputImageType, TMaskImageType> Superclass;
+    typedef ExtractLungFilter              Self;
+    typedef itk::SmartPointer<Self>        Pointer;
+    typedef itk::SmartPointer<const Self>  ConstPointer;
+    
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);  
+    
+    /** Run-time type information (and related methods). */
+    itkTypeMacro(ExtractLungFilter, ImageToImageFilter);
+    FILTERBASE_INIT;
+
+    /** Some convenient typedefs */
+    typedef TInputImageType                       InputImageType;
+    typedef typename InputImageType::ConstPointer InputImageConstPointer;
+    typedef typename InputImageType::Pointer      InputImagePointer;
+    typedef typename InputImageType::RegionType   InputImageRegionType; 
+    typedef typename InputImageType::PixelType    InputImagePixelType; 
+    typedef typename InputImageType::SizeType     InputImageSizeType; 
+    typedef typename InputImageType::IndexType    InputImageIndexType; 
+        
+    typedef TMaskImageType                       MaskImageType;
+    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;
+    typedef itk::Image<InternalPixelType, InputImageType::ImageDimension> InternalImageType;
+    typedef typename InternalImageType::Pointer                           InternalImagePointer;
+    typedef typename InternalImageType::IndexType                         InternalIndexType;
+    typedef LabelizeParameters<InternalPixelType>                         LabelParamType;
+    
+    /** Connect inputs */
+    void SetInput(const InputImageType * image);
+    void SetInputPatientMask(MaskImageType * mask, MaskImagePixelType BG);
+    itkSetMacro(PatientMaskBackgroundValue, MaskImagePixelType);
+    itkGetConstMacro(PatientMaskBackgroundValue, MaskImagePixelType);
+    GGO_DefineOption(patientBG, SetPatientMaskBackgroundValue, MaskImagePixelType);
+
+    // Set all options at a time
+    template<class ArgsInfoType>
+      void SetArgsInfo(ArgsInfoType arg);
+
+    // Get output (only availabe after update !)
+    typename MaskImageType::Pointer GetTracheaImage() { return trachea; }
+
+    // Background / Foreground
+    itkGetConstMacro(BackgroundValue, MaskImagePixelType);
+    itkGetConstMacro(ForegroundValue, MaskImagePixelType);
+
+    // For common segmentation processes
+    itkSetMacro(MinimalComponentSize, int);
+    itkGetConstMacro(MinimalComponentSize, int);
+    GGO_DefineOption(minSize, SetMinimalComponentSize, int);
+
+    // Step 1 options RemoveAir
+    itkSetMacro(UpperThreshold, InputImagePixelType);
+    itkGetConstMacro(UpperThreshold, InputImagePixelType);
+    GGO_DefineOption(upper, SetUpperThreshold, InputImagePixelType);
+
+    itkSetMacro(LowerThreshold, InputImagePixelType);
+    itkGetConstMacro(LowerThreshold, InputImagePixelType);
+    itkSetMacro(UseLowerThreshold, bool);
+    itkGetConstMacro(UseLowerThreshold, bool);
+    itkBooleanMacro(UseLowerThreshold);
+    GGO_DefineOption_WithTest(lower, SetLowerThreshold, InputImagePixelType, UseLowerThreshold);
+
+    void SetLabelizeParameters1(LabelParamType * a) { m_LabelizeParameters1 = a; }
+    itkGetConstMacro(LabelizeParameters1, LabelParamType*);
+    GGO_DefineOption_LabelParam(1, SetLabelizeParameters1, LabelParamType);
+
+    // Step 2 options FindTrachea
+    itkSetMacro(UpperThresholdForTrachea, InputImagePixelType);
+    itkGetConstMacro(UpperThresholdForTrachea, InputImagePixelType);
+    GGO_DefineOption(upperThresholdForTrachea, SetUpperThresholdForTrachea, InputImagePixelType);
+
+    itkSetMacro(MultiplierForTrachea, double);
+    itkGetConstMacro(MultiplierForTrachea, double);
+    GGO_DefineOption(multiplierForTrachea, SetMultiplierForTrachea, double);
+
+    itkSetMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
+    itkGetConstMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
+    GGO_DefineOption(thresholdStepSizeForTrachea, SetThresholdStepSizeForTrachea, InputImagePixelType);
+
+    void AddSeed(InternalIndexType s);
+    std::vector<InternalIndexType> & GetSeeds() { return  m_Seeds; }
+    GGO_DefineOption_Vector(seed, AddSeed, InternalIndexType, InputImageType::ImageDimension, true);
+
+    // Step 3 options ExtractLung
+    itkSetMacro(NumberOfHistogramBins, int);
+    itkGetConstMacro(NumberOfHistogramBins, int);
+    GGO_DefineOption(bins, SetNumberOfHistogramBins, int);
+
+    void SetLabelizeParameters2(LabelParamType* a) { m_LabelizeParameters2 = a; }
+    itkGetConstMacro(LabelizeParameters2, LabelParamType*);
+    GGO_DefineOption_LabelParam(2, SetLabelizeParameters2, LabelParamType);
+
+    // Step 4 options RemoveTrachea
+    itkSetMacro(RadiusForTrachea, int);
+    itkGetConstMacro(RadiusForTrachea, int);
+    GGO_DefineOption(radius, SetRadiusForTrachea, int);
+    
+    void SetLabelizeParameters3(LabelParamType * a) { m_LabelizeParameters3 = a; }
+    itkGetConstMacro(LabelizeParameters3, LabelParamType*);
+    GGO_DefineOption_LabelParam(3, SetLabelizeParameters3, LabelParamType);
+
+    // Step 5 options LungSeparation
+    //     itkSetMacro(FinalOpenClose, bool);
+    //     itkGetConstMacro(FinalOpenClose, bool);
+    //     itkBooleanMacro(FinalOpenClose);
+
+ //    virtual void Update();
+
+  protected:
+    ExtractLungFilter();
+    virtual ~ExtractLungFilter() {}
+    
+    // Global options
+    itkSetMacro(BackgroundValue, MaskImagePixelType);
+    itkSetMacro(ForegroundValue, MaskImagePixelType);
+    MaskImagePixelType m_PatientMaskBackgroundValue;
+    MaskImagePixelType m_BackgroundValue;
+    MaskImagePixelType m_ForegroundValue;
+    int m_MinimalComponentSize;
+
+    // Step 1
+    InputImagePixelType m_UpperThreshold;
+    InputImagePixelType m_LowerThreshold;
+    bool m_UseLowerThreshold;
+    LabelParamType* m_LabelizeParameters1;
+
+    // Step 2
+    InputImagePixelType m_UpperThresholdForTrachea;
+    InputImagePixelType m_ThresholdStepSizeForTrachea;
+    double m_MultiplierForTrachea;
+    std::vector<InternalIndexType> m_Seeds;
+
+    // Step 3
+    int m_NumberOfHistogramBins;
+    LabelParamType* m_LabelizeParameters2;
+
+    // Step 4
+    int m_RadiusForTrachea;
+    LabelParamType* m_LabelizeParameters3;
+
+    // Step 5
+    //     bool m_FinalOpenClose;
+    
+    virtual void GenerateOutputInformation();
+    virtual void GenerateData();
+
+    // Steps
+    void RemoveAir();
+    void FindTrachea();
+    void ExtractLung();
+    void RemoveTrachea();
+    void LungSeparation();
+    InputImageConstPointer input;
+    MaskImageConstPointer patient;
+    InputImagePointer working_input;
+    typename InternalImageType::Pointer working_image;  
+    typename InternalImageType::Pointer trachea_tmp;
+    MaskImagePointer trachea;
+        
+  private:
+    ExtractLungFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractLungFilter.txx"
+#endif
+
+#endif
diff --git a/segmentation/clitkExtractLungFilter.txx b/segmentation/clitkExtractLungFilter.txx
new file mode 100644 (file)
index 0000000..2c7be4c
--- /dev/null
@@ -0,0 +1,439 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - 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
+
+// clitk
+#include "clitkImageCommon.h"
+#include "clitkSetBackgroundImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+#include "clitkAutoCropFilter.h"
+
+// itk
+#include "itkBinaryThresholdImageFilter.h"
+#include "itkConnectedComponentImageFilter.h"
+#include "itkRelabelComponentImageFilter.h"
+#include "itkOtsuThresholdImageFilter.h"
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+ExtractLungFilter():
+  clitk::FilterBase(),
+  itk::ImageToImageFilter<TInputImageType, TMaskImageType>()
+{
+  // Default global options
+  this->SetNumberOfRequiredInputs(2);
+  SetPatientMaskBackgroundValue(0);
+  SetBackgroundValue(0); // Must be zero
+  SetForegroundValue(1);
+
+  // Step 1 default values
+  SetUpperThreshold(-300);
+  SetLowerThreshold(-1000);
+  UseLowerThresholdOff();
+  LabelParamType * p1 = new LabelParamType;
+  p1->SetFirstKeep(1);
+  p1->UseLastKeepOff();
+  p1->AddLabelToRemove(2);
+  SetLabelizeParameters1(p1);
+
+  // Step 2 default values
+  SetUpperThresholdForTrachea(-900);
+  SetMultiplierForTrachea(5);
+  SetThresholdStepSizeForTrachea(64);
+  
+  // Step 3 default values
+  SetNumberOfHistogramBins(500);
+  LabelParamType * p2 = new LabelParamType;
+  p2->SetFirstKeep(1);
+  p2->UseLastKeepOff();
+  // p->AddLabelToRemove(2); // No label to remove by default
+  SetLabelizeParameters2(p2);
+
+  // Step 4 default values
+  SetRadiusForTrachea(1);
+  LabelParamType * p3 = new LabelParamType;
+  p3->SetFirstKeep(1);
+  p3->SetLastKeep(2);
+  p3->UseLastKeepOff();
+  SetLabelizeParameters3(p3);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+void 
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+SetInput(const TInputImageType * image) 
+{
+  this->SetNthInput(0, const_cast<TInputImageType *>(image));
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+void 
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+SetInputPatientMask(TMaskImageType * image, MaskImagePixelType bg ) 
+{
+  this->SetNthInput(1, const_cast<TMaskImageType *>(image));
+  SetPatientMaskBackgroundValue(bg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+void 
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+AddSeed(InternalIndexType s) 
+{ 
+  m_Seeds.push_back(s);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+template<class ArgsInfoType>
+void 
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+SetArgsInfo(ArgsInfoType mArgsInfo)
+{
+  SetVerboseOption_GGO(mArgsInfo);
+  SetVerboseStep_GGO(mArgsInfo);
+  SetWriteStep_GGO(mArgsInfo);
+  SetVerboseWarningOff_GGO(mArgsInfo);
+
+  SetUpperThreshold_GGO(mArgsInfo);
+  SetLowerThreshold_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);
+
+  SetNumberOfHistogramBins_GGO(mArgsInfo);
+  SetLabelizeParameters2_GGO(mArgsInfo);
+
+  SetRadiusForTrachea_GGO(mArgsInfo);
+  SetLabelizeParameters3_GGO(mArgsInfo);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+void 
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+GenerateOutputInformation() 
+{ 
+  input   = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
+  Superclass::GenerateOutputInformation();
+//   MaskImagePointer output = this->GetOutput(0);
+
+  // Get input pointers
+  input   = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
+  patient = dynamic_cast<const TMaskImageType*>(itk::ProcessObject::GetInput(1));
+
+  // Check image
+  if (!HasSameSizeAndSpacing<TInputImageType, TMaskImageType>(input, patient)) {
+    this->SetLastError("* ERROR * the images (input and patient mask) must have the same size & spacing");
+    return;
+  }
+  
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Set background to initial image");
+  working_input = SetBackground<TInputImageType, TMaskImageType>
+    (input, patient, GetPatientMaskBackgroundValue(), -1000);
+  StopCurrentStep<InputImageType>(working_input);
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Remove Air");
+  // Threshold to get air
+  typedef itk::BinaryThresholdImageFilter<InputImageType, InternalImageType> InputBinarizeFilterType; 
+  typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New();
+  binarizeFilter->SetInput(working_input);
+  if (m_UseLowerThreshold) binarizeFilter->SetLowerThreshold(m_LowerThreshold);
+  binarizeFilter->SetUpperThreshold(m_UpperThreshold);
+  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_image = RemoveLabels<InternalImageType>
+    (working_image, GetBackgroundValue(), GetLabelizeParameters1()->GetLabelsToRemove());
+  typename InternalImageType::Pointer air = KeepLabels<InternalImageType>
+    (working_image, 
+     GetBackgroundValue(), 
+     GetForegroundValue(), 
+     GetLabelizeParameters1()->GetFirstKeep(), 
+     GetLabelizeParameters1()->GetLastKeep(), 
+     GetLabelizeParameters1()->GetUseLastKeep());
+  // Set Air to BG
+  working_input = SetBackground<TInputImageType, InternalImageType>
+    (working_input, air, this->GetForegroundValue(), this->GetBackgroundValue());
+
+  // End
+  StopCurrentStep<InputImageType>(working_input);
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Find the trachea");
+  if (m_Seeds.size() == 0) { // try to find seed
+    // Search seed (parameters = UpperThresholdForTrachea)
+    static const unsigned int Dim = InputImageType::ImageDimension;
+    typename InternalImageType::RegionType sliceRegion = working_input->GetLargestPossibleRegion();
+    typename InternalImageType::SizeType sliceRegionSize = sliceRegion.GetSize();
+    typename InternalImageType::IndexType sliceRegionIndex = sliceRegion.GetIndex();
+    sliceRegionIndex[Dim-1]=sliceRegionSize[Dim-1]-5;
+    sliceRegionSize[Dim-1]=5;
+    sliceRegion.SetSize(sliceRegionSize);
+    sliceRegion.SetIndex(sliceRegionIndex);
+    
+    typedef  itk::ImageRegionConstIterator<InputImageType> IteratorType;
+    IteratorType it(working_input, sliceRegion);
+    it.GoToBegin();
+    while (!it.IsAtEnd()) {
+      if(it.Get() < GetUpperThresholdForTrachea() ) {
+        AddSeed(it.GetIndex());
+      }
+      ++it;
+    }
+  }
+  
+  if (m_Seeds.size() != 0) {
+    // Explosion controlled region growing
+    typedef clitk::ExplosionControlledThresholdConnectedImageFilter<InputImageType, InternalImageType> 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->SetAdaptLowerBorder(false);
+    f->SetAdaptUpperBorder(true);
+    f->SetMinimumSize(5000); 
+    f->SetReplaceValue(1);
+    f->SetMultiplier(GetMultiplierForTrachea());
+    f->SetThresholdStepSize(GetThresholdStepSizeForTrachea());
+    f->SetMinimumThresholdStepSize(1);
+    for(unsigned int i=0; i<m_Seeds.size();i++) {
+      //    std::cout<<"Adding seed " <<m_Seeds[i]<<"..."<<std::endl;
+      f->AddSeed(m_Seeds[i]);
+    }  
+    f->Update();
+    trachea_tmp = f->GetOutput();
+    // Set output
+    StopCurrentStep<InternalImageType>(trachea_tmp);
+
+  }
+  else { // Trachea not found
+    this->SetWarning("* WARNING * No seed found for trachea.");
+    // Set output
+    StopCurrentStep();
+  }
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Extract the lung with Otsu filter");
+  // Automated Otsu thresholding and relabeling
+  typedef itk::OtsuThresholdImageFilter<InputImageType,InternalImageType> 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();
+
+  // Set output
+  StopCurrentStep<InternalImageType>(working_image);
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Select labels");
+  // Keep right labels
+  working_image = LabelizeAndSelectLabels<InternalImageType>
+    (working_image, 
+     GetBackgroundValue(), 
+     GetForegroundValue(), 
+     false, 
+     GetMinimalComponentSize(), 
+     GetLabelizeParameters2());
+
+  // Set output
+  StopCurrentStep<InternalImageType>(working_image);
+  
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  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);
+  
+   // Dilate the trachea 
+    static const unsigned int Dim = InputImageType::ImageDimension;
+    typedef itk::BinaryBallStructuringElement<InternalPixelType, Dim> KernelType;
+    KernelType structuringElement;
+    structuringElement.SetRadius(GetRadiusForTrachea());
+    structuringElement.CreateStructuringElement();
+    typedef clitk::ConditionalBinaryDilateImageFilter<InternalImageType, InternalImageType, 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->Update();
+    working_image = dilateFilter->GetOutput();  
+    
+    // Set trachea with dilatation
+    trachea_tmp = SetBackground<InternalImageType, InternalImageType>
+      (trachea_tmp, working_image, -1, this->GetForegroundValue()); 
+
+    // Remove the trachea
+    working_image = SetBackground<InternalImageType, InternalImageType>
+      (working_image, working_image, -1, this->GetBackgroundValue());  
+    
+    // Label
+    working_image = LabelizeAndSelectLabels<InternalImageType>
+      (working_image, 
+       GetBackgroundValue(), 
+       GetForegroundValue(), 
+       false, 
+       GetMinimalComponentSize(), 
+       GetLabelizeParameters3());
+    
+    // Set output
+    StopCurrentStep<InternalImageType>(working_image);
+  }
+  
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  typedef clitk::AutoCropFilter<InternalImageType> CropFilterType;
+  typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+  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();
+    StopCurrentStep<MaskImageType>(trachea);  
+  }
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Croping lung");
+  cropFilter = CropFilterType::New(); // Needed to reset pipeline
+  cropFilter->SetInput(working_image);
+  cropFilter->Update();   
+  working_image = cropFilter->GetOutput();
+  StopCurrentStep<InternalImageType>(working_image);
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Separate Left/Right lungs");
+  // Initial label
+  working_image = Labelize<InternalImageType>(working_image, 
+                                              GetBackgroundValue(), 
+                                              false, 
+                                              GetMinimalComponentSize());
+
+  // Count the labels
+  typedef itk::StatisticsImageFilter<InternalImageType> StatisticsImageFilterType;
+  typename StatisticsImageFilterType::Pointer statisticsImageFilter=StatisticsImageFilterType::New();
+  statisticsImageFilter->SetInput(working_image);
+  statisticsImageFilter->Update();
+  unsigned int initialNumberOfLabels = statisticsImageFilter->GetMaximum();
+  working_image = statisticsImageFilter->GetOutput();  
+  // Decompose the first label
+  static const unsigned int Dim = InputImageType::ImageDimension;
+  if (initialNumberOfLabels<2) {
+    // Structuring element radius
+    typename InputImageType::SizeType radius;
+    for (unsigned int i=0;i<Dim;i++) radius[i]=1;
+    typedef clitk::DecomposeAndReconstructImageFilter<InternalImageType,InternalImageType> DecomposeAndReconstructFilterType;
+    typename DecomposeAndReconstructFilterType::Pointer decomposeAndReconstructFilter=DecomposeAndReconstructFilterType::New();
+    decomposeAndReconstructFilter->SetInput(working_image);
+    decomposeAndReconstructFilter->SetVerbose(false);
+    decomposeAndReconstructFilter->SetRadius(radius);
+    decomposeAndReconstructFilter->SetMaximumNumberOfLabels(2);
+    decomposeAndReconstructFilter->SetMinimumObjectSize(this->GetMinimalComponentSize());
+    decomposeAndReconstructFilter->SetMinimumNumberOfIterations(1);
+    decomposeAndReconstructFilter->SetBackgroundValue(this->GetBackgroundValue());
+    decomposeAndReconstructFilter->SetForegroundValue(this->GetForegroundValue());
+    decomposeAndReconstructFilter->SetFullyConnected(true);
+    decomposeAndReconstructFilter->SetNumberOfNewLabels(1);
+    decomposeAndReconstructFilter->Update();
+    working_image = decomposeAndReconstructFilter->GetOutput();      
+  }
+
+  // Retain labels (lungs)
+  typedef itk::ThresholdImageFilter<InternalImageType> ThresholdImageFilterType;
+  typename ThresholdImageFilterType::Pointer thresholdFilter = ThresholdImageFilterType::New();
+  thresholdFilter->SetInput(working_image);
+  thresholdFilter->ThresholdAbove(2);
+  thresholdFilter->SetOutsideValue(this->GetBackgroundValue());
+  thresholdFilter->Update();
+  working_image = thresholdFilter->GetOutput();
+  StopCurrentStep<InternalImageType> (working_image);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+void 
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+GenerateData() {
+  // Final Cast 
+  typedef itk::CastImageFilter<InternalImageType, MaskImageType> CastImageFilterType;
+  typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
+  caster->SetInput(working_image);
+  caster->Update();
+  // Set output
+  //this->SetNthOutput(0, caster->GetOutput()); // -> no because redo filter otherwise
+  this->GraftOutput(caster->GetOutput());
+  return;
+}
+//--------------------------------------------------------------------
+
+  
+#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
diff --git a/segmentation/clitkExtractLungGenericFilter.h b/segmentation/clitkExtractLungGenericFilter.h
new file mode 100644 (file)
index 0000000..7d6306b
--- /dev/null
@@ -0,0 +1,70 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKEXTRACTLUNGSGENERICFILTER_H
+#define CLITKEXTRACTLUNGSGENERICFILTER_H
+
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkExtractLungFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk 
+{
+  
+  template<class ArgsInfoType>
+  class ITK_EXPORT ExtractLungGenericFilter: 
+    public ImageToImageGenericFilter<ExtractLungGenericFilter<ArgsInfoType> >
+  {
+    
+  public:
+    //--------------------------------------------------------------------
+    ExtractLungGenericFilter();
+
+    //--------------------------------------------------------------------
+    typedef ExtractLungGenericFilter      Self;
+    typedef ImageToImageGenericFilter<ExtractLungGenericFilter<ArgsInfoType> > Superclass;
+    typedef itk::SmartPointer<Self>       Pointer;
+    typedef itk::SmartPointer<const Self> ConstPointer;
+
+    //--------------------------------------------------------------------
+    itkNewMacro(Self);  
+    itkTypeMacro(ExtractLungGenericFilter, LightObject);
+
+    //--------------------------------------------------------------------
+    void SetArgsInfo(const ArgsInfoType & a);
+
+    //--------------------------------------------------------------------
+    // Main function called each time the filter is updated
+    template<class ImageType>  
+    void UpdateWithInputImageType();
+
+  protected:
+    template<unsigned int Dim> void InitializeImageType();
+    ArgsInfoType mArgsInfo;
+    
+  }; // end class
+  //--------------------------------------------------------------------
+    
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractLungGenericFilter.txx"
+#endif
+
+#endif // #define CLITKEXTRACTLUNGSGENERICFILTER_H
diff --git a/segmentation/clitkExtractLungGenericFilter.txx b/segmentation/clitkExtractLungGenericFilter.txx
new file mode 100644 (file)
index 0000000..18fc2cf
--- /dev/null
@@ -0,0 +1,105 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLUNGSGENERICFILTER_TXX
+#define CLITKEXTRACTLUNGSGENERICFILTER_TXX
+
+#include "clitkImageCommon.h"
+  
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ExtractLungGenericFilter<ArgsInfoType>::ExtractLungGenericFilter():
+  ImageToImageGenericFilter<Self>("ExtractLung") 
+{
+  // Default values
+  cmdline_parser_clitkExtractLung_init(&mArgsInfo);
+  InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ExtractLungGenericFilter<ArgsInfoType>::InitializeImageType() 
+{  
+  ADD_IMAGE_TYPE(Dim, short);
+  // ADD_IMAGE_TYPE(Dim, int);
+  // ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::ExtractLungGenericFilter<ArgsInfoType>::SetArgsInfo(const ArgsInfoType & a) 
+{
+  mArgsInfo=a;
+  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);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+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;
+  typename FilterType::Pointer filter = FilterType::New();
+    
+  // Set global Options 
+  filter->SetArgsInfo(mArgsInfo);
+  filter->SetInput(input);
+  filter->SetInputPatientMask(patient, mArgsInfo.patientBG_arg);
+
+  // Go !
+  filter->Update();
+  
+  // Check if error
+  if (filter->HasError()) {
+    SetLastError(filter->GetLastError());
+    // No output
+    return;
+  }
+
+  // Write/Save results
+  typename OutputImageType::Pointer output = filter->GetOutput();
+  this->template SetNextOutput<OutputImageType>(output); 
+  if (mArgsInfo.outputTrachea_given) 
+    this->template SetNextOutput<typename FilterType::MaskImageType>(filter->GetTracheaImage()); 
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKEXTRACTLUNGSGENERICFILTER_TXX
diff --git a/segmentation/clitkExtractLymphStations.cxx b/segmentation/clitkExtractLymphStations.cxx
new file mode 100644 (file)
index 0000000..cf392f8
--- /dev/null
@@ -0,0 +1,44 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkExtractLymphStations_ggo.h"
+#include "clitkExtractLymphStationsGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+  // Init command line
+  GGO(clitkExtractLymphStations, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::ExtractLymphStationsGenericFilter<args_info_clitkExtractLymphStations> FilterType;
+  FilterType::Pointer filter = FilterType::New();
+
+  filter->SetArgsInfo(args_info);
+  filter->Update();
+
+  if (filter->HasError()) {
+    std::cout << filter->GetLastError() << std::endl;
+  }
+
+  return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
diff --git a/segmentation/clitkExtractLymphStations.ggo b/segmentation/clitkExtractLymphStations.ggo
new file mode 100644 (file)
index 0000000..78efb35
--- /dev/null
@@ -0,0 +1,27 @@
+#File clitkExtractLymphStations.ggo
+package "clitkExtractLymphStations"
+version "1.0"
+purpose "Extract LymphStations with help of TODO"
+
+option "config"                -  "Config file"                  string        no
+option "imagetypes"     -  "Display allowed image types"  flag          off
+option "verbose"        v  "Verbose"                     flag          off
+option "verboseStep"    -  "Verbose each step"           flag          off
+option "writeStep"      w  "Write image at each step"    flag          off
+option "verboseOption"  -  "Display options values"       flag          off
+option "verboseWarningOff" -  "Do not display warning"    flag          off
+
+section "I/O"
+
+option "mediastinum"   m       "Input mediastinum mask filename" string        yes
+option "trachea"       t       "Input trachea mask filename"     string        yes
+option "output"        o       "Output lungs mask filename"      string        yes
+
+option "carenaZposition"               c       "Sup-Inf position of the carena (in mm)" double no
+option "middleLobeBronchusZposition"           b       "Sup-Inf position of the middle lobe bronchus (in mm)" double no
+option "spacing"     - "Intermediate resampling spacing"         double no default="6"
+option "fuzzy1"             -  "Fuzzy relative position threshold"       double no default="0.6"
+
+
+
+
diff --git a/segmentation/clitkExtractLymphStationsFilter.h b/segmentation/clitkExtractLymphStationsFilter.h
new file mode 100644 (file)
index 0000000..e90abd4
--- /dev/null
@@ -0,0 +1,147 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLYMPHSTATIONSFILTER_H
+#define CLITKEXTRACTLYMPHSTATIONSFILTER_H
+
+#include "clitkFilterBase.h"
+
+namespace clitk {
+  
+  //--------------------------------------------------------------------
+  /*
+    Try to extract the LymphStations part of a thorax CT.
+    Inputs : 
+    - Patient label image
+    - Lungs label image
+    - Bones label image
+  */
+  //--------------------------------------------------------------------
+  
+  template <class TImageType>
+  class ITK_EXPORT ExtractLymphStationsFilter: 
+    public clitk::FilterBase, 
+    public itk::ImageToImageFilter<TImageType, TImageType> 
+  {
+
+  public:
+    /** Standard class typedefs. */
+    typedef itk::ImageToImageFilter<TImageType, TImageType> Superclass;
+    typedef ExtractLymphStationsFilter            Self;
+    typedef itk::SmartPointer<Self>             Pointer;
+    typedef itk::SmartPointer<const Self>       ConstPointer;
+    
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);
+    
+    /** Run-time type information (and related methods). */
+    itkTypeMacro(ExtractLymphStationsFilter, InPlaceImageFilter);
+    FILTERBASE_INIT;
+
+    /** Some convenient typedefs. */
+    typedef TImageType                       ImageType;
+    typedef typename ImageType::ConstPointer ImageConstPointer;
+    typedef typename ImageType::Pointer      ImagePointer;
+    typedef typename ImageType::RegionType   ImageRegionType; 
+    typedef typename ImageType::PixelType    ImagePixelType; 
+    typedef typename ImageType::SizeType     ImageSizeType; 
+    typedef typename ImageType::IndexType    ImageIndexType; 
+        
+    /** Connect inputs */
+    void SetInputMediastinumLabelImage(const TImageType * image, ImagePixelType bg=0);
+    void SetInputTracheaLabelImage(const TImageType * image, ImagePixelType bg=0);
+  
+    /** ImageDimension constants */
+    itkStaticConstMacro(ImageDimension, unsigned int, TImageType::ImageDimension);
+
+    // Set all options at a time
+    template<class ArgsInfoType>
+      void SetArgsInfo(ArgsInfoType arg);
+   
+    // Background / Foreground
+    itkSetMacro(BackgroundValueMediastinum, ImagePixelType);
+    itkGetConstMacro(BackgroundValueMediastinum, ImagePixelType);
+    //GGO_DefineOption(MediastinumBG, SetBackgroundValueMediastinum, ImagePixelType);
+    
+    itkSetMacro(BackgroundValueTrachea, ImagePixelType);
+    itkGetConstMacro(BackgroundValueTrachea, ImagePixelType);
+    //GGO_DefineOption(TracheaBG, SetBackgroundValueTrachea, ImagePixelType);
+
+    itkGetConstMacro(BackgroundValue, ImagePixelType);
+    itkGetConstMacro(ForegroundValue, ImagePixelType);
+
+    itkSetMacro(CarenaZPositionInMM, double);
+    itkGetConstMacro(CarenaZPositionInMM, double);
+    GGO_DefineOption(carenaZposition, SetCarenaZPositionInMM, double);
+
+    itkSetMacro(MiddleLobeBronchusZPositionInMM, double);
+    itkGetConstMacro(MiddleLobeBronchusZPositionInMM, double);
+    GGO_DefineOption(middleLobeBronchusZposition, SetMiddleLobeBronchusZPositionInMM, double);
+
+    itkSetMacro(IntermediateSpacing, double);
+    itkGetConstMacro(IntermediateSpacing, double);
+    GGO_DefineOption(spacing, SetIntermediateSpacing, double);
+
+    itkSetMacro(FuzzyThreshold1, double);
+    itkGetConstMacro(FuzzyThreshold1, double);
+    GGO_DefineOption(fuzzy1, SetFuzzyThreshold1, double);
+
+
+
+  protected:
+    ExtractLymphStationsFilter();
+    virtual ~ExtractLymphStationsFilter() {}
+    
+    virtual void GenerateOutputInformation();
+    virtual void GenerateInputRequestedRegion();
+    virtual void GenerateData();
+       
+    itkSetMacro(BackgroundValue, ImagePixelType);
+    itkSetMacro(ForegroundValue, ImagePixelType);
+    
+    ImageConstPointer m_mediastinum;
+    ImageConstPointer m_trachea;
+    ImagePointer m_working_image;
+    ImagePointer m_working_trachea;  
+    ImagePointer m_output;  
+    
+    ImagePixelType m_BackgroundValueMediastinum;
+    ImagePixelType m_BackgroundValueTrachea;
+    ImagePixelType m_BackgroundValue;
+    ImagePixelType m_ForegroundValue;
+    
+    double m_CarenaZPositionInMM;
+    double m_MiddleLobeBronchusZPositionInMM; 
+    double m_IntermediateSpacing;
+    double m_FuzzyThreshold1;
+    
+  private:
+    ExtractLymphStationsFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractLymphStationsFilter.txx"
+#endif
+
+#endif
diff --git a/segmentation/clitkExtractLymphStationsFilter.txx b/segmentation/clitkExtractLymphStationsFilter.txx
new file mode 100644 (file)
index 0000000..0bcb447
--- /dev/null
@@ -0,0 +1,286 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLYMPHSTATIONSFILTER_TXX
+#define CLITKEXTRACTLYMPHSTATIONSFILTER_TXX
+
+// clitk
+#include "clitkCommon.h"
+#include "clitkExtractLymphStationsFilter.h"
+#include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+#include "clitkAutoCropFilter.h"
+#include "clitkSegmentationFunctions.h"
+
+// itk
+#include <deque>
+#include <itkStatisticsLabelMapFilter.h>
+#include <itkLabelImageToStatisticsLabelMapFilter.h>
+#include <itkRegionOfInterestImageFilter.h>
+#include <itkBinaryThresholdImageFilter.h>
+#include <itkImageSliceConstIteratorWithIndex.h>
+
+// itk ENST
+#include "RelativePositionPropImageFilter.h"
+
+//--------------------------------------------------------------------
+template <class TImageType>
+clitk::ExtractLymphStationsFilter<TImageType>::
+ExtractLymphStationsFilter():
+  clitk::FilterBase(),
+  itk::ImageToImageFilter<TImageType, TImageType>()
+{
+  this->SetNumberOfRequiredInputs(1);
+  SetBackgroundValueMediastinum(0);
+  SetBackgroundValueTrachea(0);
+  SetBackgroundValue(0);
+  SetForegroundValue(1);
+
+  SetIntermediateSpacing(6);
+  SetFuzzyThreshold1(0.6);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+SetInputMediastinumLabelImage(const TImageType * image, ImagePixelType bg) {
+  this->SetNthInput(0, const_cast<TImageType *>(image));
+  m_BackgroundValueMediastinum = bg;
+  SetCarenaZPositionInMM(image->GetOrigin()[2]+image->GetLargestPossibleRegion().GetSize()[2]*image->GetSpacing()[2]);
+  SetMiddleLobeBronchusZPositionInMM(image->GetOrigin()[2]);
+  // DD(m_CarenaZPositionInMM);
+//   DD(m_MiddleLobeBronchusZPositionInMM);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+SetInputTracheaLabelImage(const TImageType * image, ImagePixelType bg) {
+  this->SetNthInput(1, const_cast<TImageType *>(image));
+  m_BackgroundValueTrachea = bg;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+template<class ArgsInfoType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+SetArgsInfo(ArgsInfoType mArgsInfo)
+{
+  SetVerboseOption_GGO(mArgsInfo);
+  SetVerboseStep_GGO(mArgsInfo);
+  SetWriteStep_GGO(mArgsInfo);
+  SetVerboseWarningOff_GGO(mArgsInfo);
+  SetCarenaZPositionInMM_GGO(mArgsInfo);
+  SetMiddleLobeBronchusZPositionInMM_GGO(mArgsInfo);
+  SetIntermediateSpacing_GGO(mArgsInfo);
+  SetFuzzyThreshold1_GGO(mArgsInfo);
+  //SetBackgroundValueMediastinum_GGO(mArgsInfo);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+GenerateOutputInformation() { 
+  //  Superclass::GenerateOutputInformation();
+  
+  // Get input
+  m_mediastinum = dynamic_cast<const TImageType*>(itk::ProcessObject::GetInput(0));
+  m_trachea = dynamic_cast<const TImageType*>(itk::ProcessObject::GetInput(1));
+    
+  // ----------------------------------------------------------------
+  // ----------------------------------------------------------------
+  // Superior limit = carena
+  // Inferior limit = origine middle lobe bronchus
+  StartNewStep("Inf/Sup limits with carena/bronchus");
+  ImageRegionType region = m_mediastinum->GetLargestPossibleRegion(); DD(region);
+  ImageSizeType size = region.GetSize();
+  ImageIndexType index = region.GetIndex();
+  DD(m_CarenaZPositionInMM);
+  DD(m_MiddleLobeBronchusZPositionInMM);
+  index[2] = floor((m_MiddleLobeBronchusZPositionInMM - m_mediastinum->GetOrigin()[2]) / m_mediastinum->GetSpacing()[2]);
+  size[2] = ceil((m_CarenaZPositionInMM-m_MiddleLobeBronchusZPositionInMM) / m_mediastinum->GetSpacing()[2]);
+  region.SetSize(size);
+  region.SetIndex(index);
+  DD(region);
+  typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> CropFilterType;
+  typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+  cropFilter->SetInput(m_mediastinum);
+  cropFilter->SetRegionOfInterest(region);
+  cropFilter->Update();
+  m_working_image = cropFilter->GetOutput();
+  // Auto Crop (because following rel pos is faster)
+  m_working_image = clitk::AutoCrop<ImageType>(m_working_image, 0); 
+  StopCurrentStep<ImageType>(m_working_image);
+  m_output = m_working_image;
+
+  // ----------------------------------------------------------------
+  // ----------------------------------------------------------------
+  // Separate trachea in two CCL
+  StartNewStep("Separate trachea");
+  // DD(region);
+  ImageRegionType trachea_region = m_trachea->GetLargestPossibleRegion();
+  for(int i=0; i<3; i++) {
+    index[i] = floor(((index[i]*m_mediastinum->GetSpacing()[i])+m_mediastinum->GetOrigin()[i]
+                      -m_trachea->GetOrigin()[i])/m_trachea->GetSpacing()[i]);
+    // DD(index[i]);
+    size[i] = ceil((size[i]*m_mediastinum->GetSpacing()[i])/m_trachea->GetSpacing()[i]);
+    //  DD(size[i]);
+    if (index[i] < 0) { 
+      size[i] += index[i];
+      index[i] = 0;       
+    }
+    if (size[i]+index[i] > (trachea_region.GetSize()[i] + trachea_region.GetIndex()[i])) {
+      size[i] = trachea_region.GetSize()[i] + trachea_region.GetIndex()[i] - index[i];
+    }
+  }
+  // DD(index);
+  //   DD(size);
+  region.SetIndex(index);
+  region.SetSize(size);  
+  //  typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> CropFilterType;
+  //  typename CropFilterType::Pointer 
+  cropFilter = CropFilterType::New();
+ //  m_trachea.Print(std::cout);
+  cropFilter->SetInput(m_trachea);
+  cropFilter->SetRegionOfInterest(region);
+  cropFilter->Update();
+  m_working_trachea = cropFilter->GetOutput();
+
+  // Labelize and consider two main labels
+  m_working_trachea = Labelize<ImageType>(m_working_trachea, 0, true, 1);
+  StopCurrentStep<ImageType>(m_working_trachea);
+  
+  // Detect wich label is at Left
+  typedef itk::ImageSliceConstIteratorWithIndex<ImageType> SliceIteratorType;
+  SliceIteratorType iter(m_working_trachea, m_working_trachea->GetLargestPossibleRegion());
+  iter.SetFirstDirection(0);
+  iter.SetSecondDirection(1);
+  iter.GoToBegin();
+  bool stop = false;
+  ImagePixelType leftLabel;
+  while (!stop) {
+    if (iter.Get() != m_BackgroundValueTrachea) {
+      //     DD(iter.GetIndex());
+      //       DD((int)iter.Get());
+      leftLabel = iter.Get();
+      stop = true;
+    }
+    ++iter;
+  }
+  DD((int)leftLabel);
+  
+  // Relative position 
+  StartNewStep("Left/Right limits with trachea");
+
+  // Select LeftLabel (set label 1 to 0)
+  ImagePointer temp = SetBackground<ImageType, ImageType>(m_working_trachea, m_working_trachea, 1, 0);
+  writeImage<ImageType>(temp, "temp1.mhd");
+
+  // Left relative position
+  typedef clitk::AddRelativePositionConstraintToLabelImageFilter<TImageType> RelPosFilterType;
+  typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
+  relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+  relPosFilter->VerboseStepOff();
+  relPosFilter->WriteStepOff();
+  relPosFilter->SetInput(m_working_image); 
+  relPosFilter->SetInputObject(temp); 
+  relPosFilter->SetOrientationType(RelPosFilterType::RightTo);
+  relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+  relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
+  relPosFilter->Update();
+  m_working_image = relPosFilter->GetOutput();
+
+  // Select RightLabel (set label 2 to 0)
+  temp = SetBackground<ImageType, ImageType>(m_working_trachea, m_working_trachea, 2, 0);
+  writeImage<ImageType>(temp, "temp2.mhd");
+
+  // Left relative position
+  relPosFilter = RelPosFilterType::New();
+  relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+  relPosFilter->VerboseStepOn();
+  relPosFilter->WriteStepOn();
+  relPosFilter->SetInput(m_working_image); 
+  relPosFilter->SetInputObject(temp); 
+  relPosFilter->SetOrientationType(RelPosFilterType::LeftTo);
+  relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+  relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
+  relPosFilter->Update();
+  m_working_image = relPosFilter->GetOutput();
+
+
+  //-----------------------------------------------------
+  //  StartNewStep("Left/Right limits with trachea (slice by slice");
+  //  typedef SliceBySliceImageFilter<ImageType, ImageType, 
+
+  
+  DD("end");
+  m_output = m_working_image;
+  StopCurrentStep<ImageType>(m_output);
+
+  // Set output image information (required)
+  ImagePointer outputImage = this->GetOutput(0);
+  outputImage->SetRegions(m_working_image->GetLargestPossibleRegion());
+  outputImage->SetOrigin(m_working_image->GetOrigin());
+  outputImage->SetRequestedRegion(m_working_image->GetLargestPossibleRegion());
+  DD("end2");
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+GenerateInputRequestedRegion() {
+  DD("GenerateInputRequestedRegion");
+  // Call default
+  Superclass::GenerateInputRequestedRegion();
+  // Following needed because output region can be greater than input (trachea)
+  ImagePointer mediastinum = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(0));
+  ImagePointer trachea = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(1));
+  mediastinum->SetRequestedRegion(mediastinum->GetLargestPossibleRegion());
+  trachea->SetRequestedRegion(trachea->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+GenerateData() {
+  DD("GenerateData");
+  // Final Step -> graft output (if SetNthOutput => redo)
+  this->GraftOutput(m_output);
+}
+//--------------------------------------------------------------------
+  
+
+#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
diff --git a/segmentation/clitkExtractLymphStationsGenericFilter.h b/segmentation/clitkExtractLymphStationsGenericFilter.h
new file mode 100644 (file)
index 0000000..fa2d18c
--- /dev/null
@@ -0,0 +1,70 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_H
+#define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_H
+
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkExtractLymphStationsFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk 
+{
+  
+  template<class ArgsInfoType>
+  class ITK_EXPORT ExtractLymphStationsGenericFilter: 
+    public ImageToImageGenericFilter<ExtractLymphStationsGenericFilter<ArgsInfoType> >
+  {
+    
+  public:
+    //--------------------------------------------------------------------
+    ExtractLymphStationsGenericFilter();
+
+    //--------------------------------------------------------------------
+    typedef ExtractLymphStationsGenericFilter      Self;
+    typedef ImageToImageGenericFilter<ExtractLymphStationsGenericFilter<ArgsInfoType> > Superclass;
+    typedef itk::SmartPointer<Self>       Pointer;
+    typedef itk::SmartPointer<const Self> ConstPointer;
+
+    //--------------------------------------------------------------------
+    itkNewMacro(Self);  
+    itkTypeMacro(ExtractLymphStationsGenericFilter, LightObject);
+
+    //--------------------------------------------------------------------
+    void SetArgsInfo(const ArgsInfoType & a);
+
+    //--------------------------------------------------------------------
+    // Main function called each time the filter is updated
+    template<class ImageType>  
+    void UpdateWithInputImageType();
+
+  protected:
+    template<unsigned int Dim> void InitializeImageType();
+    ArgsInfoType mArgsInfo;
+    
+  }; // end class
+  //--------------------------------------------------------------------
+    
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractLymphStationsGenericFilter.txx"
+#endif
+
+#endif // #define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_H
diff --git a/segmentation/clitkExtractLymphStationsGenericFilter.txx b/segmentation/clitkExtractLymphStationsGenericFilter.txx
new file mode 100644 (file)
index 0000000..2644c1f
--- /dev/null
@@ -0,0 +1,99 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_TXX
+#define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_TXX
+
+#include "clitkImageCommon.h"
+  
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::ExtractLymphStationsGenericFilter():
+  ImageToImageGenericFilter<Self>("ExtractLymphStations") 
+{
+  // Default values
+  cmdline_parser_clitkExtractLymphStations_init(&mArgsInfo);
+  InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::InitializeImageType() 
+{  
+  ADD_IMAGE_TYPE(Dim, uchar);
+  // ADD_IMAGE_TYPE(Dim, short);
+  // ADD_IMAGE_TYPE(Dim, int);
+  // ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::SetArgsInfo(const ArgsInfoType & a) 
+{
+  mArgsInfo=a;
+  SetIOVerbose(mArgsInfo.verbose_flag);
+  if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
+  if (mArgsInfo.mediastinum_given) AddInputFilename(mArgsInfo.mediastinum_arg);
+  if (mArgsInfo.trachea_given) AddInputFilename(mArgsInfo.trachea_arg);
+  if (mArgsInfo.output_given)  AddOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::UpdateWithInputImageType() 
+{ 
+  // Reading input
+  typename ImageType::Pointer mediastinum = this->template GetInput<ImageType>(0);
+  typename ImageType::Pointer trachea = this->template GetInput<ImageType>(1);
+
+  // Create filter
+  typedef clitk::ExtractLymphStationsFilter<ImageType> FilterType;
+  typename FilterType::Pointer filter = FilterType::New();
+    
+  // Set global Options 
+  filter->SetInputMediastinumLabelImage(mediastinum, 0); // change 0 with BG 
+  filter->SetInputTracheaLabelImage(trachea, 0); // change 0 with BG 
+  filter->SetArgsInfo(mArgsInfo);
+
+  // Go !
+  filter->Update();
+  
+  // Check if error
+  if (filter->HasError()) {
+    SetLastError(filter->GetLastError());
+    // No output
+    return;
+  }
+
+  // Write/Save results
+  typename ImageType::Pointer output = filter->GetOutput();
+  this->template SetNextOutput<ImageType>(output); 
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_TXX
diff --git a/segmentation/clitkExtractMediastinum.cxx b/segmentation/clitkExtractMediastinum.cxx
new file mode 100644 (file)
index 0000000..8a1feec
--- /dev/null
@@ -0,0 +1,44 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkExtractMediastinum_ggo.h"
+#include "clitkExtractMediastinumGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+  // Init command line
+  GGO(clitkExtractMediastinum, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::ExtractMediastinumGenericFilter<args_info_clitkExtractMediastinum> FilterType;
+  FilterType::Pointer filter = FilterType::New();
+
+  filter->SetArgsInfo(args_info);
+  filter->Update();
+
+  if (filter->HasError()) {
+    std::cout << filter->GetLastError() << std::endl;
+  }
+
+  return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
diff --git a/segmentation/clitkExtractMediastinum.ggo b/segmentation/clitkExtractMediastinum.ggo
new file mode 100644 (file)
index 0000000..490c673
--- /dev/null
@@ -0,0 +1,34 @@
+#File clitkExtractMediastinum.ggo
+package "clitkExtractMediastinum"
+version "1.0"
+purpose "Extract mediastinum with help of patient/lungs/bones mask"
+
+option "config"                -  "Config file"                  string        no
+option "imagetypes"     -  "Display allowed image types"  flag          off
+option "verbose"        v  "Verbose"                     flag          off
+option "verboseStep"    -  "Verbose each step"           flag          off
+option "writeStep"      w  "Write image at each step"    flag          off
+option "verboseOption"  -  "Display options values"       flag          off
+option "verboseWarningOff" -  "Do not display warning"    flag          off
+
+section "I/O"
+
+option "patient"       p       "Input patient mask filename"     string        yes
+option "patientBG"     -       "Patient Background"              int           default="0" no
+option "bones"         b       "Input bones mask filename"       string        yes
+option "bonesBG"       -       "Bones Background"                int           default="0" no
+option "lung"          l       "Input lung mask filename"        string        yes
+option "lungBG"        -       "Lung Background"                 int           default="0" no
+option "lungLeft"      -       "Lung Left value"                 int           default="1" no
+option "lungRight"     -       "Lung Right value"                int           default="2" no
+
+option "output"        o       "Output lungs mask filename"      string        yes
+
+section "Step 1 : Left/Right limits with lungs"
+
+option "spacing"     - "Intermediate resampling spacing"         double no default="6"
+option "fuzzy1"             -  "Fuzzy relative position threshold"       double no default="0.6"
+
+section "Step 2 : Ant/Post limits with bones"
+
+option "fuzzy2"             -  "Fuzzy relative position threshold"       double no default="0.6"
diff --git a/segmentation/clitkExtractMediastinumFilter.h b/segmentation/clitkExtractMediastinumFilter.h
new file mode 100644 (file)
index 0000000..6c252d4
--- /dev/null
@@ -0,0 +1,152 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTMEDIASTINUMFILTER_H
+#define CLITKEXTRACTMEDIASTINUMFILTER_H
+
+#include "clitkFilterBase.h"
+
+namespace clitk {
+  
+  //--------------------------------------------------------------------
+  /*
+    Try to extract the mediastinum part of a thorax CT.
+    Inputs : 
+    - Patient label image
+    - Lungs label image
+    - Bones label image
+  */
+  //--------------------------------------------------------------------
+  
+  template <class TImageType>
+  class ITK_EXPORT ExtractMediastinumFilter: 
+    public clitk::FilterBase, 
+    public itk::ImageToImageFilter<TImageType, TImageType> 
+  {
+
+  public:
+    /** Standard class typedefs. */
+    typedef itk::ImageToImageFilter<TImageType, TImageType> Superclass;
+    typedef ExtractMediastinumFilter            Self;
+    typedef itk::SmartPointer<Self>             Pointer;
+    typedef itk::SmartPointer<const Self>       ConstPointer;
+    
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);
+    
+    /** Run-time type information (and related methods). */
+    itkTypeMacro(ExtractMediastinumFilter, InPlaceImageFilter);
+    FILTERBASE_INIT;
+
+    /** Some convenient typedefs. */
+    typedef TImageType                       ImageType;
+    typedef typename ImageType::ConstPointer ImageConstPointer;
+    typedef typename ImageType::Pointer      ImagePointer;
+    typedef typename ImageType::RegionType   ImageRegionType; 
+    typedef typename ImageType::PixelType    ImagePixelType; 
+    typedef typename ImageType::SizeType     ImageSizeType; 
+    typedef typename ImageType::IndexType    ImageIndexType; 
+        
+    /** Connect inputs */
+    void SetInputPatientLabelImage(const TImageType * image, ImagePixelType bg=0);
+    void SetInputLungLabelImage(const TImageType * image, ImagePixelType bg=0, 
+                                 ImagePixelType fgLeftLung=1, ImagePixelType fgRightLung=2);
+    void SetInputBonesLabelImage(const TImageType * image, ImagePixelType bg=0);
+   
+    /** ImageDimension constants */
+    itkStaticConstMacro(ImageDimension, unsigned int, TImageType::ImageDimension);
+
+    // Set all options at a time
+    template<class ArgsInfoType>
+      void SetArgsInfo(ArgsInfoType arg);
+   
+    // Background / Foreground
+    itkSetMacro(BackgroundValuePatient, ImagePixelType);
+    itkGetConstMacro(BackgroundValuePatient, ImagePixelType);
+    GGO_DefineOption(patientBG, SetBackgroundValuePatient, ImagePixelType);
+    
+    itkSetMacro(BackgroundValueLung, ImagePixelType);
+    itkGetConstMacro(BackgroundValueLung, ImagePixelType);
+    GGO_DefineOption(lungBG, SetBackgroundValueLung, ImagePixelType);
+    
+    itkSetMacro(BackgroundValueBones, ImagePixelType);
+    itkGetConstMacro(BackgroundValueBones, ImagePixelType);
+    GGO_DefineOption(bonesBG, SetBackgroundValueBones, ImagePixelType);
+    
+    itkGetConstMacro(BackgroundValue, ImagePixelType);
+    itkGetConstMacro(ForegroundValue, ImagePixelType);
+
+    itkSetMacro(ForegroundValueLeftLung, ImagePixelType);
+    itkGetConstMacro(ForegroundValueLeftLung, ImagePixelType);
+    GGO_DefineOption(lungLeft, SetForegroundValueLeftLung, ImagePixelType);
+    
+    itkSetMacro(ForegroundValueRightLung, ImagePixelType);
+    itkGetConstMacro(ForegroundValueRightLung, ImagePixelType);
+    GGO_DefineOption(lungRight, SetForegroundValueRightLung, ImagePixelType);
+    
+    itkSetMacro(IntermediateSpacing, double);
+    itkGetConstMacro(IntermediateSpacing, double);
+    GGO_DefineOption(spacing, SetIntermediateSpacing, double);
+
+    itkSetMacro(FuzzyThreshold1, double);
+    itkGetConstMacro(FuzzyThreshold1, double);
+    GGO_DefineOption(fuzzy1, SetFuzzyThreshold1, double);
+
+    itkSetMacro(FuzzyThreshold2, double);
+    itkGetConstMacro(FuzzyThreshold2, double);
+    GGO_DefineOption(fuzzy2, SetFuzzyThreshold2, double);
+
+  protected:
+    ExtractMediastinumFilter();
+    virtual ~ExtractMediastinumFilter() {}
+    
+    virtual void GenerateOutputInformation();
+    virtual void GenerateInputRequestedRegion();
+    virtual void GenerateData();
+       
+    itkSetMacro(BackgroundValue, ImagePixelType);
+    itkSetMacro(ForegroundValue, ImagePixelType);
+    
+    ImagePixelType m_BackgroundValuePatient;
+    ImagePixelType m_BackgroundValueLung;
+    ImagePixelType m_BackgroundValueBones;
+    ImagePixelType m_ForegroundValueLeftLung;
+    ImagePixelType m_ForegroundValueRightLung;
+
+    ImagePixelType m_BackgroundValue;
+    ImagePixelType m_ForegroundValue;
+    
+    double m_IntermediateSpacing;
+    double m_FuzzyThreshold1;
+    double m_FuzzyThreshold2;
+    
+  private:
+    ExtractMediastinumFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractMediastinumFilter.txx"
+#endif
+
+#endif
diff --git a/segmentation/clitkExtractMediastinumFilter.txx b/segmentation/clitkExtractMediastinumFilter.txx
new file mode 100644 (file)
index 0000000..b5535cf
--- /dev/null
@@ -0,0 +1,263 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTMEDIASTINUMFILTER_TXX
+#define CLITKEXTRACTMEDIASTINUMFILTER_TXX
+
+// clitk
+#include "clitkCommon.h"
+#include "clitkExtractMediastinumFilter.h"
+#include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+
+// itk
+#include <deque>
+#include "itkStatisticsLabelMapFilter.h"
+#include "itkLabelImageToStatisticsLabelMapFilter.h"
+#include "itkRegionOfInterestImageFilter.h"
+#include "itkBinaryThresholdImageFilter.h"
+
+// itk ENST
+#include "RelativePositionPropImageFilter.h"
+
+//--------------------------------------------------------------------
+template <class TImageType>
+clitk::ExtractMediastinumFilter<TImageType>::
+ExtractMediastinumFilter():
+  clitk::FilterBase(),
+  itk::ImageToImageFilter<TImageType, TImageType>()
+{
+  this->SetNumberOfRequiredInputs(3);
+
+  SetBackgroundValuePatient(0);
+  SetBackgroundValueLung(0);
+  SetBackgroundValueBones(0);
+  SetForegroundValueLeftLung(1);
+  SetForegroundValueRightLung(2);
+  SetBackgroundValue(0);
+  SetForegroundValue(1);
+
+  SetIntermediateSpacing(6);
+  SetFuzzyThreshold1(0.6);
+  SetFuzzyThreshold2(0.7);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractMediastinumFilter<TImageType>::
+SetInputPatientLabelImage(const TImageType * image, ImagePixelType bg) {
+  this->SetNthInput(0, const_cast<TImageType *>(image));
+  m_BackgroundValuePatient = bg;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractMediastinumFilter<TImageType>::
+SetInputLungLabelImage(const TImageType * image, ImagePixelType bg, 
+                       ImagePixelType fgLeft, ImagePixelType fgRight) {
+  this->SetNthInput(1, const_cast<TImageType *>(image));
+  m_BackgroundValueLung = bg;
+  m_ForegroundValueLeftLung = fgLeft;
+  m_ForegroundValueRightLung = fgRight;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractMediastinumFilter<TImageType>::
+SetInputBonesLabelImage(const TImageType * image, ImagePixelType bg) {
+  this->SetNthInput(2, const_cast<TImageType *>(image));
+  m_BackgroundValueBones = bg;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+template<class ArgsInfoType>
+void 
+clitk::ExtractMediastinumFilter<TImageType>::
+SetArgsInfo(ArgsInfoType mArgsInfo)
+{
+  SetVerboseOption_GGO(mArgsInfo);
+  SetVerboseStep_GGO(mArgsInfo);
+  SetWriteStep_GGO(mArgsInfo);
+  SetVerboseWarningOff_GGO(mArgsInfo);
+
+  SetBackgroundValuePatient_GGO(mArgsInfo);
+  SetBackgroundValueLung_GGO(mArgsInfo);
+  SetBackgroundValueBones_GGO(mArgsInfo);
+
+  SetForegroundValueLeftLung_GGO(mArgsInfo);
+  SetForegroundValueRightLung_GGO(mArgsInfo);
+
+  SetIntermediateSpacing_GGO(mArgsInfo);
+  SetFuzzyThreshold1_GGO(mArgsInfo);
+  SetFuzzyThreshold2_GGO(mArgsInfo);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractMediastinumFilter<TImageType>::
+GenerateOutputInformation() { 
+  ImagePointer input = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(0));
+  ImagePointer outputImage = this->GetOutput(0);
+  outputImage->SetRegions(outputImage->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractMediastinumFilter<TImageType>::
+GenerateInputRequestedRegion() {
+  // Call default
+  Superclass::GenerateInputRequestedRegion();  
+  // Get input pointers
+  ImagePointer patient = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(0));
+  ImagePointer lung    = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(1));
+  ImagePointer bones   = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(2));
+    
+  patient->SetRequestedRegion(patient->GetLargestPossibleRegion());
+  lung->SetRequestedRegion(lung->GetLargestPossibleRegion());
+  bones->SetRequestedRegion(bones->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractMediastinumFilter<TImageType>::
+GenerateData() {
+  // Get input pointers
+  ImageConstPointer patient = dynamic_cast<const TImageType*>(itk::ProcessObject::GetInput(0));
+  ImageConstPointer lung   = dynamic_cast<const TImageType*>(itk::ProcessObject::GetInput(1));
+  ImageConstPointer bones   = dynamic_cast<const TImageType*>(itk::ProcessObject::GetInput(2));
+    
+  // Get output pointer
+  ImagePointer 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->SetInput2(lung);    
+  boolFilter->SetOperationType(BoolFilterType::AndNot);
+  boolFilter->Update();    
+  boolFilter->SetInput1(boolFilter->GetOutput());
+  boolFilter->SetInput2(bones);
+  boolFilter->SetOperationType(BoolFilterType::AndNot);
+  boolFilter->Update(); 
+  output = boolFilter->GetOutput();
+
+  output = clitk::AutoCrop<ImageType>(output, GetBackgroundValue()); 
+  ////autoCropFilter->GetOutput();  typedef clitk::AutoCropFilter<ImageType> CropFilterType;
+  //typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+  //cropFilter->SetInput(output);
+  //cropFilter->Update();   
+  //output = cropFilter->GetOutput();
+
+  this->template StopCurrentStep<TImageType>(output);
+
+  // Step 2: LR limits from lung (need separate lung ?)
+  StartNewStep("Left/Right limits with lungs");
+  typedef clitk::AddRelativePositionConstraintToLabelImageFilter<TImageType> RelPosFilterType;
+  typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
+  relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+  relPosFilter->VerboseStepOff();
+  relPosFilter->WriteStepOff();
+  relPosFilter->SetInput(output); 
+  relPosFilter->SetInputObject(lung); 
+  relPosFilter->SetOrientationType(RelPosFilterType::LeftTo);
+  relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+  relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
+  relPosFilter->Update();
+  output = relPosFilter->GetOutput();
+
+  relPosFilter->SetInput(output); 
+  relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+  relPosFilter->VerboseStepOff();
+  relPosFilter->WriteStepOff();
+  relPosFilter->SetInputObject(lung); 
+  relPosFilter->SetOrientationType(RelPosFilterType::RightTo);
+  relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+  relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
+  relPosFilter->Update();   
+  output = relPosFilter->GetOutput();
+  this->template StopCurrentStep<TImageType>(output);
+
+  // Step 3: AP limits from bones
+  StartNewStep("Ant/Post limits with bones");
+  relPosFilter->SetCurrentStepNumber(0);
+  relPosFilter->ResetPipeline();// = RelPosFilterType::New();
+  relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+  relPosFilter->VerboseStepOff();
+  relPosFilter->WriteStepOff();
+  relPosFilter->SetInput(output); 
+  relPosFilter->SetInputObject(bones); 
+  relPosFilter->SetOrientationType(RelPosFilterType::AntTo);
+  relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+  relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
+  relPosFilter->Update();
+
+  relPosFilter->SetInput(relPosFilter->GetOutput()); 
+  relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+  relPosFilter->VerboseStepOff();
+  relPosFilter->WriteStepOff();
+  relPosFilter->SetInputObject(bones); 
+  relPosFilter->SetOrientationType(RelPosFilterType::PostTo);
+  relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+  relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
+  relPosFilter->Update();   
+  output = relPosFilter->GetOutput();
+  this->template StopCurrentStep<TImageType>(output);
+
+  // Get CCL
+  output = clitk::Labelize<TImageType>(output, GetBackgroundValue(), true, 100);
+  // output = RemoveLabels<TImageType>(output, BG, param->GetLabelsToRemove());
+  output = clitk::KeepLabels<TImageType>(output, GetBackgroundValue(), 
+                                  GetForegroundValue(), 1, 1, 0);
+
+  output = clitk::AutoCrop<ImageType>(output, GetBackgroundValue()); 
+  //  cropFilter = CropFilterType::New();
+  //cropFilter->SetInput(output);
+  //cropFilter->Update();   
+  //output = cropFilter->GetOutput();
+
+  // Final Step -> set output
+  this->SetNthOutput(0, output);
+}
+//--------------------------------------------------------------------
+  
+
+#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
diff --git a/segmentation/clitkExtractMediastinumGenericFilter.h b/segmentation/clitkExtractMediastinumGenericFilter.h
new file mode 100644 (file)
index 0000000..70a4532
--- /dev/null
@@ -0,0 +1,70 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKEXTRACTMEDIASTINUMSGENERICFILTER_H
+#define CLITKEXTRACTMEDIASTINUMSGENERICFILTER_H
+
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkExtractMediastinumFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk 
+{
+  
+  template<class ArgsInfoType>
+  class ITK_EXPORT ExtractMediastinumGenericFilter: 
+    public ImageToImageGenericFilter<ExtractMediastinumGenericFilter<ArgsInfoType> >
+  {
+    
+  public:
+    //--------------------------------------------------------------------
+    ExtractMediastinumGenericFilter();
+
+    //--------------------------------------------------------------------
+    typedef ExtractMediastinumGenericFilter      Self;
+    typedef ImageToImageGenericFilter<ExtractMediastinumGenericFilter<ArgsInfoType> > Superclass;
+    typedef itk::SmartPointer<Self>       Pointer;
+    typedef itk::SmartPointer<const Self> ConstPointer;
+
+    //--------------------------------------------------------------------
+    itkNewMacro(Self);  
+    itkTypeMacro(ExtractMediastinumGenericFilter, LightObject);
+
+    //--------------------------------------------------------------------
+    void SetArgsInfo(const ArgsInfoType & a);
+
+    //--------------------------------------------------------------------
+    // Main function called each time the filter is updated
+    template<class ImageType>  
+    void UpdateWithInputImageType();
+
+  protected:
+    template<unsigned int Dim> void InitializeImageType();
+    ArgsInfoType mArgsInfo;
+    
+  }; // end class
+  //--------------------------------------------------------------------
+    
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractMediastinumGenericFilter.txx"
+#endif
+
+#endif // #define CLITKEXTRACTMEDIASTINUMSGENERICFILTER_H
diff --git a/segmentation/clitkExtractMediastinumGenericFilter.txx b/segmentation/clitkExtractMediastinumGenericFilter.txx
new file mode 100644 (file)
index 0000000..5a2cead
--- /dev/null
@@ -0,0 +1,102 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTMEDIASTINUMSGENERICFILTER_TXX
+#define CLITKEXTRACTMEDIASTINUMSGENERICFILTER_TXX
+
+#include "clitkImageCommon.h"
+  
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::ExtractMediastinumGenericFilter():
+  ImageToImageGenericFilter<Self>("ExtractMediastinum") 
+{
+  // Default values
+  cmdline_parser_clitkExtractMediastinum_init(&mArgsInfo);
+  InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::InitializeImageType() 
+{  
+  ADD_IMAGE_TYPE(Dim, uchar);
+  // ADD_IMAGE_TYPE(Dim, short);
+  // ADD_IMAGE_TYPE(Dim, int);
+  // ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::SetArgsInfo(const ArgsInfoType & a) 
+{
+  mArgsInfo=a;
+  SetIOVerbose(mArgsInfo.verbose_flag);
+  if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
+  if (mArgsInfo.patient_given) AddInputFilename(mArgsInfo.patient_arg);
+  if (mArgsInfo.lung_given) AddInputFilename(mArgsInfo.lung_arg);
+  if (mArgsInfo.bones_given) AddInputFilename(mArgsInfo.bones_arg);
+  if (mArgsInfo.output_given)  AddOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::UpdateWithInputImageType() 
+{ 
+  // Reading input
+  typename ImageType::Pointer patient = this->template GetInput<ImageType>(0);
+  typename ImageType::Pointer lung = this->template GetInput<ImageType>(1);
+  typename ImageType::Pointer bones = this->template GetInput<ImageType>(2);
+
+  // Create filter
+  typedef clitk::ExtractMediastinumFilter<ImageType> FilterType;
+  typename FilterType::Pointer filter = FilterType::New();
+    
+  // Set global Options 
+  filter->SetInputPatientLabelImage(patient, mArgsInfo.patientBG_arg);
+  filter->SetInputLungLabelImage(lung, mArgsInfo.lungBG_arg, mArgsInfo.lungRight_arg, mArgsInfo.lungLeft_arg);
+  filter->SetInputBonesLabelImage(bones, mArgsInfo.bonesBG_arg);
+  filter->SetArgsInfo(mArgsInfo);
+
+  // Go !
+  filter->Update();
+  
+  // Check if error
+  if (filter->HasError()) {
+    SetLastError(filter->GetLastError());
+    // No output
+    return;
+  }
+
+  // Write/Save results
+  typename ImageType::Pointer output = filter->GetOutput();
+  this->template SetNextOutput<ImageType>(output); 
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKEXTRACTMEDIASTINUMSGENERICFILTER_TXX
diff --git a/segmentation/clitkExtractPatient.cxx b/segmentation/clitkExtractPatient.cxx
new file mode 100644 (file)
index 0000000..8e78809
--- /dev/null
@@ -0,0 +1,43 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkExtractPatient_ggo.h"
+#include "clitkExtractPatientGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkExtractPatient, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::ExtractPatientGenericFilter<args_info_clitkExtractPatient> FilterType;
+  FilterType::Pointer filter = FilterType::New();
+  
+  filter->SetArgsInfo(args_info);
+  filter->Update();
+
+  if (filter->HasError()) {
+    std::cout << filter->GetLastError() << std::endl;
+  }
+
+  return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
diff --git a/segmentation/clitkExtractPatient.ggo b/segmentation/clitkExtractPatient.ggo
new file mode 100644 (file)
index 0000000..3a239e7
--- /dev/null
@@ -0,0 +1,53 @@
+#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."
+
+option "config"                -  "Config file"                  string        no
+option "imagetypes"     -  "Display allowed image types"  flag          off
+option "verbose"        v  "Verbose"                     flag          off
+option "verboseStep"    -  "Verbose each step"           flag          off
+option "writeStep"      w  "Write image at each step"    flag          off
+option "verboseOption"  -  "Display options values"       flag          off
+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
+
+section "Binarize"
+
+option "lower"         -       "Initial lower threshold"       double          no      
+option "upper"         -       "Initial upper threshold"       double          no      default="-300"
+
+section "First Label Image (air=1)"
+
+option "erode1"                 -      "Decompose through erosion"             flag            off     
+option "radius1"        -      "Radius for erosion and dilation"       int             multiple        no      default="1"
+option "new1"           -      "Number of new labels"                  int             no      default="1"     
+option "max1"           -      "Max number of labels to consider"      int             no      default="2"     
+
+section "Second Label Image (air=1)"
+
+option "erode2"                 -      "Decompose through erosion"             flag            off     
+option "radius2"        -      "Radius for erosion and dilation"       int             multiple        no      default="1"
+option "new2"           -      "Number of new labels"                  int             no      default="1"     
+option "max2"           -      "Max number of labels to consider"      int             no      default="2"     
+# option "crop"                -       "Crop the first label image"            flag    off     
+# option "boundingBox"         b       "Bounding box of the crop region (minX,maxX,...)" int   no  multiple
+# option "lowerS"      -       "Size of the lower crop region"   int   no  multiple
+# option "upperS"      -       "Size of the upper crop region"   int   no  multiple
+
+section "Labels to keep (air=1)"
+
+option "firstKeep"     -               "First label to keep"                   int     no      default="1"
+option  "lastKeep"     -               "Last label to keep"                    int     no      default="1"     
+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
+
+
diff --git a/segmentation/clitkExtractPatientFilter.h b/segmentation/clitkExtractPatientFilter.h
new file mode 100644 (file)
index 0000000..9346d9a
--- /dev/null
@@ -0,0 +1,210 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTPATIENTFILTER_H
+#define CLITKEXTRACTPATIENTFILTER_H
+
+#include "clitkFilterBase.h"
+
+namespace clitk {
+  
+  //--------------------------------------------------------------------
+  /*
+    Try to extract the Patient part of a thorax CT.  
+
+    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.
+
+  */
+  //--------------------------------------------------------------------
+  
+  template <class TInputImageType, class TOutputImageType>
+  class ITK_EXPORT ExtractPatientFilter: 
+    public clitk::FilterBase, 
+    public itk::ImageToImageFilter<TInputImageType, TOutputImageType> 
+  {
+  public:
+    /** Standard class typedefs. */
+    typedef ExtractPatientFilter            Self;
+    typedef itk::ImageToImageFilter<TInputImageType, TOutputImageType> Superclass;
+    typedef itk::SmartPointer<Self>         Pointer;
+    typedef itk::SmartPointer<const Self>   ConstPointer;
+    
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);
+    
+    /** Run-time type information (and related methods). */
+    itkTypeMacro(ExtractPatientFilter, ImageToImageFilter);
+    FILTERBASE_INIT;
+
+    /** Some convenient typedefs. */
+    typedef TInputImageType                       InputImageType;
+    typedef typename InputImageType::ConstPointer InputImageConstPointer;
+    typedef typename InputImageType::Pointer      InputImagePointer;
+    typedef typename InputImageType::RegionType   InputImageRegionType; 
+    typedef typename InputImageType::PixelType    InputImagePixelType; 
+    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; 
+
+    itkStaticConstMacro(ImageDimension, unsigned int, InputImageType::ImageDimension);
+    typedef int InternalPixelType;
+    typedef itk::Image<InternalPixelType, ImageDimension> InternalImageType;
+    typedef typename InternalImageType::SizeType          InternalImageSizeType;
+    
+    /** Connect inputs */
+    void SetInput(const TInputImageType * image);
+
+    // Set all options at a time
+    template<class ArgsInfoType>
+      void SetArgsInfo(ArgsInfoType arg);
+
+    // Step 1
+    itkSetMacro(UpperThreshold, InputImagePixelType);
+    itkGetMacro(UpperThreshold, InputImagePixelType);
+    GGO_DefineOption(upper, SetUpperThreshold, InputImagePixelType);
+
+    itkSetMacro(LowerThreshold, InputImagePixelType);
+    itkGetMacro(LowerThreshold, InputImagePixelType);
+    itkSetMacro(UseLowerThreshold, bool);    
+    itkGetConstMacro(UseLowerThreshold, bool);    
+    itkBooleanMacro(UseLowerThreshold);
+    GGO_DefineOption_WithTest(lower, SetLowerThreshold, InputImagePixelType, UseLowerThreshold);
+
+    // Step 2
+    itkSetMacro(DecomposeAndReconstructDuringFirstStep, bool);
+    itkGetConstMacro(DecomposeAndReconstructDuringFirstStep, bool);
+    itkBooleanMacro(DecomposeAndReconstructDuringFirstStep);
+    GGO_DefineOption_Flag(erode1, SetDecomposeAndReconstructDuringFirstStep);
+
+    itkSetMacro(Radius1, InternalImageSizeType);
+    itkGetConstMacro(Radius1, InternalImageSizeType);
+    GGO_DefineOption_Vector(radius1, SetRadius1, InternalImageSizeType, ImageDimension, true);
+
+    itkSetMacro(MaximumNumberOfLabels1, int);
+    itkGetConstMacro(MaximumNumberOfLabels1, int);
+    GGO_DefineOption(max1, SetMaximumNumberOfLabels1, int);
+
+    itkSetMacro(NumberOfNewLabels1, int);
+    itkGetConstMacro(NumberOfNewLabels1, int);
+    GGO_DefineOption(new1, SetNumberOfNewLabels1, int);
+
+    // Step 2
+    itkSetMacro(DecomposeAndReconstructDuringSecondStep, bool);
+    itkGetConstMacro(DecomposeAndReconstructDuringSecondStep, bool);
+    itkBooleanMacro(DecomposeAndReconstructDuringSecondStep);
+    GGO_DefineOption_Flag(erode2, SetDecomposeAndReconstructDuringSecondStep);
+
+    itkSetMacro(Radius2, InternalImageSizeType);
+    itkGetConstMacro(Radius2, InternalImageSizeType);
+    GGO_DefineOption_Vector(radius2, SetRadius2, InternalImageSizeType, ImageDimension, true)
+
+    itkSetMacro(MaximumNumberOfLabels2, int);
+    itkGetConstMacro(MaximumNumberOfLabels2, int);
+    GGO_DefineOption(max2, SetMaximumNumberOfLabels2, int);
+
+    itkSetMacro(NumberOfNewLabels2, int);
+    itkGetConstMacro(NumberOfNewLabels2, int);
+    GGO_DefineOption(new2, SetNumberOfNewLabels2, int);
+
+    // Step 3
+    itkSetMacro(FirstKeep, int);
+    itkGetConstMacro(FirstKeep, int);
+    GGO_DefineOption(firstKeep, SetFirstKeep, int);
+
+    itkSetMacro(LastKeep, int);
+    itkGetConstMacro(LastKeep, int);
+    GGO_DefineOption(lastKeep, SetLastKeep, int);
+
+    // Step 4
+    itkSetMacro(FinalOpenClose, bool);
+    itkGetConstMacro(FinalOpenClose, bool);
+    itkBooleanMacro(FinalOpenClose);
+    GGO_DefineOption_Flag(openClose, SetFinalOpenClose);
+
+    // Step 4
+    itkSetMacro(AutoCrop, bool);
+    itkGetConstMacro(AutoCrop, bool);
+    itkBooleanMacro(AutoCrop);
+    GGO_DefineOption_Flag(autoCrop, SetAutoCrop);
+
+  protected:
+    ExtractPatientFilter();
+    virtual ~ExtractPatientFilter() {}
+    
+    itkSetMacro(BackgroundValue, OutputImagePixelType);
+    itkSetMacro(ForegroundValue, OutputImagePixelType);
+    itkGetConstMacro(BackgroundValue, OutputImagePixelType);
+    itkGetConstMacro(ForegroundValue, OutputImagePixelType);
+    OutputImagePixelType m_BackgroundValue;
+    OutputImagePixelType m_ForegroundValue;
+
+    InputImagePixelType m_UpperThreshold;
+    InputImagePixelType m_LowerThreshold;
+    bool m_UseLowerThreshold;
+    bool m_DecomposeAndReconstructDuringFirstStep;
+    bool m_DecomposeAndReconstructDuringSecondStep;
+    bool m_FinalOpenClose;
+    InternalImageSizeType m_Radius1;
+    InternalImageSizeType m_Radius2;
+    int m_MaximumNumberOfLabels1;
+    int m_MaximumNumberOfLabels2;
+    int m_NumberOfNewLabels1;
+    int m_NumberOfNewLabels2;
+    int m_FirstKeep;
+    int m_LastKeep;
+    bool m_AutoCrop;
+
+    virtual void GenerateOutputInformation();
+    virtual void GenerateData();
+    
+    InputImageConstPointer input;
+    OutputImagePointer output;
+    typename InternalImageType::Pointer working_image;
+        
+  private:
+    ExtractPatientFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractPatientFilter.txx"
+#endif
+
+#endif
diff --git a/segmentation/clitkExtractPatientFilter.txx b/segmentation/clitkExtractPatientFilter.txx
new file mode 100644 (file)
index 0000000..cfc2ab2
--- /dev/null
@@ -0,0 +1,313 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTPATIENTFILTER_TXX
+#define CLITKEXTRACTPATIENTFILTER_TXX
+
+// clitk
+#include "clitkImageCommon.h"
+#include "clitkSetBackgroundImageFilter.h"
+#include "clitkDecomposeAndReconstructImageFilter.h"
+#include "clitkAutoCropFilter.h"
+
+// itk
+#include "itkBinaryThresholdImageFilter.h"
+#include "itkConnectedComponentImageFilter.h"
+#include "itkRelabelComponentImageFilter.h"
+#include "itkBinaryMorphologicalClosingImageFilter.h"
+#include "itkBinaryMorphologicalOpeningImageFilter.h"
+#include "itkBinaryBallStructuringElement.h"
+#include "itkCastImageFilter.h"
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+ExtractPatientFilter():
+  clitk::FilterBase(),
+  itk::ImageToImageFilter<TInputImageType, TOutputImageType>()
+{
+  this->SetNumberOfRequiredInputs(1);
+  SetBackgroundValue(0); // Must be zero
+  SetForegroundValue(1);
+
+  // Step 1: Threshold + CC + sort (Find low density areas)
+  SetUpperThreshold(-300);
+  SetLowerThreshold(-1000);
+  UseLowerThresholdOff();
+
+  // Step 2: DecomposeAndReconstructImageFilter (optional)
+  DecomposeAndReconstructDuringFirstStepOff();
+  InternalImageSizeType r;
+  r.Fill(1);
+  SetRadius1(r);
+  SetMaximumNumberOfLabels1(2);
+  SetNumberOfNewLabels1(1);
+
+  // Step 3: Remove the air (largest area).
+
+  // Step 4: 2nd DecomposeAndReconstructImageFilter
+  DecomposeAndReconstructDuringSecondStepOff();
+  SetRadius2(r);
+  SetMaximumNumberOfLabels2(2);
+  SetNumberOfNewLabels2(1);
+  
+  // Step 5: Only keep label corresponding (Keep patient's labels)
+  SetFirstKeep(1);
+  SetLastKeep(1);
+  
+  // Step 4: OpenClose (option)
+  FinalOpenCloseOn();
+  AutoCropOff();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void 
+clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+SetInput(const TInputImageType * image) 
+{
+  this->SetNthInput(0, const_cast<TInputImageType *>(image));
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+template<class ArgsInfoType>
+void 
+clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+SetArgsInfo(ArgsInfoType arg)
+{
+  SetVerboseOption_GGO(arg);
+  SetVerboseStep_GGO(arg);
+  SetWriteStep_GGO(arg);
+  SetVerboseWarningOff_GGO(arg);
+
+  SetUpperThreshold_GGO(arg);
+  SetLowerThreshold_GGO(arg);
+
+  SetDecomposeAndReconstructDuringFirstStep_GGO(arg);
+  SetRadius1_GGO(arg);
+  SetMaximumNumberOfLabels1_GGO(arg);
+  SetNumberOfNewLabels1_GGO(arg);
+
+  SetDecomposeAndReconstructDuringSecondStep_GGO(arg);
+  SetRadius2_GGO(arg);
+  SetMaximumNumberOfLabels2_GGO(arg);
+  SetNumberOfNewLabels2_GGO(arg);
+  
+  SetFirstKeep_GGO(arg);
+  SetLastKeep_GGO(arg);
+
+  SetFinalOpenClose_GGO(arg);
+  SetAutoCrop_GGO(arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void 
+clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+GenerateOutputInformation() { 
+
+  Superclass::GenerateOutputInformation();
+  input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
+
+  // OutputImagePointer outputImage = this->GetOutput(0);
+//   outputImage->SetRegions(input->GetLargestPossibleRegion());
+
+  // Get input pointers
+  static const unsigned int Dim = InputImageType::ImageDimension;
+  //input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
+    
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // Step 1: 
+  StartNewStep("Find low densities areas");
+  typedef itk::BinaryThresholdImageFilter<InputImageType, InternalImageType> BinarizeFilterType;  
+  typename BinarizeFilterType::Pointer binarizeFilter=BinarizeFilterType::New();
+  binarizeFilter->SetInput(input);
+  if (m_UseLowerThreshold) binarizeFilter->SetLowerThreshold(GetLowerThreshold());
+  binarizeFilter->SetUpperThreshold(GetUpperThreshold());
+  binarizeFilter ->SetInsideValue(this->GetForegroundValue());
+  binarizeFilter ->SetOutsideValue(this->GetBackgroundValue());
+
+  // Connected component labeling
+  typedef itk::ConnectedComponentImageFilter<InternalImageType, InternalImageType> ConnectFilterType;
+  typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
+  connectFilter->SetInput(binarizeFilter->GetOutput());
+  connectFilter->SetBackgroundValue(this->GetBackgroundValue());
+  connectFilter->SetFullyConnected(false);
+  
+  // Sort labels according to size
+  typedef itk::RelabelComponentImageFilter<InternalImageType, InternalImageType> RelabelFilterType;
+  typename RelabelFilterType::Pointer relabelFilter=RelabelFilterType::New();
+  relabelFilter->InPlaceOn();
+  relabelFilter->SetInput(connectFilter->GetOutput());
+  relabelFilter->Update();
+  working_image = relabelFilter->GetOutput();
+  
+  // End
+  StopCurrentStep<InternalImageType>(working_image);
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // [Optional] 
+  if (GetDecomposeAndReconstructDuringFirstStep()) {
+    StartNewStep("First Decompose & Reconstruct step");
+    typedef clitk::DecomposeAndReconstructImageFilter<InternalImageType,InternalImageType> FilterType;
+    typename FilterType::Pointer f = FilterType::New();
+    f->SetInput(working_image);
+    // f->SetVerbose(m_Verbose);
+    f->SetRadius(GetRadius1());
+    f->SetMaximumNumberOfLabels(GetMaximumNumberOfLabels1());
+    f->SetBackgroundValue(this->GetBackgroundValue());
+    f->SetForegroundValue(this->GetForegroundValue());
+    f->SetFullyConnected(true);
+    f->SetNumberOfNewLabels(GetNumberOfNewLabels1());
+    f->Update();
+    working_image = f->GetOutput();
+    StopCurrentStep<InternalImageType>(working_image);
+  }
+  
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Remove the air (largest area)");
+  typedef itk::BinaryThresholdImageFilter<InternalImageType, InternalImageType> iBinarizeFilterType;  
+  typename iBinarizeFilterType::Pointer binarizeFilter2 = iBinarizeFilterType::New();
+  binarizeFilter2->SetInput(working_image);
+  binarizeFilter2->SetLowerThreshold(this->GetForegroundValue());
+  binarizeFilter2->SetUpperThreshold(this->GetForegroundValue());
+  binarizeFilter2 ->SetInsideValue(this->GetBackgroundValue());
+  binarizeFilter2 ->SetOutsideValue(this->GetForegroundValue());
+  //  binarizeFilter2 ->Update(); // NEEDED ?
+
+  typename ConnectFilterType::Pointer connectFilter2 = ConnectFilterType::New();
+  connectFilter2->SetInput(binarizeFilter2->GetOutput());
+  connectFilter2->SetBackgroundValue(this->GetBackgroundValue());
+  connectFilter2->SetFullyConnected(false);
+
+  typename RelabelFilterType::Pointer relabelFilter2 = RelabelFilterType::New();
+  relabelFilter2->SetInput(connectFilter2->GetOutput());
+  relabelFilter2->Update();
+  working_image = relabelFilter2->GetOutput();
+  StopCurrentStep<InternalImageType>(working_image);
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // [Optional] 
+  if (GetDecomposeAndReconstructDuringSecondStep()) {
+    StartNewStep("Second Decompose & Reconstruct step");
+    typedef clitk::DecomposeAndReconstructImageFilter<InternalImageType,InternalImageType> FilterType;
+    typename FilterType::Pointer f = FilterType::New();
+    f->SetInput(working_image);
+    // f->SetVerbose(m_Verbose);
+    f->SetRadius(GetRadius2());
+    f->SetMaximumNumberOfLabels(GetMaximumNumberOfLabels2());
+    f->SetBackgroundValue(this->GetBackgroundValue());
+    f->SetForegroundValue(this->GetForegroundValue());
+    f->SetFullyConnected(true);
+    f->SetNumberOfNewLabels(GetNumberOfNewLabels2());
+    f->Update();
+    working_image = f->GetOutput();
+    StopCurrentStep<InternalImageType>(working_image);
+  }
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  StartNewStep("Keep patient's labels");
+  typename iBinarizeFilterType::Pointer binarizeFilter3 = iBinarizeFilterType::New();
+  binarizeFilter3->SetInput(working_image);
+  binarizeFilter3->SetLowerThreshold(GetFirstKeep());
+  binarizeFilter3->SetUpperThreshold(GetLastKeep());
+  binarizeFilter3 ->SetInsideValue(this->GetForegroundValue());
+  binarizeFilter3 ->SetOutsideValue(this->GetBackgroundValue());
+  binarizeFilter3->Update();
+  working_image = binarizeFilter3->GetOutput();
+  StopCurrentStep<InternalImageType>(working_image);
+  
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // [Optional]
+  if (GetFinalOpenClose()) {
+    StartNewStep("Final OpenClose");
+    // Open
+    typedef itk::BinaryBallStructuringElement<InternalPixelType,Dim> KernelType;
+    KernelType structuringElement;
+    structuringElement.SetRadius(1);
+    structuringElement.CreateStructuringElement();
+    typedef itk::BinaryMorphologicalOpeningImageFilter<InternalImageType, InternalImageType , KernelType> OpenFilterType;
+    typename OpenFilterType::Pointer openFilter = OpenFilterType::New();
+    openFilter->SetInput(working_image);
+    openFilter->SetBackgroundValue(this->GetBackgroundValue());
+    openFilter->SetForegroundValue(this->GetForegroundValue());
+    openFilter->SetKernel(structuringElement);  
+    // Close
+    typedef itk::BinaryMorphologicalClosingImageFilter<InternalImageType, InternalImageType , KernelType> CloseFilterType;
+    typename CloseFilterType::Pointer closeFilter = CloseFilterType::New();
+    closeFilter->SetInput(openFilter->GetOutput());
+    closeFilter->SetSafeBorder(true);
+    closeFilter->SetForegroundValue(this->GetForegroundValue());
+    //  closeFilter->SetBackgroundValue(SetBackgroundValue());
+    closeFilter->SetKernel(structuringElement);
+    closeFilter->Update();  
+    working_image = closeFilter->GetOutput();
+    StopCurrentStep<InternalImageType>(working_image);
+  }
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // Final Cast 
+  typedef itk::CastImageFilter<InternalImageType, OutputImageType> CastImageFilterType;
+  typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
+  caster->SetInput(working_image);
+  caster->Update();
+  output = caster->GetOutput();
+
+  //--------------------------------------------------------------------
+  //--------------------------------------------------------------------
+  // [Optional]
+  if (GetAutoCrop()) {
+  StartNewStep("AutoCrop");
+    typedef clitk::AutoCropFilter<OutputImageType> CropFilterType;
+    typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+    cropFilter->SetInput(output);
+    cropFilter->SetBackgroundValue(GetBackgroundValue());
+    cropFilter->Update();   
+    output = cropFilter->GetOutput();
+    StopCurrentStep<OutputImageType>(output);
+  }
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void 
+clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+GenerateData() {
+  //this->SetNthOutput(0, output); // -> no because redo filter otherwise
+  this->GraftOutput(output);
+}
+//--------------------------------------------------------------------
+  
+
+#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
diff --git a/segmentation/clitkExtractPatientGenericFilter.cxx b/segmentation/clitkExtractPatientGenericFilter.cxx
new file mode 100644 (file)
index 0000000..429729f
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef clitkExtractPatientGenericFilter_cxx
+#define clitkExtractPatientGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkExtractPatientGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkExtractPatientGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  ExtractPatientGenericFilter::ExtractPatientGenericFilter()
+  {
+    m_Verbose=false;
+    m_InputFileName="";
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void ExtractPatientGenericFilter::Update()
+  {
+    // Read the Dimension and PixelType
+    int Dimension;
+    std::string PixelType;
+    ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType);
+
+    
+    // Call UpdateWithDim
+    if(Dimension==2) UpdateWithDim<2>(PixelType);
+    else if(Dimension==3) UpdateWithDim<3>(PixelType);
+    // else if (Dimension==4)UpdateWithDim<4>(PixelType); 
+    else 
+      {
+       std::cout<<"Error, Only for 2 or 3  Dimensions!!!"<<std::endl ;
+       return;
+      }
+  }
+
+
+} //end clitk
+
+#endif  //#define clitkExtractPatientGenericFilter_cxx
diff --git a/segmentation/clitkExtractPatientGenericFilter.h b/segmentation/clitkExtractPatientGenericFilter.h
new file mode 100644 (file)
index 0000000..23b1ecf
--- /dev/null
@@ -0,0 +1,69 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKEXTRACTPATIENTGENERICFILTER_H
+#define CLITKEXTRACTPATIENTGENERICFILTER_H
+
+// clitk 
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkExtractPatientFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk 
+{
+
+  template<class ArgsInfoType>
+  class ITK_EXPORT ExtractPatientGenericFilter:
+    public ImageToImageGenericFilter<ExtractPatientGenericFilter<ArgsInfoType> >
+  {
+  public:
+    //--------------------------------------------------------------------
+    ExtractPatientGenericFilter();
+  
+    //--------------------------------------------------------------------
+    typedef ExtractPatientGenericFilter   Self;
+    typedef ImageToImageGenericFilter<ExtractPatientGenericFilter<ArgsInfoType> > Superclass;
+    typedef itk::SmartPointer<Self>       Pointer;
+    typedef itk::SmartPointer<const Self> ConstPointer;
+   
+    //--------------------------------------------------------------------
+    itkNewMacro(Self);  
+    itkTypeMacro( ExtractPatientGenericFilter, LightObject );
+
+    //--------------------------------------------------------------------
+    void SetArgsInfo(const ArgsInfoType & a);
+
+    //--------------------------------------------------------------------
+    // Main function called each time the filter is updated
+    template<class ImageType>  
+    void UpdateWithInputImageType();
+
+  protected:
+    template<unsigned int Dim> void InitializeImageType();
+    ArgsInfoType mArgsInfo;
+
+  };// end class
+  //--------------------------------------------------------------------
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractPatientGenericFilter.txx"
+#endif
+
+#endif // #define CLITKEXTRACTPATIENTGENERICFILTER_H
diff --git a/segmentation/clitkExtractPatientGenericFilter.txx b/segmentation/clitkExtractPatientGenericFilter.txx
new file mode 100644 (file)
index 0000000..26252de
--- /dev/null
@@ -0,0 +1,95 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#include "clitkImageCommon.h"
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ExtractPatientGenericFilter<ArgsInfoType>::ExtractPatientGenericFilter():
+  ImageToImageGenericFilter<Self>("ExtractPatient") 
+{
+  // Default values
+  cmdline_parser_clitkExtractPatient_init(&mArgsInfo);
+  InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ExtractPatientGenericFilter<ArgsInfoType>::InitializeImageType() 
+{  
+  ADD_IMAGE_TYPE(Dim, short);
+  // ADD_IMAGE_TYPE(Dim, int);
+  // ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::ExtractPatientGenericFilter<ArgsInfoType>::SetArgsInfo(const ArgsInfoType & a) 
+{
+  mArgsInfo=a;
+  SetIOVerbose(mArgsInfo.verbose_flag);
+  if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
+  if (mArgsInfo.input_given)  SetInputFilename(mArgsInfo.input_arg);
+  if (mArgsInfo.output_given)  AddOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::ExtractPatientGenericFilter<ArgsInfoType>::UpdateWithInputImageType() 
+{ 
+  // Output image type
+  typedef itk::Image<uchar, ImageType::ImageDimension> OutputImageType;
+
+  // Reading input
+  typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
+
+  // Create filter
+  typedef clitk::ExtractPatientFilter<ImageType, OutputImageType> FilterType;
+  typename FilterType::Pointer filter = FilterType::New();
+    
+  // Set global Options 
+  filter->SetArgsInfo(mArgsInfo);
+  filter->SetInput(input);
+
+  // Go !
+  filter->Update();
+  
+  // Check if error
+  if (filter->HasError()) {
+    SetLastError(filter->GetLastError());
+    // No output
+    return;
+  }
+
+  // Write/Save results
+  typename OutputImageType::Pointer output = filter->GetOutput();
+  this->template SetNextOutput<OutputImageType>(output); 
+}
+//--------------------------------------------------------------------
+
+
diff --git a/segmentation/clitkFillMask.cxx b/segmentation/clitkFillMask.cxx
new file mode 100644 (file)
index 0000000..209fbf7
--- /dev/null
@@ -0,0 +1,45 @@
+/*------------------------------------------------------------------------
+                                                                                 
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+                                                                             
+  ------------------------------------------------------------------------*/
+
+/* =================================================
+ * @file   clitkFillMask.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkFillMask_ggo.h"
+#include "clitkIO.h"
+#include "clitkFillMaskGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkFillMask,args_info);
+  CLITK_INIT;
+
+  // Filter
+  clitk::FillMaskGenericFilter::Pointer genericFilter=clitk::FillMaskGenericFilter::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/segmentation/clitkFillMask.ggo b/segmentation/clitkFillMask.ggo
new file mode 100644 (file)
index 0000000..60e80e7
--- /dev/null
@@ -0,0 +1,13 @@
+#File clitkFillMask.ggo
+package "clitkFillMask"
+version "1.0"
+purpose "Fill in holes (bg=0) in an object (fg=1) of a binary image, by running over the slices and retaining only one connected component bg."
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+option "input"         i       "Input image filename"            string        yes
+option "output"        o       "Output image filename"           string        yes
+option "dir"           d       "Directions (axes) to perform filling (defaults to 2,1,0)"      int multiple no
+
+
diff --git a/segmentation/clitkFillMaskGenericFilter.cxx b/segmentation/clitkFillMaskGenericFilter.cxx
new file mode 100644 (file)
index 0000000..59a88e5
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef clitkFillMaskGenericFilter_cxx
+#define clitkFillMaskGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkFillMaskGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkFillMaskGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  FillMaskGenericFilter::FillMaskGenericFilter()
+  {
+    m_Verbose=false;
+    m_InputFileName="";
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void FillMaskGenericFilter::Update()
+  {
+    // Read the Dimension and PixelType
+    int Dimension;
+    std::string PixelType;
+    ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType);
+
+    
+    // Call UpdateWithPixelType
+     if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<< PixelType<<"..."<<std::endl;
+     if (Dimension != 3) 
+       {
+        std::cerr<<"Error: Only for 3D!!"<<std::endl;
+        return;
+       }
+     
+     if(PixelType == "short"){  
+       if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
+       UpdateWithPixelType<signed short>(); 
+     }
+     
+     //    else if(PixelType == "unsigned_short"){  
+     //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
+     //       UpdateWithPixelType<unsigned short>(); 
+     //     }
+     
+     else if (PixelType == "unsigned_char"){ 
+       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
+       UpdateWithPixelType<unsigned char>();
+     }
+     
+     //     else if (PixelType == "char"){ 
+     //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
+     //       UpdateWithPixelType<signed char>();
+     //     }
+     
+     else {
+       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
+       UpdateWithPixelType<float>();
+     }
+  }
+
+
+} //end clitk
+
+#endif  //#define clitkFillMaskGenericFilter_cxx
diff --git a/segmentation/clitkFillMaskGenericFilter.h b/segmentation/clitkFillMaskGenericFilter.h
new file mode 100644 (file)
index 0000000..8a9b479
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef clitkFillMaskGenericFilter_h
+#define clitkFillMaskGenericFilter_h
+
+/* =================================================
+ * @file   clitkFillMaskGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkFillMask_ggo.h"
+#include "clitkImageCommon.h"
+#include "clitkExtractImageFilter.h"
+
+//itk include
+#include "itkLightObject.h"
+#include "itkJoinSeriesImageFilter.h"
+#include "itkBinaryThresholdImageFilter.h"
+#include "itkConnectedComponentImageFilter.h"
+#include "itkRelabelComponentImageFilter.h"
+#include "itkThresholdImageFilter.h"
+#include "itkPermuteAxesImageFilter.h"
+#include "itkExtractImageFilter.h"
+#include "itkCastImageFilter.h"
+
+namespace clitk 
+{
+
+
+  class ITK_EXPORT FillMaskGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef FillMaskGenericFilter                   Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( FillMaskGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_clitkFillMask & a)
+    {
+      m_ArgsInfo=a;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+      m_InputFileName=m_ArgsInfo.input_arg;
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    FillMaskGenericFilter();
+    ~FillMaskGenericFilter() {};
+
+    
+    //----------------------------------------  
+    // Templated members
+    //----------------------------------------  
+    template <class PixelType>  void UpdateWithPixelType();
+
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_clitkFillMask m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_InputFileName;
+
+  };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkFillMaskGenericFilter.txx"
+#endif
+
+#endif // #define clitkFillMaskGenericFilter_h
diff --git a/segmentation/clitkFillMaskGenericFilter.txx b/segmentation/clitkFillMaskGenericFilter.txx
new file mode 100644 (file)
index 0000000..d723e10
--- /dev/null
@@ -0,0 +1,201 @@
+#ifndef clitkFillMaskGenericFilter_txx
+#define clitkFillMaskGenericFilter_txx
+
+/* =================================================
+ * @file   clitkFillMaskGenericFilter.txx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+namespace clitk
+{
+
+  //-------------------------------------------------------------------
+  // Update with the pixeltype
+  //-------------------------------------------------------------------
+  template <class  PixelType> 
+  void 
+  FillMaskGenericFilter::UpdateWithPixelType()
+  {
+    // Dim & Pix
+    const unsigned int Dimension=3;
+    typedef int InternalPixelType;
+
+    // ImageTypes
+    typedef itk::Image<PixelType, Dimension> InputImageType;
+    typedef itk::Image<InternalPixelType, Dimension> InternalImageType;
+    typedef itk::Image<PixelType, Dimension> OutputImageType;
+    
+    // Read the input
+    typedef itk::ImageFileReader<InputImageType> InputReaderType;
+    typename InputReaderType::Pointer reader = InputReaderType::New();
+    reader->SetFileName( m_InputFileName);
+    reader->Update();
+    typename InputImageType::Pointer input= reader->GetOutput();
+  
+    // Read the directions over which to fill holes
+    std::vector<unsigned int> direction;
+    if (m_ArgsInfo.dir_given)
+      for ( unsigned int i=0;i<m_ArgsInfo.dir_given;i++)
+       direction.push_back(m_ArgsInfo.dir_arg[i]);
+    else
+      for ( unsigned int i=0;i<Dimension;i++)
+       direction.push_back(Dimension-i-1);
+
+    //---------------------------------------- 
+    // Cast to internal type    
+    //----------------------------------------  
+    typedef itk::CastImageFilter<InputImageType,InternalImageType> InputCastImageFilterType;
+    typename InputCastImageFilterType::Pointer inputCaster= InputCastImageFilterType::New();
+    inputCaster->SetInput(input);
+    inputCaster->Update();
+
+    //---------------------------------------- 
+    // Loop over directions    
+    //---------------------------------------- 
+    typename InternalImageType::Pointer output=inputCaster->GetOutput();
+    for (unsigned int i=0; i<direction.size();i++)
+      {
+       
+       //---------------------------------------- 
+       // Fill the holes of a mask in 2D
+       //----------------------------------------
+       if(m_Verbose) std::cout<<"Fill holes in the mask slice by slice in direction "<<direction[i]<<"..."<<std::endl;
+
+       // We define the region to be extracted.
+       typedef  itk::Image<InternalPixelType, Dimension-1> ImageSliceType;
+       typedef  itk::Image<InternalPixelType, Dimension-1> MaskSliceType;
+       typename InternalImageType::RegionType region3D= input->GetLargestPossibleRegion();
+       typename InternalImageType::RegionType::SizeType size3D= region3D.GetSize();
+       typename InternalImageType::RegionType::SizeType size2D=size3D;
+       size2D[direction[i]]=0;
+       typename InternalImageType::IndexType start2D; 
+       start2D.Fill(0);
+       typename InternalImageType::RegionType desiredRegion;
+       desiredRegion.SetSize( size2D );
+       desiredRegion.SetIndex( start2D );
+      
+       // Extract and Join 
+       typedef itk::ExtractImageFilter<InternalImageType, ImageSliceType> ExtractImageFilterType;
+       typedef itk::JoinSeriesImageFilter<ImageSliceType, InternalImageType> JoinSeriesFilterType;
+       typename JoinSeriesFilterType::Pointer joinFilter=JoinSeriesFilterType::New();
+       joinFilter->SetSpacing(input->GetSpacing()[direction[i]]);
+      
+       //---------------------------------------- 
+       // Run over the sliceIndexs
+       // ----------------------------------------
+       for(unsigned int sliceIndex=0; sliceIndex <size3D[direction[i]]; sliceIndex++)
+         {
+           //---------------------------------------- 
+           // Extract mask sliceIndex
+           //----------------------------------------
+           typename ExtractImageFilterType::Pointer extractFilter=ExtractImageFilterType::New();
+           extractFilter->SetInput(output);
+           start2D[direction[i]]=sliceIndex;
+           desiredRegion.SetIndex( start2D );
+           extractFilter->SetExtractionRegion( desiredRegion );
+           extractFilter->Update( );
+           typename ImageSliceType::Pointer slice= extractFilter->GetOutput();
+
+           // Binarize the image (Before: OBJECT!=0, rest=0, After: object=1, rest=0 )
+           typedef itk::BinaryThresholdImageFilter<ImageSliceType,ImageSliceType> BinarizeFilterType;
+           typename BinarizeFilterType::Pointer binarizeFilter=BinarizeFilterType::New();
+           binarizeFilter->SetInput(slice);
+           binarizeFilter->SetUpperThreshold(0);
+           binarizeFilter->SetOutsideValue(0);
+           binarizeFilter->SetInsideValue(1);
+           // writeImage<ImageSliceType>(binarizeFilter->GetOutput(),"/home/jef/tmp/input.mhd");
+
+           // Perform connected labelling on the slice (body+air=0 )
+           typedef itk::ConnectedComponentImageFilter<ImageSliceType, ImageSliceType> ConnectFilterType;
+           typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
+           connectFilter->SetInput(binarizeFilter->GetOutput());
+           connectFilter->SetBackgroundValue(0);
+           connectFilter->SetFullyConnected(false);
+           //connectFilter->Update();
+           //writeImage<ImageSliceType>(connectFilter->GetOutput(),"/home/jef/tmp/connect.mhd");
+                 
+           // Sort the labels
+           typedef itk::RelabelComponentImageFilter<ImageSliceType, ImageSliceType> RelabelFilterType;
+           typename RelabelFilterType::Pointer relabelFilter=RelabelFilterType::New();
+           relabelFilter->SetInput(connectFilter->GetOutput());
+           //relabelFilter->Update();
+           //writeImage<ImageSliceType>(relabelFilter->GetOutput(),"/home/jef/tmp/label.mhd"); 
+           
+           // Keep the first
+           typedef itk::ThresholdImageFilter<ImageSliceType> ThresholdFilterType;
+           typename ThresholdFilterType::Pointer thresholdFilter=ThresholdFilterType::New();
+           thresholdFilter->SetInput(relabelFilter->GetOutput());
+           thresholdFilter->SetUpper(1);
+           thresholdFilter->SetOutsideValue(0);
+           // thresholdFilter->Update();
+           // writeImage<ImageSliceType>(thresholdFilter->GetOutput(),"/home/jef/tmp/bin.mhd");        
+
+           // Invert the labels (lung 1, rest 0)
+           typename BinarizeFilterType::Pointer switchFilter=BinarizeFilterType::New();
+           switchFilter->SetInput(thresholdFilter->GetOutput());
+           switchFilter->SetUpperThreshold(0);
+           switchFilter->SetOutsideValue(0);
+           switchFilter->SetInsideValue(1);
+           switchFilter->Update();
+           //writeImage<ImageSliceType>(switchFilter->GetOutput(),"/home/jef/tmp/inv_bin.mhd");        
+           
+           //Join
+           joinFilter->SetInput( sliceIndex, switchFilter->GetOutput());
+         }
+       
+       // Join to a 3D image   
+       if (m_Verbose) std::cout<<"Joining the slices..."<<std::endl;
+       joinFilter->Update();
+       
+       // Permute the axes to reset to orientation
+       typedef itk::PermuteAxesImageFilter<InternalImageType> PermuteFilterType;
+       typename PermuteFilterType::Pointer permuteFilter=PermuteFilterType::New();
+       permuteFilter->SetInput(joinFilter->GetOutput());
+       typename PermuteFilterType::PermuteOrderArrayType order;
+       order[direction[i]]=2;
+       if( direction[i]==2)
+         {
+           order[0]=0;
+           order[1]=1;
+         }
+       else if ( direction[i]==1)
+         {
+           order[0]=0;
+           order[2]=1;
+         }
+       else if (direction[i]==0)
+         {
+           order[1]=0;
+           order[2]=1;
+         }
+       permuteFilter->SetOrder(order);
+       permuteFilter->Update();
+       output =permuteFilter->GetOutput();
+       
+       // Set the image direction to the input one
+       output->SetDirection(input->GetDirection());
+       output->SetOrigin(input->GetOrigin());
+      }
+
+
+    // Cast
+    typedef itk::CastImageFilter<InternalImageType,OutputImageType> OutputCastImageFilterType;
+    typename OutputCastImageFilterType::Pointer outputCaster =OutputCastImageFilterType::New();
+    outputCaster->SetInput(output);
+            
+    // Output
+    typedef itk::ImageFileWriter<OutputImageType> WriterType;
+    typename WriterType::Pointer writer = WriterType::New();
+    writer->SetFileName(m_ArgsInfo.output_arg);
+    writer->SetInput(outputCaster->GetOutput());
+    writer->Update();
+  }
+
+}//end clitk
+
+#endif //#define clitkFillMaskGenericFilter_txx
diff --git a/segmentation/clitkTestFilter.cxx b/segmentation/clitkTestFilter.cxx
new file mode 100644 (file)
index 0000000..a0b386d
--- /dev/null
@@ -0,0 +1,211 @@
+
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+// clitk
+#include "clitkTestFilter_ggo.h"
+#include "clitkImageCommon.h"
+#include "clitkBooleanOperatorLabelImageFilter.h"
+#include "clitkAutoCropFilter.h"
+//#include "clitkRelativePositionConstraintLabelImageFilter.h"
+#include "clitkResampleImageWithOptionsFilter.h"
+#include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
+
+#include "clitkExtractLungFilter.h"
+#include "clitkExtractPatientFilter.h"
+#include "clitkExtractMediastinumFilter.h"
+
+// ITK ENST
+#include "RelativePositionPropImageFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkTestFilter, args_info);
+
+  // Image types
+  //typedef unsigned char PixelType;
+  typedef short PixelType;
+  static const int Dim=3;
+  typedef itk::Image<PixelType, Dim> InputImageType;
+
+  // Read inputs
+  InputImageType::Pointer input1;
+  InputImageType::Pointer input2;
+  InputImageType::Pointer input3;
+  input1 = clitk::readImage<InputImageType>(args_info.input1_arg, true);
+  if (args_info.input2_given) input2 = clitk::readImage<InputImageType>(args_info.input2_arg, true);
+  if (args_info.input3_given) input3 = clitk::readImage<InputImageType>(args_info.input3_arg, true);
+  
+  // Declare output
+  InputImageType::Pointer output;
+
+  //--------------------------------------------------------------------
+  // Filter test BooleanOperatorLabelImageFilter
+  if (0) {
+    typedef clitk::BooleanOperatorLabelImageFilter<InputImageType> FilterType;
+    FilterType::Pointer filter = FilterType::New();
+    filter->SetInput1(input1);
+    filter->SetInput2(input2);
+    output = clitk::NewImageLike<InputImageType>(input1);
+    filter->GraftOutput(output);  /// TO VERIFY !!!
+    filter->Update();  
+    filter->SetInput2(input3);
+    filter->Update();    
+    output = filter->GetOutput();
+    clitk::writeImage<InputImageType>(output, args_info.output_arg);
+  }
+  
+  //--------------------------------------------------------------------
+  // Filter test AutoCropLabelImageFilter
+  if (1) {
+    typedef clitk::AutoCropFilter<InputImageType> FilterType;
+    FilterType::Pointer filter = FilterType::New();
+    filter->SetInput(input1);
+    filter->Update();    
+    output = filter->GetOutput();
+    clitk::writeImage<InputImageType>(output, args_info.output_arg);
+  }
+
+  //--------------------------------------------------------------------
+  // Filter test RelativePositionPropImageFilter
+  if (0) {
+    typedef itk::Image<float, Dim> OutputImageType;
+    OutputImageType::Pointer outputf;
+    typedef itk::RelativePositionPropImageFilter<InputImageType, OutputImageType> FilterType;
+    FilterType::Pointer filter = FilterType::New();
+    filter->SetInput(input1);
+
+    filter->SetAlpha1(clitk::deg2rad(args_info.angle1_arg)); // xy plane
+    filter->SetAlpha2(clitk::deg2rad(args_info.angle2_arg));
+    filter->SetK1(M_PI/2.0); // Opening parameter, default = pi/2
+    filter->SetFast(true);
+    filter->SetRadius(2);
+    filter->SetVerboseProgress(true);
+    
+    /*         A1   A2
+               Left      0    0
+               Right   180    0
+               Ant      90    0
+               Post    -90    0
+               Inf       0   90
+               Sup       0  -90
+    */
+
+    filter->Update();    
+    clitk::writeImage<OutputImageType>(filter->GetOutput(), args_info.output_arg);
+  }
+
+  //--------------------------------------------------------------------
+  // Filter test 
+  if (0) {
+    typedef itk::Image<short, Dim> OutputImageType;
+    typedef clitk::ResampleImageWithOptionsFilter<InputImageType, OutputImageType> FilterType;
+    FilterType::Pointer filter = FilterType::New();
+    filter->SetInput(input1); 
+    filter->SetOutputIsoSpacing(1);
+    //filter->SetNumberOfThreads(4); // auto
+    filter->SetGaussianFilteringEnabled(false);
+    filter->Update();    
+    clitk::writeImage<OutputImageType>(filter->GetOutput(), args_info.output_arg);
+  }
+
+  //--------------------------------------------------------------------
+  // Filter AddRelativePositionConstraintToLabelImageFilter test 
+  if (0) {
+    /*
+    typedef clitk::AddRelativePositionConstraintToLabelImageFilter<InputImageType> FilterType;
+    FilterType::Pointer filter = FilterType::New();
+    filter->SetInput(input1); 
+    filter->SetInputObject(input2); 
+    filter->SetOrientationType(FilterType::LeftTo);
+    filter->SetIntermediateSpacing(5);
+    filter->SetFuzzyThreshold(0.5);
+    filter->VerboseStepOn();
+    filter->WriteStepOff();
+    filter->Update();
+
+    filter->SetInput(filter->GetOutput()); 
+    filter->SetInputObject(input2); 
+    filter->SetOrientationType(FilterType::RightTo);
+    filter->SetIntermediateSpacing(5);
+    filter->SetFuzzyThreshold(0.5);
+    filter->Update();   
+
+    clitk::writeImage<InputImageType>(filter->GetOutput(), args_info.output_arg);
+    */
+  }
+
+  //--------------------------------------------------------------------
+  // Filter test ExtractPatientFilter
+  if (0) {
+    typedef itk::Image<char, Dim> OutputImageType;
+    typedef clitk::ExtractPatientFilter<InputImageType, OutputImageType> FilterType;
+    FilterType::Pointer filter = FilterType::New();
+    filter->SetInput(input1);
+    filter->VerboseStepOn();
+    filter->WriteStepOn();    
+    // options (default)
+    filter->SetUpperThreshold(-300);
+    filter->FinalOpenCloseOff(); // default=on (not rezally needed ?)
+    filter->Update();    
+    OutputImageType::Pointer output = filter->GetOutput();
+    clitk::writeImage<OutputImageType>(output, args_info.output_arg);
+  }
+
+  //--------------------------------------------------------------------
+  // Filter test ExtractLungsFilter
+  if (0) {
+    typedef itk::Image<PixelType, Dim> OutputImageType; // to change into char
+    typedef clitk::ExtractLungFilter<InputImageType, OutputImageType> FilterType;
+    FilterType::Pointer filter = FilterType::New();
+    // DD(filter->GetNumberOfSteps());
+    filter->SetInput(input1); // CT
+    filter->SetInputPatientMask(input2, 0); // Patient mask and BG value
+    filter->VerboseStepOn();
+    filter->WriteStepOn();    
+    // options (default)
+    //filter->SetBackgroundValue(0);
+    filter->SetUpperThreshold(-300);
+    // filter->SetMinimumComponentSize(100);
+
+    filter->Update();    
+    OutputImageType::Pointer output = filter->GetOutput();
+    clitk::writeImage<OutputImageType>(output, args_info.output_arg);
+  }
+
+  //--------------------------------------------------------------------
+  // Filter test ExtractMediastinumFilter
+  if (0) {
+    typedef clitk::ExtractMediastinumFilter<InputImageType> FilterType;
+    FilterType::Pointer filter = FilterType::New();
+    filter->SetInputPatientLabelImage(input1);
+    filter->SetInputLungLabelImage(input2, 0, 1, 2); // BG, FG Left Lung, FG Right Lung
+    filter->SetInputBonesLabelImage(input3);
+    filter->VerboseStepOn();
+    filter->WriteStepOn();    
+    filter->Update();    
+    output = filter->GetOutput();
+    clitk::writeImage<InputImageType>(output, args_info.output_arg);
+  }
+
+  // This is the end my friend
+  return EXIT_SUCCESS;
+}// end main
+//--------------------------------------------------------------------
diff --git a/segmentation/clitkTestFilter.ggo b/segmentation/clitkTestFilter.ggo
new file mode 100644 (file)
index 0000000..d9778e7
--- /dev/null
@@ -0,0 +1,16 @@
+#File clitkTestFilter.ggo
+package "clitkTestFilter"
+version "1.0"
+purpose "Test a filter"
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+option "input1"                i       "Input 1 image filename"          string        yes
+option "input2"                j       "Input 2 image filename"          string        no
+option "input3"                k       "Input 3 image filename"          string        no
+option "output"        o       "Output image filename"           string        yes
+
+option "angle1"        a       "First angle (degree)"            float         default = "0" no
+option "angle2"        b       "Second angle (degree)"           float         default = "0" no
+