]> Creatis software - FrontAlgorithms.git/commitdiff
Segmentation guided by a gaussian estimator added -- Not yet finished
authorLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Fri, 27 Mar 2015 22:44:05 +0000 (17:44 -0500)
committerLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Fri, 27 Mar 2015 22:44:05 +0000 (17:44 -0500)
CMakeLists.txt
appli/examples/CMakeLists.txt
appli/examples/example_ImageAlgorithmRegionGrow_GaussianModelEstimator.cxx [new file with mode: 0644]
lib/fpa/Image/Algorithm.h
lib/fpa/Image/Algorithm.hxx
lib/fpa/Image/RegionGrow.h

index 2ad5b5461f0146bc104049eb6a52b80cbc8134dd..15cf2d947cf44c9636594be9bd85cc2b310dc8dc 100644 (file)
@@ -32,7 +32,7 @@ SET(FrontAlgorithms_VERSION "${FrontAlgorithms_MAJOR_VERSION}.${FrontAlgorithms_
 
 OPTION(BUILD_EXAMPLES "Build examples" OFF)
 OPTION(BUILD_SHARED_LIBS "Build shared libs" OFF)
-OPTION(USE_VTK "Build using VTK" OFF)
+OPTION(USE_VTK "Build using VTK" ON)
 
 IF(BUILD_SHARED_LIBS)
   SET(LIB_TYPE SHARED)
index 254ef0b0f968047e4a430546f1bfc026f059efb2..ad80e0a91bc753d5a423ab483bef62af05a48d09 100644 (file)
@@ -34,6 +34,24 @@ IF(BUILD_EXAMPLES)
         ${VTK_LIBRARIES} vtkIOLegacy
         )
     ENDFOREACH(APP)
+
+    IF(USE_cpPlugins)
+      SET(
+        cpPlugins_APPLIS
+        example_ImageAlgorithmRegionGrow_GaussianModelEstimator
+        )
+
+      FOREACH(APP ${cpPlugins_APPLIS})
+        ADD_EXECUTABLE(${APP} ${APP}.cxx)
+        TARGET_LINK_LIBRARIES(
+          ${APP}
+          FrontAlgorithms
+          ${cpPlugins_Extensions_LIBRARY_NAME}
+          )
+      ENDFOREACH(APP)
+
+    ENDIF(USE_cpPlugins)
+
   ENDIF(USE_VTK)
 ENDIF(BUILD_EXAMPLES)
 
diff --git a/appli/examples/example_ImageAlgorithmRegionGrow_GaussianModelEstimator.cxx b/appli/examples/example_ImageAlgorithmRegionGrow_GaussianModelEstimator.cxx
new file mode 100644 (file)
index 0000000..850ef5a
--- /dev/null
@@ -0,0 +1,256 @@
+#include <iostream>
+#include <limits>
+#include <string>
+
+#include <itkImage.h>
+#include <itkImageFileReader.h>
+#include <itkSignedDanielssonDistanceMapImageFilter.h>
+#include <itkImageToVTKImageFilter.h>
+
+#include <vtkImageActor.h>
+#include <vtkInteractorStyleImage.h>
+#include <vtkPointHandleRepresentation3D.h>
+#include <vtkProperty.h>
+#include <vtkRenderer.h>
+#include <vtkRenderWindow.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkSeedRepresentation.h>
+#include <vtkSeedWidget.h>
+#include <vtkSmartPointer.h>
+
+#include <fpa/Image/RegionGrow.h>
+#include <fpa/Image/Functors/RegionGrowAllBelongsFunction.h>
+#include <fpa/VTK/Image2DObserver.h>
+#include <cpPlugins/Extensions/Algorithms/IterativeGaussianModelEstimator.h>
+
+// -------------------------------------------------------------------------
+const unsigned int Dim = 2;
+typedef unsigned char TChannel;
+typedef itk::RGBPixel< TChannel > TPixel;
+typedef double TScalar;
+typedef itk::Image< TChannel, Dim > TImage;
+typedef itk::Image< TPixel, Dim >   TColorImage;
+typedef itk::ImageToVTKImageFilter< TColorImage > TVTKImage;
+
+typedef itk::ImageFileReader< TColorImage >   TColorImageReader;
+typedef fpa::Image::RegionGrow< TColorImage, TImage, fpa::Image::Functors::CastVertexValueToConstantCost< TPixel, bool > > TFrontAlgorithm;
+
+typedef
+fpa::VTK::Image2DObserver< TFrontAlgorithm, vtkRenderWindow >
+TObserver;
+
+// -------------------------------------------------------------------------
+template< class I, class S >
+class GaussianFunction
+  : public fpa::Image::Functors::RegionGrowAllBelongsFunction< I >
+{
+public:
+  // Type-related and pointers
+  typedef GaussianFunction                                        Self;
+  typedef fpa::Image::Functors::RegionGrowAllBelongsFunction< I > Superclass;
+  typedef itk::SmartPointer< Self >                               Pointer;
+  typedef itk::SmartPointer< const Self >                         ConstPointer;
+
+  // Superclass' types
+  typedef typename Superclass::TInputImage  TInputImage;
+  typedef typename Superclass::TOutputValue TOutputValue;
+  typedef typename Superclass::TIndex       TIndex;
+
+  typedef cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, 3 > TEstimator;
+
+public:
+  itkNewMacro( Self );
+  itkTypeMacro(
+    GaussianFunction,
+    fpa_Image_Functors_RegionGrowAllBelongsFunction
+    );
+
+  itkGetConstMacro( ModelSupport, unsigned long );
+  itkSetMacro( ModelSupport, unsigned long );
+
+  typedef itk::Image< bool, I::ImageDimension > TMarks;
+
+public:
+  virtual void SetInputImage( TInputImage* img )
+    {
+      std::cout << "Set!!!" << std::endl;
+      this->Superclass::SetInputImage( img );
+      this->m_Marks = TMarks::New( );
+      this->m_Marks->SetLargestPossibleRegion( img->GetLargestPossibleRegion( ) );
+      this->m_Marks->SetRequestedRegion( img->GetRequestedRegion( ) );
+      this->m_Marks->SetBufferedRegion( img->GetBufferedRegion( ) );
+      this->m_Marks->SetOrigin( img->GetOrigin( ) );
+      this->m_Marks->SetSpacing( img->GetSpacing( ) );
+      this->m_Marks->SetDirection( img->GetDirection( ) );
+      this->m_Marks->Allocate( );
+      this->m_Marks->FillBuffer( false );
+    }
+
+
+  virtual TOutputValue Evaluate( const TIndex& idx ) const
+    {
+      const TInputImage* img = this->GetInputImage( );
+      typename TInputImage::PixelType rgb = img->GetPixel( idx );
+
+      if( !this->m_Estimating )
+      {
+        if( !( this->m_Marks->GetPixel( idx ) ) )
+        {
+          this->m_Estimator->AddSample(
+            S( rgb.GetRed( ) ),
+            S( rgb.GetGreen( ) ),
+            S( rgb.GetBlue( ) )
+            );
+          this->m_Marks->SetPixel( idx, true );
+#error CONTINUE HERE!!!!
+          std::cout << this->m_Estimator->GetNumberOfSamples( ) << " " << this->m_ModelSupport << std::endl;
+          if( this->m_Estimator->GetNumberOfSamples( ) == this->m_ModelSupport )
+            this->m_Estimating = true;
+
+        } // fi
+        return( true );
+      }
+      else
+        return( false );
+    }
+
+protected:
+  GaussianFunction( )
+    : Superclass( ),
+      m_ModelSupport( 10 )
+    {
+      this->m_Estimator = TEstimator::New( );
+      this->m_Estimator->Clear( );
+      this->m_Estimating = false;
+    }
+  virtual ~GaussianFunction( )
+    { }
+
+private:
+  // Purposely not implemented
+  GaussianFunction( const Self& );
+  void operator=( const Self& );
+
+protected:
+  typename TEstimator::Pointer m_Estimator;
+  unsigned long m_ModelSupport;
+  mutable bool m_Estimating;
+  typename TMarks::Pointer m_Marks;
+};
+
+typedef GaussianFunction< TColorImage, TScalar > TMembershipFunction;
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  if( argc < 3 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " input_image support" << std::endl;
+    return( 1 );
+
+  } // fi
+  std::string input_image_fn = argv[ 1 ];
+  unsigned long support = std::atoi( argv[ 2 ] );
+
+  // Read image
+  TColorImageReader::Pointer input_image_reader = TColorImageReader::New( );
+  input_image_reader->SetFileName( input_image_fn );
+  try
+  {
+    input_image_reader->Update( );
+  }
+  catch( itk::ExceptionObject& err )
+  {
+    std::cerr << "Error caught: " << err << std::endl;
+    return( 1 );
+
+  } // yrt
+  TColorImage::ConstPointer input_image = input_image_reader->GetOutput( );
+
+  TVTKImage::Pointer vtk_image = TVTKImage::New( );
+  vtk_image->SetInput( input_image );
+  vtk_image->Update( );
+
+  // VTK visualization
+  vtkSmartPointer< vtkImageActor > actor =
+    vtkSmartPointer< vtkImageActor >::New( );
+  actor->SetInputData( vtk_image->GetOutput( ) );
+
+  vtkSmartPointer< vtkRenderer > renderer =
+    vtkSmartPointer< vtkRenderer >::New( );
+  renderer->SetBackground( 0.1, 0.2, 0.7 );
+  renderer->AddActor( actor );
+  vtkSmartPointer< vtkRenderWindow > window =
+    vtkSmartPointer< vtkRenderWindow >::New( );
+  window->SetSize( 800, 800 );
+  window->AddRenderer( renderer );
+
+  // VTK interaction
+  vtkSmartPointer< vtkInteractorStyleImage > imageStyle =
+    vtkSmartPointer< vtkInteractorStyleImage >::New( );
+  vtkSmartPointer< vtkRenderWindowInteractor > interactor =
+    vtkSmartPointer< vtkRenderWindowInteractor >::New( );
+  interactor->SetInteractorStyle( imageStyle );
+  window->SetInteractor( interactor );
+  window->Render( );
+
+  // Create the widget and its representation
+  vtkSmartPointer< vtkPointHandleRepresentation3D > handle =
+    vtkSmartPointer< vtkPointHandleRepresentation3D >::New( );
+  handle->GetProperty( )->SetColor( 1, 0, 0 );
+  vtkSmartPointer< vtkSeedRepresentation > rep =
+    vtkSmartPointer< vtkSeedRepresentation >::New( );
+  rep->SetHandleRepresentation( handle );
+
+  vtkSmartPointer< vtkSeedWidget > widget =
+    vtkSmartPointer< vtkSeedWidget >::New( );
+  widget->SetInteractor( interactor );
+  widget->SetRepresentation( rep );
+
+  // Let some interaction
+  interactor->Initialize( );
+  window->Render( );
+  widget->On( );
+  interactor->Start( );
+
+  // Configure observer
+  TObserver::Pointer obs = TObserver::New( );
+  obs->SetImage( input_image, window );
+
+  // Configure membership function
+  TMembershipFunction::Pointer membership = TMembershipFunction::New( );
+  membership->SetModelSupport( support );
+  membership->SetInputImage( const_cast< TColorImage* >( input_image.GetPointer( ) ) );
+
+  // Configure algorithm
+  TFrontAlgorithm::Pointer algorithm = TFrontAlgorithm::New( );
+  for( unsigned int s = 0; s < rep->GetNumberOfSeeds( ); s++ )
+  {
+    double pos[ 3 ];
+    rep->GetSeedWorldPosition( s, pos );
+
+    TColorImage::PointType pnt;
+    pnt[ 0 ] = TScalar( pos[ 0 ] );
+    pnt[ 1 ] = TScalar( pos[ 1 ] );
+
+    TColorImage::IndexType idx;
+    if( input_image->TransformPhysicalPointToIndex( pnt, idx ) )
+      algorithm->AddSeed( idx, 0 );
+
+  } // rof
+  algorithm->AddObserver( itk::AnyEvent( ), obs );
+  algorithm->ThrowEventsOn( );
+  algorithm->SetInput( input_image );
+  algorithm->SetNeighborhoodOrder( 1 );
+  algorithm->SetMembershipFunction( membership );
+  algorithm->Update( );
+
+  // One last interaction
+  interactor->Start( );
+
+  return( 0 );
+}
+
+// eof - $RCSfile$
index 289eb6c0e7da7dad12899fcf8c929b3b0e58d5f1..e23a1084c3a585826adb7f9e54ac44bf233f6767 100644 (file)
@@ -8,13 +8,85 @@ namespace fpa
 {
   namespace Image
   {
+    namespace Functors
+    {
+      /**
+       */
+      template< class VV, class C >
+      class CastVertexValueToCost
+        : public itk::FunctionBase< VV, C >
+      {
+      public:
+        // Type-related and pointers
+        typedef CastVertexValueToCost           Self;
+        typedef itk::FunctionBase< VV, C >      Superclass;
+        typedef itk::SmartPointer< Self >       Pointer;
+        typedef itk::SmartPointer< const Self > ConstPointer;
+
+      public:
+        itkNewMacro( Self );
+        itkTypeMacro( CastVertexValueToCost, itkFunctionBase );
+
+      public:
+        virtual C Evaluate( const VV& v ) const
+          { return( C( v ) ); }
+
+      protected:
+        CastVertexValueToCost( )
+          : Superclass( )
+          { }
+        virtual ~CastVertexValueToCost( )
+          { }
+
+      private:
+        // Purposely not implemented
+        CastVertexValueToCost( const Self& );
+        void operator=( const Self& );
+      };
+
+      /**
+       */
+      template< class VV, class C >
+      class CastVertexValueToConstantCost
+        : public itk::FunctionBase< VV, C >
+      {
+      public:
+        // Type-related and pointers
+        typedef CastVertexValueToConstantCost   Self;
+        typedef itk::FunctionBase< VV, C >      Superclass;
+        typedef itk::SmartPointer< Self >       Pointer;
+        typedef itk::SmartPointer< const Self > ConstPointer;
+
+      public:
+        itkNewMacro( Self );
+        itkTypeMacro( CastVertexValueToConstantCost, itkFunctionBase );
+
+      public:
+        virtual C Evaluate( const VV& v ) const
+          { return( C( 1 ) ); }
+
+      protected:
+        CastVertexValueToConstantCost( )
+          : Superclass( )
+          { }
+        virtual ~CastVertexValueToConstantCost( )
+          { }
+
+      private:
+        // Purposely not implemented
+        CastVertexValueToConstantCost( const Self& );
+        void operator=( const Self& );
+      };
+
+    } // ecapseman
+
     /**
      * A generic front propagation algorithm were vertices are image pixels.
      *
      * @param I    Input image type
      * @param A    Base algorithm (RegionGrow, Dijkstra or FastMarching)
      */
-    template< class I, class A >
+    template< class I, class A, class CC >
     class Algorithm
       : public A
     {
@@ -26,8 +98,9 @@ namespace fpa
       typedef itk::SmartPointer< const Self > ConstPointer;
 
       /// Template input values
-      typedef I TInputImage;
-      typedef A TBaseAlgorithm;
+      typedef I  TInputImage;
+      typedef A  TBaseAlgorithm;
+      typedef CC TCostConversionFunction;
 
       typedef typename A::TTraits            TTraits;
       typedef typename TTraits::TCost        TCost;
@@ -36,7 +109,6 @@ namespace fpa
       typedef typename TTraits::TVertexValue TVertexValue;
 
       typedef itk::Image< TResult, I::ImageDimension > TOutputImage;
-      typedef itk::FunctionBase< TCost, TCost > TCostConversionFunction;
 
     protected:
       typedef typename TTraits::TFrontId _TFrontId;
index 1b7eab945b71940b7c9e8cbff464faef7b44300a..4a57bddef02b9f60eb44d604c3f4a14cc74d4478 100644 (file)
@@ -6,24 +6,25 @@
 #include <itkConstNeighborhoodIterator.h>
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+fpa::Image::Algorithm< I, A, CC >::
 Algorithm( )
   : Superclass( ),
     m_NeighborhoodOrder( 1 )
 {
+  this->m_CostConversion = TCostConversionFunction::New( );
 }
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+fpa::Image::Algorithm< I, A, CC >::
 ~Algorithm( )
 {
 }
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-bool fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+bool fpa::Image::Algorithm< I, A, CC >::
 _UpdateResult( _TNode& n )
 {
   bool ret = this->Superclass::_UpdateResult( n );
@@ -32,8 +33,8 @@ _UpdateResult( _TNode& n )
 }
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-unsigned long fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+unsigned long fpa::Image::Algorithm< I, A, CC >::
 _NumberOfVertices( ) const
 {
   return(
@@ -42,26 +43,26 @@ _NumberOfVertices( ) const
 }
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-typename fpa::Image::Algorithm< I, A >::
-TVertexValue fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+typename fpa::Image::Algorithm< I, A, CC >::
+TVertexValue fpa::Image::Algorithm< I, A, CC >::
 _Value( const TVertex& v ) const
 {
   return( this->GetInput( )->GetPixel( v ) );
 }
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-typename fpa::Image::Algorithm< I, A >::
-TResult fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+typename fpa::Image::Algorithm< I, A, CC >::
+TResult fpa::Image::Algorithm< I, A, CC >::
 _Result( const TVertex& v ) const
 {
   return( this->GetOutput( )->GetPixel( v ) );
 }
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-double fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+double fpa::Image::Algorithm< I, A, CC >::
 _Norm( const TVertex& a, const TVertex& b ) const
 {
   typename I::PointType pa, pb;
@@ -71,8 +72,8 @@ _Norm( const TVertex& a, const TVertex& b ) const
 }
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-bool fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+bool fpa::Image::Algorithm< I, A, CC >::
 _Edge( const TVertex& a, const TVertex& b ) const
 {
   unsigned long dist = 0;
@@ -85,27 +86,25 @@ _Edge( const TVertex& a, const TVertex& b ) const
 }
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-typename fpa::Image::Algorithm< I, A >::
-TCost fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+typename fpa::Image::Algorithm< I, A, CC >::
+TCost fpa::Image::Algorithm< I, A, CC >::
 _Cost( const TVertex& a, const TVertex& b ) const
 {
   static const TCost INF_COST = std::numeric_limits< TCost >::max( );
   if( this->_Edge( a, b ) )
   {
-    TCost c = TCost( this->GetInput( )->GetPixel( b ) );
-    if( this->m_CostConversion.IsNotNull( ) )
-      return( this->m_CostConversion->Evaluate( c ) );
-    else
-      return( c );
+    return(
+      this->m_CostConversion->Evaluate( this->GetInput( )->GetPixel( b ) )
+      );
   }
   else
     return( INF_COST );
 }
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-void fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+void fpa::Image::Algorithm< I, A, CC >::
 _Neighs( const _TNode& n, _TNodes& N ) const
 {
   typename I::RegionType reg = this->GetInput( )->GetRequestedRegion( );
@@ -151,8 +150,8 @@ _Neighs( const _TNode& n, _TNodes& N ) const
 }
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-void fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+void fpa::Image::Algorithm< I, A, CC >::
 _NeighsInDim( const _TNode& n, const unsigned int& d, _TNodes& N )
 {
   typename I::RegionType reg = this->GetInput( )->GetRequestedRegion( );
@@ -169,8 +168,8 @@ _NeighsInDim( const _TNode& n, const unsigned int& d, _TNodes& N )
 }
 
 // -------------------------------------------------------------------------
-template< class I, class A >
-void fpa::Image::Algorithm< I, A >::
+template< class I, class A, class CC >
+void fpa::Image::Algorithm< I, A, CC >::
 _InitializeResults( )
 {
 }
index dd7c851a5bf5324ad12b72d101a9f59910e57232..b12a869d87ccdca57610f351da531a9b71e30bc0 100644 (file)
@@ -14,22 +14,22 @@ namespace fpa
     /**
      * @param I Input image type
      */
-    template< class I >
+    template< class I, class O = I, class CC = fpa::Image::Functors::CastVertexValueToCost< typename I::PixelType, typename O::PixelType > >
     class RegionGrow
-      : public Algorithm< I, fpa::Base::RegionGrow< typename I::IndexType, typename I::PixelType, typename I::PixelType, itk::Functor::IndexLexicographicCompare< I::ImageDimension >, itk::ImageToImageFilter< I, I > > >
+      : public Algorithm< I, fpa::Base::RegionGrow< typename I::IndexType, typename O::PixelType, typename I::PixelType, itk::Functor::IndexLexicographicCompare< I::ImageDimension >, itk::ImageToImageFilter< I, O > >, CC >
     {
     public:
       // Standard class typdedefs
       typedef typename I::IndexType TVertex;
-      typedef typename I::PixelType TResult;
+      typedef typename O::PixelType TResult;
       typedef typename I::PixelType TVertexValue;
-      typedef itk::ImageToImageFilter< I, I > TBaseFilter;
+      typedef itk::ImageToImageFilter< I, O > TBaseFilter;
       typedef fpa::Base::RegionGrow< TVertex, TResult, TVertexValue, itk::Functor::IndexLexicographicCompare< I::ImageDimension >, TBaseFilter > TBaseAlgorithm;
 
-      typedef RegionGrow                      Self;
-      typedef Algorithm< I, TBaseAlgorithm >  Superclass;
-      typedef itk::SmartPointer< Self >       Pointer;
-      typedef itk::SmartPointer< const Self > ConstPointer;
+      typedef RegionGrow                         Self;
+      typedef Algorithm< I, TBaseAlgorithm, CC > Superclass;
+      typedef itk::SmartPointer< Self >          Pointer;
+      typedef itk::SmartPointer< const Self >    ConstPointer;
 
       typedef
       fpa::Image::Functors::ImageFunction< I, bool >