]> Creatis software - clitk.git/commitdiff
new FillMask with itk filter
authordsarrut <dsarrut>
Fri, 22 Oct 2010 07:56:13 +0000 (07:56 +0000)
committerdsarrut <dsarrut>
Fri, 22 Oct 2010 07:56:13 +0000 (07:56 +0000)
segmentation/clitkFillMaskFilter.h [new file with mode: 0644]
segmentation/clitkFillMaskFilter.txx [new file with mode: 0644]

diff --git a/segmentation/clitkFillMaskFilter.h b/segmentation/clitkFillMaskFilter.h
new file mode 100644 (file)
index 0000000..31c25b3
--- /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 CLITKFILLMASKFILTER_H
+#define CLITKFILLMASKFILTER_H
+
+// clitk 
+#include "clitkCommon.h"
+
+//itk 
+#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 
+{
+  
+  //--------------------------------------------------------------------
+  template <class TImageType>
+  class ITK_EXPORT FillMaskFilter: 
+    public itk::ImageToImageFilter<TImageType, TImageType > 
+  {
+  public:
+    /** Standard class typedefs. */
+    typedef itk::ImageToImageFilter<TImageType, TImageType> Superclass;
+    typedef FillMaskFilter                 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(FillMaskFilter, ImageToImageFilter);
+
+    /** Some convenient typedefs */
+    typedef TImageType                       ImageType;
+    typedef typename ImageType::ConstPointer InputImageConstPointer;
+    typedef typename ImageType::Pointer      InputImagePointer;
+    typedef typename ImageType::RegionType   InputImageRegionType; 
+    typedef typename ImageType::PixelType    InputImagePixelType; 
+    typedef typename ImageType::SizeType     InputImageSizeType; 
+    typedef typename ImageType::IndexType    InputImageIndexType; 
+    typedef typename ImageType::PointType    InputImagePointType; 
+    itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
+
+    /** Options */
+    void AddDirection(int dir);
+    void ResetDirections();
+    const std::vector<int> & GetDirections() const { return m_Directions; }
+
+    // Set all options at a time
+    template<class ArgsInfoType> void SetOptionsFromArgsInfo(ArgsInfoType & arg);
+    template<class ArgsInfoType> void SetOptionsToArgsInfo(ArgsInfoType & arg);
+  protected:
+    FillMaskFilter();
+    virtual ~FillMaskFilter() {};
+
+    // Main members
+    InputImageConstPointer input;
+    std::vector<int> m_Directions;
+
+   // Main function
+    virtual void GenerateData();
+    
+   private:
+    FillMaskFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkFillMaskFilter.txx"
+#endif
+
+#endif
diff --git a/segmentation/clitkFillMaskFilter.txx b/segmentation/clitkFillMaskFilter.txx
new file mode 100644 (file)
index 0000000..7ddda01
--- /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 CLITKFILLMASKFILTER_TXX
+#define CLITKFILLMASKFILTER_TXX
+
+//--------------------------------------------------------------------
+template <class ImageType>
+clitk::FillMaskFilter<ImageType>::FillMaskFilter():
+  itk::ImageToImageFilter<ImageType, ImageType>()
+{
+  // Default global options
+  this->SetNumberOfRequiredInputs(1);
+  ResetDirections();
+  AddDirection(2);
+  AddDirection(1);
+  AddDirection(0);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::FillMaskFilter<ImageType>::
+AddDirection(int dir)
+{
+  m_Directions.push_back(dir);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::FillMaskFilter<ImageType>::
+ResetDirections()
+{
+  m_Directions.clear();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+template<class ArgsInfoType>
+void 
+clitk::FillMaskFilter<ImageType>::
+SetOptionsFromArgsInfo(ArgsInfoType & mArgsInfo)
+{
+  ResetDirections();
+  for(uint i=0; i<mArgsInfo.dir_given; i++) {
+    AddDirection(mArgsInfo.dir_arg[i]);
+  }
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+template<class ArgsInfoType>
+void 
+clitk::FillMaskFilter<ImageType>::
+SetOptionsToArgsInfo(ArgsInfoType & mArgsInfo)
+{
+  mArgsInfo.dir_arg = new int[m_Directions.size()];
+  mArgsInfo.dir_given = m_Directions.size();
+  for(uint i=0; i<mArgsInfo.dir_given; i++) {
+    mArgsInfo.dir_arg[i] = m_Directions[i];
+  }
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::FillMaskFilter<ImageType>::
+GenerateData() 
+{
+  InputImagePointer input  = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
+
+  // Cast 
+  typedef int InternalPixelType;
+  typedef itk::Image<InternalPixelType, ImageType::ImageDimension> InternalImageType;
+  typedef itk::CastImageFilter<ImageType,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<m_Directions.size();i++) {
+    DD(i);
+    //---------------------------------------- 
+    // Fill the holes of a mask in 2D
+    //----------------------------------------
+        
+    // We define the region to be extracted.
+    typedef  itk::Image<InternalPixelType, ImageType::ImageDimension-1> ImageSliceType;
+    typedef  itk::Image<InternalPixelType, ImageType::ImageDimension-1> MaskSliceType;
+    typename InternalImageType::RegionType region3D = input->GetLargestPossibleRegion();
+    typename InternalImageType::RegionType::SizeType size3D = region3D.GetSize();
+    typename InternalImageType::RegionType::SizeType size2D = size3D;
+    size2D[m_Directions[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()[m_Directions[i]]);
+      
+    //---------------------------------------- 
+    // Run over the sliceIndexs
+    // ----------------------------------------
+    for(unsigned int sliceIndex=0; sliceIndex <size3D[m_Directions[i]]; sliceIndex++)
+      {
+        //---------------------------------------- 
+        // Extract mask sliceIndex
+        //----------------------------------------
+        typename ExtractImageFilterType::Pointer extractFilter=ExtractImageFilterType::New();
+        extractFilter->SetInput(output);
+        start2D[m_Directions[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      
+    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[m_Directions[i]]=2;
+    if( m_Directions[i]==2)
+      {
+        order[0]=0;
+        order[1]=1;
+      }
+    else if ( m_Directions[i]==1)
+      {
+        order[0]=0;
+        order[2]=1;
+      }
+    else if (m_Directions[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());
+  }
+  
+  writeImage<InternalImageType>(output, "toto.mhd");
+  
+  // Cast
+  DD("cast");
+  typedef itk::CastImageFilter<InternalImageType,ImageType> OutputCastImageFilterType;
+  typename OutputCastImageFilterType::Pointer outputCaster =OutputCastImageFilterType::New();
+  outputCaster->SetInput(output);
+  outputCaster->Update();
+  
+  // Output
+  DD("Graft");
+  this->GraftOutput(outputCaster->GetOutput());
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKFILLMASKFILTER_TXX