From: Leonardo Florez-Valencia Date: Fri, 27 Mar 2015 22:44:05 +0000 (-0500) Subject: Segmentation guided by a gaussian estimator added -- Not yet finished X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=d3bb16bf060b7249a9ed1a49e6b118ca9394a22a;p=FrontAlgorithms.git Segmentation guided by a gaussian estimator added -- Not yet finished --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ad5b54..15cf2d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/appli/examples/CMakeLists.txt b/appli/examples/CMakeLists.txt index 254ef0b..ad80e0a 100644 --- a/appli/examples/CMakeLists.txt +++ b/appli/examples/CMakeLists.txt @@ -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 index 0000000..850ef5a --- /dev/null +++ b/appli/examples/example_ImageAlgorithmRegionGrow_GaussianModelEstimator.cxx @@ -0,0 +1,256 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +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$ diff --git a/lib/fpa/Image/Algorithm.h b/lib/fpa/Image/Algorithm.h index 289eb6c..e23a108 100644 --- a/lib/fpa/Image/Algorithm.h +++ b/lib/fpa/Image/Algorithm.h @@ -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; diff --git a/lib/fpa/Image/Algorithm.hxx b/lib/fpa/Image/Algorithm.hxx index 1b7eab9..4a57bdd 100644 --- a/lib/fpa/Image/Algorithm.hxx +++ b/lib/fpa/Image/Algorithm.hxx @@ -6,24 +6,25 @@ #include // ------------------------------------------------------------------------- -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( ) { } diff --git a/lib/fpa/Image/RegionGrow.h b/lib/fpa/Image/RegionGrow.h index dd7c851..b12a869 100644 --- a/lib/fpa/Image/RegionGrow.h +++ b/lib/fpa/Image/RegionGrow.h @@ -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 >