]> Creatis software - FrontAlgorithms.git/commitdiff
...
authorLeonardo Flórez-Valencia <leonardo.florez@gmail.com>
Wed, 22 Mar 2017 03:13:46 +0000 (22:13 -0500)
committerLeonardo Flórez-Valencia <leonardo.florez@gmail.com>
Wed, 22 Mar 2017 03:13:46 +0000 (22:13 -0500)
libs/fpa/Base/MarksInterface.h [new file with mode: 0644]
libs/fpa/Base/MarksInterface.hxx [new file with mode: 0644]
libs/fpa/Image/MarksInterface.h [new file with mode: 0644]
libs/fpa/Image/MarksInterface.hxx [new file with mode: 0644]
libs/fpa/Image/RegionGrow.h
libs/fpa/Image/RegionGrow.hxx

diff --git a/libs/fpa/Base/MarksInterface.h b/libs/fpa/Base/MarksInterface.h
new file mode 100644 (file)
index 0000000..b0fae74
--- /dev/null
@@ -0,0 +1,66 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__MarksInterface__h__
+#define __fpa__Base__MarksInterface__h__
+
+#include <itkProcessObject.h>
+#include <vector>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TVertex >
+    class MarksInterface
+    {
+    public:
+      typedef _TVertex       TVertex;
+      typedef MarksInterface Self;
+
+      // Minigraph to represent collisions
+      typedef std::pair< _TVertex, bool >   TCollision;
+      typedef std::vector< TCollision >     TCollisionsRow;
+      typedef std::vector< TCollisionsRow > TCollisions;
+
+    public:
+      bool StopAtOneFront( ) const;
+      void StopAtOneFrontOn( );
+      void StopAtOneFrontOff( );
+      void SetStopAtOneFront( bool v );
+
+    protected:
+      MarksInterface( itk::ProcessObject* filter );
+      virtual ~MarksInterface( );
+
+      virtual bool _IsMarked( const TVertex& v ) const = 0;
+      virtual unsigned long _GetMark( const TVertex& v ) const = 0;
+      virtual void _Mark( const TVertex& v, unsigned long frontId ) = 0;
+      virtual void _FreeMarks( ) = 0;
+
+      virtual void _InitMarks( unsigned long nSeeds );
+      unsigned long _Collisions( const TVertex& a, const TVertex& b );
+
+    protected:
+      bool m_StopAtOneFront;
+      TCollisions m_Collisions;
+      unsigned int m_NumberOfFronts;
+      unsigned int m_NumberOfSeeds;
+      itk::ProcessObject* m_Filter;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/MarksInterface.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__MarksInterface__h__
+
+// eof - $RCSfile$
diff --git a/libs/fpa/Base/MarksInterface.hxx b/libs/fpa/Base/MarksInterface.hxx
new file mode 100644 (file)
index 0000000..56de375
--- /dev/null
@@ -0,0 +1,129 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__MarksInterface__hxx__
+#define __fpa__Base__MarksInterface__hxx__
+
+#include <queue>
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+bool fpa::Base::MarksInterface< _TVertex >::
+StopAtOneFront( ) const
+{
+  return( this->m_StopAtOneFront );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+void fpa::Base::MarksInterface< _TVertex >::
+StopAtOneFrontOn( )
+{
+  this->SetStopAtOneFront( true );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+void fpa::Base::MarksInterface< _TVertex >::
+StopAtOneFrontOff( )
+{
+  this->SetStopAtOneFront( false );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+void fpa::Base::MarksInterface< _TVertex >::
+SetStopAtOneFront( bool v )
+{
+  if( this->m_StopAtOneFront != v )
+  {
+    this->m_StopAtOneFront = v;
+    if( this->m_Filter != NULL )
+      this->m_Filter->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+fpa::Base::MarksInterface< _TVertex >::
+MarksInterface( itk::ProcessObject* filter )
+  : m_StopAtOneFront( false ),
+    m_NumberOfFronts( 0 ),
+    m_NumberOfSeeds( 0 ),
+    m_Filter( filter )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+fpa::Base::MarksInterface< _TVertex >::
+~MarksInterface( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+void fpa::Base::MarksInterface< _TVertex >::
+_InitMarks( unsigned long nSeeds )
+{
+  this->m_NumberOfFronts = this->m_NumberOfSeeds = nSeeds;
+  TCollision coll( TVertex( ), false );
+  TCollisionsRow row( this->m_NumberOfFronts, coll );
+  this->m_Collisions.clear( );
+  this->m_Collisions.resize( this->m_NumberOfFronts, row );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex >
+unsigned long fpa::Base::MarksInterface< _TVertex >::
+_Collisions( const TVertex& a, const TVertex& b )
+{
+  auto ma = this->_GetMark( a );
+  auto mb = this->_GetMark( b );
+  if( ma == mb || ma == 0 || mb == 0 )
+    return( this->m_NumberOfFronts );
+
+  // Mark collision, if it is new
+  ma--; mb--;
+  bool ret = false;
+  bool exists = this->m_Collisions[ ma ][ mb ].second;
+  exists     &= this->m_Collisions[ mb ][ ma ].second;
+  if( !exists )
+  {
+    this->m_Collisions[ ma ][ mb ].first = a;
+    this->m_Collisions[ ma ][ mb ].second = true;
+    this->m_Collisions[ mb ][ ma ].first = b;
+    this->m_Collisions[ mb ][ ma ].second = true;
+
+    // Update number of fronts
+    unsigned long count = 0;
+    std::vector< bool > m( this->m_NumberOfSeeds, false );
+    std::queue< unsigned long > q;
+    q.push( 0 );
+    while( !q.empty( ) )
+    {
+      unsigned long f = q.front( );
+      q.pop( );
+
+      if( m[ f ] )
+        continue;
+      m[ f ] = true;
+      count++;
+
+      for( unsigned int n = 0; n < this->m_NumberOfSeeds; ++n )
+        if( this->m_Collisions[ f ][ n ].second && !m[ n ] )
+          q.push( n );
+
+    } // elihw
+    this->m_NumberOfFronts = this->m_NumberOfSeeds - count;
+
+  } // fi
+  return( this->m_NumberOfFronts );
+}
+
+#endif // __fpa__Base__MarksInterface__hxx__
+
+// eof - $RCSfile$
diff --git a/libs/fpa/Image/MarksInterface.h b/libs/fpa/Image/MarksInterface.h
new file mode 100644 (file)
index 0000000..d238d82
--- /dev/null
@@ -0,0 +1,59 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__MarksInterface__h__
+#define __fpa__Image__MarksInterface__h__
+
+#include <fpa/Base/MarksInterface.h>
+#include <itkIndex.h>
+#include <itkImage.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< unsigned int _VDim >
+    class MarksInterface
+      : public fpa::Base::MarksInterface< itk::Index< _VDim > >
+    {
+    public:
+      typedef MarksInterface Self;
+      typedef fpa::Base::MarksInterface< itk::Index< _VDim > > Superclass;
+
+      typedef typename Superclass::TVertex        TVertex;
+      typedef typename Superclass::TCollision     TCollision;
+      typedef typename Superclass::TCollisionsRow TCollisionsRow;
+      typedef typename Superclass::TCollisions    TCollisions;
+
+      typedef itk::Image< unsigned long, _VDim > TMarks;
+
+    protected:
+      virtual bool _IsMarked( const TVertex& v ) const override;
+      virtual unsigned long _GetMark( const TVertex& v ) const override;
+      virtual void _Mark( const TVertex& v, unsigned long frontId ) override;
+      virtual void _FreeMarks( ) override;
+      virtual void _InitMarks( unsigned long nSeeds ) override;
+
+    protected:
+      MarksInterface( itk::ProcessObject* filter );
+      virtual ~MarksInterface( );
+
+    private:
+      typename TMarks::Pointer m_Marks;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Image/MarksInterface.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Image__MarksInterface__h__
+
+// eof - $RCSfile$
diff --git a/libs/fpa/Image/MarksInterface.hxx b/libs/fpa/Image/MarksInterface.hxx
new file mode 100644 (file)
index 0000000..47ed11f
--- /dev/null
@@ -0,0 +1,86 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__MarksInterface__hxx__
+#define __fpa__Image__MarksInterface__hxx__
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+bool fpa::Image::MarksInterface< _VDim >::
+_IsMarked( const TVertex& v ) const
+{
+  return( this->m_Marks->GetPixel( v ) != 0 );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+unsigned long fpa::Image::MarksInterface< _VDim >::
+_GetMark( const TVertex& v ) const
+{
+  return( this->m_Marks->GetPixel( v ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::Image::MarksInterface< _VDim >::
+_Mark( const TVertex& v, unsigned long frontId )
+{
+  this->m_Marks->SetPixel( v, frontId );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::Image::MarksInterface< _VDim >::
+_FreeMarks( )
+{
+  this->m_Marks = NULL;
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::Image::MarksInterface< _VDim >::
+_InitMarks( unsigned long nSeeds )
+{
+  this->Superclass::_InitMarks( nSeeds );
+
+  // Try to guess input
+  if( this->m_Filter == NULL )
+    return;
+  if( this->m_Filter->GetInputs( ).size( ) == 0 )
+    return;
+  itk::ImageBase< _VDim >* input =
+    dynamic_cast< itk::ImageBase< _VDim >* >(
+      this->m_Filter->GetInputs( )[ 0 ].GetPointer( )
+      );
+  if( input == NULL )
+    return;
+
+  // Reserve memory for marks
+  this->m_Marks = TMarks::New( );
+  this->m_Marks->CopyInformation( input );
+  this->m_Marks->SetRequestedRegion( input->GetRequestedRegion( ) );
+  this->m_Marks->SetBufferedRegion( input->GetBufferedRegion( ) );
+  this->m_Marks->Allocate( );
+  this->m_Marks->FillBuffer( false );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+fpa::Image::MarksInterface< _VDim >::
+MarksInterface( itk::ProcessObject* filter )
+  : Superclass( filter )
+{
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+fpa::Image::MarksInterface< _VDim >::
+~MarksInterface( )
+{
+}
+
+#endif // __fpa__Image__MarksInterface__hxx__
+
+// eof - $RCSfile$
index e21bbb91ce6e0015abe84fb5e57a453725455f81..f60847982cff93c6225b3138634e3b22999d6d7c 100644 (file)
@@ -9,6 +9,7 @@
 #include <itkImageToImageFilter.h>
 #include <itkFunctionBase.h>
 #include <fpa/Base/SeedsInterface.h>
+#include <fpa/Image/MarksInterface.h>
 
 namespace fpa
 {
@@ -19,7 +20,8 @@ namespace fpa
     template< class _TInputImage, class _TOutputImage >
     class RegionGrow
       : public itk::ImageToImageFilter< _TInputImage, _TOutputImage >,
-        public fpa::Base::SeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::IndexType::LexicographicCompare >
+        public fpa::Base::SeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::IndexType::LexicographicCompare >,
+        public fpa::Image::MarksInterface< _TInputImage::ImageDimension >
     {
     public:
       typedef _TInputImage  TInputImage;
@@ -36,6 +38,7 @@ namespace fpa
       typedef itk::SmartPointer< const Self >                    ConstPointer;
 
       typedef fpa::Base::SeedsInterface< TIndex, TIndexCompare > TSeedsInterface;
+      typedef fpa::Image::MarksInterface< _TInputImage::ImageDimension > TMarksInterface;
       typedef itk::FunctionBase< TInputPixel, bool > TIntensityFunctor;
 
     public:
@@ -68,9 +71,6 @@ namespace fpa
 
     protected:
       typename TIntensityFunctor::Pointer m_IntensityFunctor;
-      /* TODO
-         TSeeds m_Seeds;
-      */
       TOutputPixel m_InsideValue;
       TOutputPixel m_OutsideValue;
     };
index facd9f80956f7da34923a8ff7f84fe80e5db4ca5..2208070885b1795365d98543c9a1fa10e6e8fd46 100644 (file)
@@ -27,6 +27,7 @@ fpa::Image::RegionGrow< _TInputImage, _TOutputImage >::
 RegionGrow( )
   : Superclass( ),
     TSeedsInterface( this ),
+    TMarksInterface( this ),
     m_InsideValue( TInputPixel( 0 ) ),
     m_OutsideValue( TInputPixel( 0 ) )
 {
@@ -78,31 +79,27 @@ GenerateData( )
   output->FillBuffer( this->m_OutsideValue );
 
   // Init marks
-  typedef itk::Image< bool, TInputImage::ImageDimension > _TMarks;
-  typename _TMarks::Pointer marks = _TMarks::New( );
-  marks->CopyInformation( input );
-  marks->SetRequestedRegion( region );
-  marks->SetBufferedRegion( input->GetBufferedRegion( ) );
-  marks->Allocate( );
-  marks->FillBuffer( false );
+  this->_InitMarks( this->GetNumberOfSeeds( ) );
 
   // Init queue
-  std::queue< TIndex > q;
+  typedef std::pair< TIndex, unsigned long > _TNode;
+  std::queue< _TNode > q;
+  unsigned long frontId = 1;
   for( TIndex seed: this->GetSeeds( ) )
-    q.push( seed );
+    q.push( _TNode( seed, frontId++ ) );
 
   // Main loop
   while( q.size( ) > 0 )
   {
     // Get next candidate
-    TIndex node = q.front( );
+    _TNode node = q.front( );
     q.pop( );
-    if( marks->GetPixel( node ) )
+    if( this->_IsMarked( node.first ) )
       continue;
-    marks->SetPixel( node, true );
+    this->_Mark( node.first, node.second );
 
     // Apply inclusion predicate
-    TInputPixel value = input->GetPixel( node );
+    TInputPixel value = input->GetPixel( node.first );
     bool inside = false;
     if( this->m_IntensityFunctor.IsNotNull( ) )
       inside = this->m_IntensityFunctor->Evaluate( value );
@@ -110,23 +107,35 @@ GenerateData( )
       continue;
 
     // Ok, pixel lays inside region
-    output->SetPixel( node, this->m_InsideValue );
+    output->SetPixel( node.first, this->m_InsideValue );
 
     // Add neighborhood
     for( unsigned int d = 0; d < TInputImage::ImageDimension; ++d )
     {
-      TIndex neigh = node;
+      TIndex neigh = node.first;
       for( int i = -1; i <= 1; i += 2 )
       {
-        neigh[ d ] = node[ d ] + i;
+        neigh[ d ] = node.first[ d ] + i;
         if( region.IsInside( neigh ) )
-          q.push( neigh );
+        {
+          if( this->_IsMarked( neigh ) )
+          {
+            unsigned long nColl = this->_Collisions( node.first, neigh );
+            if( nColl == 1 && this->StopAtOneFront( ) )
+              while( q.size( ) > 0 )
+                q.pop( );
+          }
+          else
+            q.push( _TNode( neigh, node.second ) );
+
+        } // fi
 
       } // rof
 
     } // rof
 
   } // elihw
+  this->_FreeMarks( );
 }
 
 #endif // __fpa__Image__RegionGrow__hxx__