]> Creatis software - FrontAlgorithms.git/commitdiff
...
authorLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Thu, 23 Mar 2017 00:17:12 +0000 (19:17 -0500)
committerLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Thu, 23 Mar 2017 00:17:12 +0000 (19:17 -0500)
16 files changed:
examples/RegionGrow_BinaryThreshold.cxx
examples/RegionGrow_Mori.cxx
examples/RegionGrow_Tautology.cxx
libs/fpa/Base/Dijkstra.h [new file with mode: 0644]
libs/fpa/Base/Dijkstra.hxx [new file with mode: 0644]
libs/fpa/Base/MoriRegionGrow.h [new file with mode: 0644]
libs/fpa/Base/MoriRegionGrow.hxx [new file with mode: 0644]
libs/fpa/Base/RegionGrow.h [new file with mode: 0644]
libs/fpa/Base/RegionGrow.hxx [new file with mode: 0644]
libs/fpa/Image/Filter.h [new file with mode: 0644]
libs/fpa/Image/Filter.hxx [new file with mode: 0644]
libs/fpa/Image/MarksInterface.hxx
libs/fpa/Image/MoriRegionGrow.h
libs/fpa/Image/MoriRegionGrow.hxx [deleted file]
libs/fpa/Image/RegionGrow.h
libs/fpa/Image/RegionGrow.hxx [deleted file]

index d4908857a23bc48993b824869bc227b3f37d1342..3e0b95a79ebce495996f7f153e0615015c6413a2 100644 (file)
@@ -1,4 +1,3 @@
-#include <itkCommand.h>
 #include <itkImage.h>
 #include <itkImageFileReader.h>
 #include <itkImageFileWriter.h>
index 7fd51b4427fd73942c95e46d8ba51c6a44586ea5..cf20cfafd70d30b49e6583df461c44ecb8b44ed6 100644 (file)
@@ -1,18 +1,38 @@
+#include <iomanip>
 #include <itkCommand.h>
 #include <itkImage.h>
 #include <itkImageFileReader.h>
 #include <itkImageFileWriter.h>
+#include <itkBinaryThresholdImageFilter.h>
 
 #include <fpa/Image/MoriRegionGrow.h>
 
 // -------------------------------------------------------------------------
 static const unsigned int VDim = 3;
-typedef short                          TPixel;
-typedef itk::Image< TPixel, VDim >     TImage;
-typedef itk::ImageFileReader< TImage > TReader;
-typedef itk::ImageFileWriter< TImage > TWriter;
-typedef fpa::Image::MoriRegionGrow< TImage, TImage > TFilter;
-typedef itk::ImageFileWriter< TFilter::TAuxiliaryImage > TAuxWriter;
+typedef short                                             TPixel;
+typedef itk::Image< TPixel, VDim >                        TImage;
+typedef itk::ImageFileReader< TImage >                    TReader;
+typedef itk::ImageFileWriter< TImage >                    TWriter;
+typedef fpa::Image::MoriRegionGrow< TImage, TImage >      TFilter;
+typedef itk::BinaryThresholdImageFilter< TImage, TImage > TThreshold;
+
+// -------------------------------------------------------------------------
+class ShowProgressObject
+{
+public:
+  ShowProgressObject( itk::ProcessObject* o )
+    {
+      this->m_Process = o;
+    }
+  void ShowProgress( )
+    {
+      std::cerr
+        << "\rProgress " << std::fixed << std::setprecision( 2 )
+        << ( this->m_Process->GetProgress( ) * 100 )
+        << " %" << std::flush;
+    }
+  itk::ProcessObject::Pointer m_Process;
+};
 
 // -------------------------------------------------------------------------
 int main( int argc, char* argv[] )
@@ -45,16 +65,35 @@ int main( int argc, char* argv[] )
   TImage::IndexType seed;
   for( int i = 0; i < VDim; ++i )
     seed[ i ] = std::atoi( argv[ i + 7 ] );
-  filter->SetSeed( seed );
-  filter->SetInsideValue( 255 );
-  filter->SetOutsideValue( 0 );
+  filter->AddSeed( seed );
+
+  // to test ProgressReporter
+  ShowProgressObject progressWatch( filter );
+  typedef itk::SimpleMemberCommand< ShowProgressObject > CommandType;
+  CommandType::Pointer command = CommandType::New();
+  command->SetCallbackFunction( &progressWatch,
+                                &ShowProgressObject::ShowProgress );
+  filter->AddObserver( itk::ProgressEvent( ), command );
+  filter->Update( );
 
+  TThreshold::Pointer threshold = TThreshold::New( );
+  threshold->SetInput( filter->GetOutput( ) );
+  threshold->SetInsideValue( 255 );
+  threshold->SetOutsideValue( 0 );
+  threshold->SetLowerThreshold( 0 );
+  threshold->SetUpperThreshold( filter->GetOptimumThreshold( ) );
+  
   TWriter::Pointer writer = TWriter::New( );
-  writer->SetInput( filter->GetOutput( ) );
+  writer->SetInput( threshold->GetOutput( ) );
   writer->SetFileName( output_image_filename );
+
+  TWriter::Pointer aux_writer = TWriter::New( );
+  aux_writer->SetInput( filter->GetOutput( ) );
+  aux_writer->SetFileName( auxiliary_image_filename );
   try
   {
     writer->Update( );
+    aux_writer->Update( );
   }
   catch( std::exception& err )
   {
@@ -63,19 +102,20 @@ int main( int argc, char* argv[] )
 
   } // yrt
 
-  TAuxWriter::Pointer aux_writer = TAuxWriter::New( );
-  aux_writer->SetInput( filter->GetAuxiliaryImage( ) );
-  aux_writer->SetFileName( auxiliary_image_filename );
-  try
+  // Show data
+  TFilter::TCurve curve = filter->GetCurve( );
+  for( TFilter::TCurveData data: curve )
   {
-    aux_writer->Update( );
+    std::cout << data.XValue << " " << data.YValue << " " << data.Diff1 << std::endl;
   }
-  catch( std::exception& err )
-  {
-    std::cerr << "ERROR: " << err.what( ) << std::endl;
-    return( 1 );
-
-  } // yrt
+  std::cerr
+    << std::endl
+    << "# Opt: "
+    << curve[ filter->GetOptimumThreshold( ) ].XValue
+    << "("
+    << filter->GetOptimumThreshold( )
+    << ")"
+    << std::endl;
   return( 0 );
 }
 
index 88cdd0a8bd965422b5b0a4bba0fbb7cceef63399..8bee8560d8cd74a695166633f483e41ce30052b6 100644 (file)
@@ -1,4 +1,3 @@
-#include <itkCommand.h>
 #include <itkImage.h>
 #include <itkImageFileWriter.h>
 
diff --git a/libs/fpa/Base/Dijkstra.h b/libs/fpa/Base/Dijkstra.h
new file mode 100644 (file)
index 0000000..2c49c06
--- /dev/null
@@ -0,0 +1,92 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__Dijkstra__h__
+#define __fpa__Base__Dijkstra__h__
+
+#include <itkFunctionBase.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+    class Dijkstra
+      : public _TFilter,
+        public _TMarksInterface,
+        public _TSeedsInterface
+    {
+    public:
+      typedef Dijkstra                        Self;
+      typedef _TFilter                        Superclass;
+      typedef _TMarksInterface                TMarksInterface;
+      typedef _TSeedsInterface                TSeedsInterface;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename Superclass::TInputValue  TInputValue;
+      typedef typename Superclass::TOutputValue TOutputValue;
+      typedef typename Superclass::TVertex      TVertex;
+      typedef typename Superclass::TVertices    TVertices;
+
+      typedef itk::FunctionBase< TInputValue, TOutputValue > TIntensityFunctor;
+      typedef itk::FunctionBase< TVertex, TOutputValue >     TVertexFunctor;
+
+    protected:
+      struct _TNode
+      {
+        TVertex Vertex;
+        TVertex Parent;
+        TOutputValue Cost;
+        _TNode( const TVertex& v, const TVertex& p )
+          {
+            this->Vertex = v;
+            this->Parent = p;
+            this->Cost = TOutputValue( 0 );
+          }
+        bool operator<( const _TNode& b ) const
+          {
+            return( this->Cost < b.Cost );
+          }
+      };
+
+    public:
+      itkTypeMacro( Dijkstra, TFilter );
+
+    public:
+      const TIntensityFunctor* GetIntensityFunctor( ) const;
+      const TVertexFunctor* GetVertexFunctor( ) const;
+
+      void SetFunctor( TIntensityFunctor* functor );
+      void SetFunctor( TVertexFunctor* functor );
+
+    protected:
+      Dijkstra( );
+      virtual ~Dijkstra( );
+
+      virtual void GenerateData( ) override;
+
+    private:
+      Dijkstra( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      typename TIntensityFunctor::Pointer m_IntensityFunctor;
+      typename TVertexFunctor::Pointer m_VertexFunctor;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/Dijkstra.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__Dijkstra__h__
+
+// eof - $RCSfile$
diff --git a/libs/fpa/Base/Dijkstra.hxx b/libs/fpa/Base/Dijkstra.hxx
new file mode 100644 (file)
index 0000000..9e8e529
--- /dev/null
@@ -0,0 +1,83 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__Dijkstra__hxx__
+#define __fpa__Base__Dijkstra__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+const typename
+fpa::Base::Dijkstra< _TFilter, _TMarksInterface, _TSeedsInterface >::
+TIntensityFunctor*
+fpa::Base::Dijkstra< _TFilter, _TMarksInterface, _TSeedsInterface >::
+GetIntensityFunctor( ) const
+{
+  return( this->m_IntensityFunctor );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+const typename
+fpa::Base::Dijkstra< _TFilter, _TMarksInterface, _TSeedsInterface >::
+TVertexFunctor*
+fpa::Base::Dijkstra< _TFilter, _TMarksInterface, _TSeedsInterface >::
+GetVertexFunctor( ) const
+{
+  return( this->m_VertexFunctor );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void fpa::Base::Dijkstra< _TFilter, _TMarksInterface, _TSeedsInterface >::
+SetFunctor( TIntensityFunctor* functor )
+{
+  if( this->m_IntensityFunctor.GetPointer( ) != functor )
+  {
+    this->m_IntensityFunctor = functor;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void fpa::Base::Dijkstra< _TFilter, _TMarksInterface, _TSeedsInterface >::
+SetFunctor( TVertexFunctor* functor )
+{
+  if( this->m_VertexFunctor.GetPointer( ) != functor )
+  {
+    this->m_VertexFunctor = functor;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+fpa::Base::Dijkstra< _TFilter, _TMarksInterface, _TSeedsInterface >::
+Dijkstra( )
+  : Superclass( ),
+    _TMarksInterface( this ),
+    _TSeedsInterface( this )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+fpa::Base::Dijkstra< _TFilter, _TMarksInterface, _TSeedsInterface >::
+~Dijkstra( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void fpa::Base::Dijkstra< _TFilter, _TMarksInterface, _TSeedsInterface >::
+GenerateData( )
+{
+}
+
+#endif // __fpa__Base__Dijkstra__hxx__
+
+// eof - $RCSfile$
diff --git a/libs/fpa/Base/MoriRegionGrow.h b/libs/fpa/Base/MoriRegionGrow.h
new file mode 100644 (file)
index 0000000..d8f2ee0
--- /dev/null
@@ -0,0 +1,96 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__MoriRegionGrow__h__
+#define __fpa__Base__MoriRegionGrow__h__
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+    class MoriRegionGrow
+      : public _TFilter,
+        public _TMarksInterface,
+        public _TSeedsInterface
+    {
+    public:
+      typedef MoriRegionGrow                  Self;
+      typedef _TFilter                        Superclass;
+      typedef _TMarksInterface                TMarksInterface;
+      typedef _TSeedsInterface                TSeedsInterface;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename Superclass::TInputValue  TInputValue;
+      typedef typename Superclass::TOutputValue TOutputValue;
+      typedef typename Superclass::TVertex      TVertex;
+      typedef typename Superclass::TVertices    TVertices;
+
+      struct TCurveData
+      {
+        TInputValue XValue;
+        unsigned long YValue;
+        double Diff1;
+        TCurveData( TInputValue v, unsigned long c )
+          {
+            this->XValue = v;
+            this->YValue = c;
+            this->Diff1 = double( 0 );
+          }
+      };
+      typedef std::vector< TCurveData > TCurve;
+
+    public:
+      itkTypeMacro( MoriRegionGrow, TFilter );
+
+      itkGetConstMacro( LowerThreshold, TInputValue );
+      itkGetConstMacro( UpperThreshold, TInputValue );
+      itkGetConstMacro( DeltaThreshold, TInputValue );
+      itkGetConstMacro( Curve, TCurve );
+      itkGetConstMacro( OptimumThreshold, TInputValue );
+
+      itkSetMacro( LowerThreshold, TInputValue );
+      itkSetMacro( UpperThreshold, TInputValue );
+      itkSetMacro( DeltaThreshold, TInputValue );
+
+    public:
+      void SetThresholdRange(
+        const TInputValue& lower, const TInputValue& upper,
+        const TInputValue& delta = TInputValue( 1 )
+        );
+
+    protected:
+      MoriRegionGrow( );
+      virtual ~MoriRegionGrow( );
+
+      virtual void GenerateData( ) override;
+
+    private:
+      MoriRegionGrow( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      TInputValue  m_LowerThreshold;
+      TInputValue  m_UpperThreshold;
+      TInputValue  m_DeltaThreshold;
+
+      TCurve m_Curve;
+      TInputValue  m_OptimumThreshold;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/MoriRegionGrow.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__MoriRegionGrow__h__
+
+// eof - $RCSfile$
diff --git a/libs/fpa/Base/MoriRegionGrow.hxx b/libs/fpa/Base/MoriRegionGrow.hxx
new file mode 100644 (file)
index 0000000..b619bce
--- /dev/null
@@ -0,0 +1,186 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__MoriRegionGrow__hxx__
+#define __fpa__Base__MoriRegionGrow__hxx__
+
+#include <queue>
+#include <itkProgressReporter.h>
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void
+fpa::Base::MoriRegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+SetThresholdRange(
+  const TInputValue& lower, const TInputValue& upper,
+  const TInputValue& delta
+  )
+{
+  this->SetLowerThreshold( lower );
+  this->SetUpperThreshold( upper );
+  this->SetDeltaThreshold( delta );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+fpa::Base::MoriRegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+MoriRegionGrow( )
+  : Superclass( ),
+    _TMarksInterface( this ),
+    _TSeedsInterface( this )
+{
+  this->m_UpperThreshold = std::numeric_limits< TInputValue >::max( );
+  if( std::numeric_limits< TInputValue >::is_integer )
+    this->m_LowerThreshold = std::numeric_limits< TInputValue >::min( );
+  else
+    this->m_LowerThreshold = -this->m_UpperThreshold;
+  this->m_DeltaThreshold = TInputValue( 1 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+fpa::Base::MoriRegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+~MoriRegionGrow( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void
+fpa::Base::MoriRegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+GenerateData( )
+{
+  // Prepare progress counter
+  double prog_size = double( this->m_UpperThreshold - this->m_LowerThreshold );
+  prog_size /= double( this->m_DeltaThreshold );
+  itk::ProgressReporter progress( this, 0, prog_size, 100, 0, 1 );
+
+  // Init objects
+  this->_ConfigureOutputs( std::numeric_limits< TOutputValue >::max( ) );
+  this->_InitMarks( this->GetNumberOfSeeds( ) );
+
+  // Init queues
+  typedef std::pair< TVertex, unsigned long > _TNode;
+  std::queue< _TNode > queues[ 2 ];
+  unsigned long frontId = 1;
+  for( TVertex seed: this->GetSeeds( ) )
+    queues[ 0 ].push( _TNode( seed, frontId++ ) );
+  unsigned int cur_queue = 0;
+  unsigned int aux_queue = 1;
+
+  // Incremental strategy
+  TInputValue upper = this->m_LowerThreshold + this->m_DeltaThreshold;
+  this->m_Curve.clear( );
+  unsigned long count = 0;
+  while( upper <= this->m_UpperThreshold )
+  {
+    // Main growing strategy
+    while( queues[ cur_queue ].size( ) > 0 )
+    {
+      // Get next candidate
+      _TNode node = queues[ cur_queue ].front( );
+      queues[ cur_queue ].pop( );
+      if( this->_IsMarked( node.first ) )
+        continue;
+      this->_Mark( node.first, node.second );
+
+      // Apply inclusion predicate
+      TInputValue value = this->_GetInputValue( node.first );
+      bool in = ( ( this->m_LowerThreshold < value ) && ( value < upper ) );
+      if( !in )
+      {
+        if( value < this->m_UpperThreshold )
+          queues[ aux_queue ].push( node );
+        this->_Mark( node.first, 0 );
+        continue;
+
+      } // fi
+
+      // Ok, value lays inside region
+      this->_SetOutputValue( node.first, this->m_Curve.size( ) + 1 );
+      count++;
+
+      // Add neighborhood
+      TVertices neighbors = this->_GetNeighbors( node.first );
+      for( TVertex neigh: neighbors )
+      {
+        if( this->_IsMarked( neigh ) )
+        {
+          // Invoke stop at collisions
+          unsigned long nColl = this->_Collisions( node.first, neigh );
+          if(
+            this->StopAtOneFront( ) &&
+            this->GetNumberOfSeeds( ) > 1 &&
+            nColl == 1
+            )
+          {
+            while( queues[ 0 ].size( ) > 0 )
+              queues[ 0 ].pop( );
+            while( queues[ 1 ].size( ) > 0 )
+              queues[ 1 ].pop( );
+
+          } // fi
+        }
+        else
+          queues[ cur_queue ].push( _TNode( neigh, node.second ) );
+
+      } // rof
+
+    } // elihw
+
+    // Update curve
+    if( this->m_Curve.size( ) > 0 )
+    {
+      if( this->m_Curve.back( ).YValue < count )
+        this->m_Curve.push_back( TCurveData( upper, count ) );
+      if( this->m_Curve.size( ) > 2 )
+      {
+        long j = this->m_Curve.size( ) - 2;
+        double yp = double( this->m_Curve[ j + 1 ].YValue );
+        double yn = double( this->m_Curve[ j - 1 ].YValue );
+        double xp = double( this->m_Curve[ j + 1 ].XValue );
+        double xn = double( this->m_Curve[ j - 1 ].XValue );
+        this->m_Curve[ j ].Diff1 = ( yp - yn ) / ( xp - xn );
+
+      } // fi
+    }
+    else
+      this->m_Curve.push_back( TCurveData( upper, count ) );
+
+    // Update queue
+    cur_queue = aux_queue;
+    aux_queue = ( cur_queue + 1 ) % 2;
+
+    // Update threshold
+    upper += this->m_DeltaThreshold;
+    progress.CompletedPixel( );
+
+  } // elihw
+
+  // Compute optimum threshold
+  double dmax = -std::numeric_limits< double >::max( );
+  long jmax = 0;
+  for( long j = 1; j < this->m_Curve.size( ) - 1; ++j )
+  {
+    double dp = this->m_Curve[ j + 1 ].Diff1;
+    double dn = this->m_Curve[ j - 1 ].Diff1;
+    double xp = double( this->m_Curve[ j + 1 ].XValue );
+    double xn = double( this->m_Curve[ j - 1 ].XValue );
+    double d2 = ( dp - dn ) / ( xp - xn );
+    if( d2 > dmax )
+    {
+      dmax = d2;
+      jmax = j;
+
+    } // fi
+
+  } // rof
+  this->m_OptimumThreshold = TOutputValue( jmax );
+  this->_FreeMarks( );
+}
+
+#endif // __fpa__Base__MoriRegionGrow__hxx__
+
+// eof - $RCSfile$
diff --git a/libs/fpa/Base/RegionGrow.h b/libs/fpa/Base/RegionGrow.h
new file mode 100644 (file)
index 0000000..2586033
--- /dev/null
@@ -0,0 +1,82 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__RegionGrow__h__
+#define __fpa__Base__RegionGrow__h__
+
+#include <itkFunctionBase.h>
+
+namespace fpa
+{
+  namespace Base
+  {
+    /**
+     */
+    template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+    class RegionGrow
+      : public _TFilter,
+        public _TMarksInterface,
+        public _TSeedsInterface
+    {
+    public:
+      typedef RegionGrow                      Self;
+      typedef _TFilter                        Superclass;
+      typedef _TMarksInterface                TMarksInterface;
+      typedef _TSeedsInterface                TSeedsInterface;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename Superclass::TInputValue  TInputValue;
+      typedef typename Superclass::TOutputValue TOutputValue;
+      typedef typename Superclass::TVertex      TVertex;
+      typedef typename Superclass::TVertices    TVertices;
+
+      typedef itk::FunctionBase< TInputValue, bool > TIntensityFunctor;
+      typedef itk::FunctionBase< TVertex, bool >     TVertexFunctor;
+
+    public:
+      itkTypeMacro( RegionGrow, TFilter );
+
+      itkGetConstMacro( InsideValue, TOutputValue );
+      itkGetConstMacro( OutsideValue, TOutputValue );
+
+      itkSetMacro( InsideValue, TOutputValue );
+      itkSetMacro( OutsideValue, TOutputValue );
+
+    public:
+      const TIntensityFunctor* GetIntensityPredicate( ) const;
+      const TVertexFunctor* GetVertexPredicate( ) const;
+
+      void SetPredicate( TIntensityFunctor* functor );
+      void SetPredicate( TVertexFunctor* functor );
+
+    protected:
+      RegionGrow( );
+      virtual ~RegionGrow( );
+
+      virtual void GenerateData( ) override;
+
+    private:
+      RegionGrow( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      typename TIntensityFunctor::Pointer m_IntensityFunctor;
+      typename TVertexFunctor::Pointer m_VertexFunctor;
+      TOutputValue m_InsideValue;
+      TOutputValue m_OutsideValue;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Base/RegionGrow.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Base__RegionGrow__h__
+
+// eof - $RCSfile$
diff --git a/libs/fpa/Base/RegionGrow.hxx b/libs/fpa/Base/RegionGrow.hxx
new file mode 100644 (file)
index 0000000..9e7bb7b
--- /dev/null
@@ -0,0 +1,147 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Base__RegionGrow__hxx__
+#define __fpa__Base__RegionGrow__hxx__
+
+#include <queue>
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+const typename
+fpa::Base::RegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+TIntensityFunctor*
+fpa::Base::RegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+GetIntensityPredicate( ) const
+{
+  return( this->m_IntensityFunctor );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+const typename
+fpa::Base::RegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+TVertexFunctor*
+fpa::Base::RegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+GetVertexPredicate( ) const
+{
+  return( this->m_VertexFunctor );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void
+fpa::Base::RegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+SetPredicate( TIntensityFunctor* functor )
+{
+  if( this->m_IntensityFunctor.GetPointer( ) != functor )
+  {
+    this->m_IntensityFunctor = functor;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void
+fpa::Base::RegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+SetPredicate( TVertexFunctor* functor )
+{
+  if( this->m_VertexFunctor.GetPointer( ) != functor )
+  {
+    this->m_VertexFunctor = functor;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+fpa::Base::RegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+RegionGrow( )
+  : Superclass( ),
+    _TMarksInterface( this ),
+    _TSeedsInterface( this ),
+    m_InsideValue( TOutputValue( 1 ) ),
+    m_OutsideValue( TOutputValue( 0 ) )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+fpa::Base::RegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+~RegionGrow( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TMarksInterface, class _TSeedsInterface >
+void
+fpa::Base::RegionGrow< _TFilter, _TMarksInterface, _TSeedsInterface >::
+GenerateData( )
+{
+  // Init objects
+  this->_ConfigureOutputs( this->m_OutsideValue );
+  this->_InitMarks( this->GetNumberOfSeeds( ) );
+
+  // Init queue
+  typedef std::pair< TVertex, unsigned long > _TNode;
+  std::queue< _TNode > q;
+  unsigned long frontId = 1;
+  for( TVertex seed: this->GetSeeds( ) )
+    q.push( _TNode( seed, frontId++ ) );
+
+  // Main loop
+  while( q.size( ) > 0 )
+  {
+    // Get next candidate
+    _TNode node = q.front( );
+    q.pop( );
+    if( this->_IsMarked( node.first ) )
+      continue;
+    this->_Mark( node.first, node.second );
+
+    // Apply inclusion predicate
+    TInputValue value = this->_GetInputValue( node.first );
+    bool inside = false;
+    if( this->m_IntensityFunctor.IsNotNull( ) )
+      inside = this->m_IntensityFunctor->Evaluate( value );
+    if( this->m_VertexFunctor.IsNotNull( ) )
+      inside &= this->m_VertexFunctor->Evaluate( node.first );
+    if( !inside )
+      continue;
+
+    // Ok, pixel lays inside region
+    this->_SetOutputValue( node.first, this->m_InsideValue );
+
+    // Add neighborhood
+    TVertices neighbors = this->_GetNeighbors( node.first );
+    for( TVertex neigh: neighbors )
+    {
+      if( this->_IsMarked( neigh ) )
+      {
+        // Invoke stop at collisions
+        unsigned long nColl = this->_Collisions( node.first, neigh );
+        if(
+          this->StopAtOneFront( ) &&
+          this->GetNumberOfSeeds( ) > 1 &&
+          nColl == 1
+          )
+          while( q.size( ) > 0 )
+            q.pop( );
+      }
+      else
+        q.push( _TNode( neigh, node.second ) );
+
+    } // rof
+
+  } // elihw
+  this->_FreeMarks( );
+}
+
+#endif // __fpa__Base__RegionGrow__hxx__
+
+// eof - $RCSfile$
diff --git a/libs/fpa/Image/Filter.h b/libs/fpa/Image/Filter.h
new file mode 100644 (file)
index 0000000..ab86f81
--- /dev/null
@@ -0,0 +1,60 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__Filter__h__
+#define __fpa__Image__Filter__h__
+
+#include <vector>
+#include <itkImageToImageFilter.h>
+
+namespace fpa
+{
+  namespace Image
+  {
+    /**
+     */
+    template< class _TInputImage, class _TOutputImage >
+    class Filter
+      : public itk::ImageToImageFilter< _TInputImage, _TOutputImage >
+    {
+    public:
+      typedef Filter Self;
+      typedef itk::ImageToImageFilter< _TInputImage, _TOutputImage > Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TInputImage TInputImage;
+      typedef _TOutputImage TOutputImage;
+
+      typedef typename TInputImage::IndexType  TVertex;
+      typedef typename TInputImage::PixelType  TInputValue;
+      typedef typename TOutputImage::PixelType TOutputValue;
+
+      typedef std::vector< TVertex > TVertices;
+
+    protected:
+      Filter( );
+      virtual ~Filter( );
+
+      virtual void GenerateInputRequestedRegion( ) override;
+      virtual void EnlargeOutputRequestedRegion( itk::DataObject* output ) override;
+
+      virtual TInputValue _GetInputValue( const TVertex& vertex ) const;
+      virtual void _SetOutputValue( const TVertex& vertex, const TOutputValue& value );
+      virtual void _ConfigureOutputs( const TOutputValue& init_value );
+      virtual TVertices _GetNeighbors( const TVertex& vertex ) const;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Image/Filter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Image__Filter__h__
+
+// eof - $RCSfile$
diff --git a/libs/fpa/Image/Filter.hxx b/libs/fpa/Image/Filter.hxx
new file mode 100644 (file)
index 0000000..ad8053b
--- /dev/null
@@ -0,0 +1,103 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__Image__Filter__hxx__
+#define __fpa__Image__Filter__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage >
+fpa::Image::Filter< _TInputImage, _TOutputImage >::
+Filter( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage >
+fpa::Image::Filter< _TInputImage, _TOutputImage >::
+~Filter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage >
+void fpa::Image::Filter< _TInputImage, _TOutputImage >::
+GenerateInputRequestedRegion( )
+{
+  this->Superclass::GenerateInputRequestedRegion( );
+  if( this->GetInput( ) )
+  {
+    TInputImage* input = const_cast< TInputImage* >( this->GetInput( ) );
+    input->SetRequestedRegionToLargestPossibleRegion( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage >
+void fpa::Image::Filter< _TInputImage, _TOutputImage >::
+EnlargeOutputRequestedRegion( itk::DataObject* output )
+{
+  this->Superclass::EnlargeOutputRequestedRegion( output );
+  output->SetRequestedRegionToLargestPossibleRegion( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage >
+typename fpa::Image::Filter< _TInputImage, _TOutputImage >::
+TInputValue fpa::Image::Filter< _TInputImage, _TOutputImage >::
+_GetInputValue( const TVertex& vertex ) const
+{
+  return( this->GetInput( )->GetPixel( vertex ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage >
+void fpa::Image::Filter< _TInputImage, _TOutputImage >::
+_SetOutputValue( const TVertex& vertex, const TOutputValue& value )
+{
+  this->GetOutput( )->SetPixel( vertex, value );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage >
+void fpa::Image::Filter< _TInputImage, _TOutputImage >::
+_ConfigureOutputs( const TOutputValue& init_value )
+{
+  const TInputImage* input = this->GetInput( );
+  TOutputImage* output = this->GetOutput( );
+  output->SetBufferedRegion( input->GetRequestedRegion( ) );
+  output->Allocate( );
+  output->FillBuffer( init_value );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage >
+typename fpa::Image::Filter< _TInputImage, _TOutputImage >::
+TVertices fpa::Image::Filter< _TInputImage, _TOutputImage >::
+_GetNeighbors( const TVertex& vertex ) const
+{
+  typename TInputImage::RegionType region =
+    this->GetInput( )->GetRequestedRegion( );
+
+  TVertices vertices;
+  for( unsigned int d = 0; d < TInputImage::ImageDimension; ++d )
+  {
+    TVertex n = vertex;
+    for( int a = -1; a <= 1; a += 2 )
+    {
+      n[ d ] = vertex[ d ] + a;
+      if( region.IsInside( n ) )
+        vertices.push_back( n );
+
+    } // rof
+
+  } // rof
+  return( vertices );
+}
+
+#endif // __fpa__Image__Filter__hxx__
+
+// eof - $RCSfile$
index 47ed11fd6ba137815d7aec07840a73eecc646e2b..4d639acda2645f947a4883d2dff477c5e2a36858 100644 (file)
@@ -63,7 +63,7 @@ _InitMarks( unsigned long nSeeds )
   this->m_Marks->SetRequestedRegion( input->GetRequestedRegion( ) );
   this->m_Marks->SetBufferedRegion( input->GetBufferedRegion( ) );
   this->m_Marks->Allocate( );
-  this->m_Marks->FillBuffer( false );
+  this->m_Marks->FillBuffer( 0 );
 }
 
 // -------------------------------------------------------------------------
index 606d4f7c0a0ca1a4541abb36ae817968979de917..182e004ba04e7cdc35ea34417a8dfc087ea338f2 100644 (file)
@@ -6,8 +6,10 @@
 #ifndef __fpa__Image__MoriRegionGrow__h__
 #define __fpa__Image__MoriRegionGrow__h__
 
-#include <itkImageToImageFilter.h>
-#include <itkBinaryThresholdImageFilter.h>
+#include <fpa/Base/MoriRegionGrow.h>
+#include <fpa/Base/SeedsInterface.h>
+#include <fpa/Image/MarksInterface.h>
+#include <fpa/Image/Filter.h>
 
 namespace fpa
 {
@@ -15,106 +17,39 @@ namespace fpa
   {
     /**
      */
-    template< class _TInputImage, class _TOutputImage, class _TAuxiliaryPixel = unsigned short >
+    template< class _TInputImage, class _TOutputImage >
     class MoriRegionGrow
-      : public itk::ImageToImageFilter< _TInputImage, _TOutputImage >
+      : public fpa::Base::MoriRegionGrow< fpa::Image::Filter< _TInputImage, _TOutputImage >, fpa::Image::MarksInterface< _TInputImage::ImageDimension >, fpa::Base::SeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::IndexType::LexicographicCompare > >
     {
     public:
-      typedef _TInputImage  TInputImage;
-      typedef _TOutputImage TOutputImage;
-      typedef _TAuxiliaryPixel TAuxiliaryPixel;
-      typedef itk::Image< TAuxiliaryPixel, TInputImage::ImageDimension > TAuxiliaryImage;
+      // Interfaces
+      typedef fpa::Image::Filter< _TInputImage, _TOutputImage > TFilter;
+      typedef fpa::Image::MarksInterface< _TInputImage::ImageDimension > TMarksInterface;
+      typedef fpa::Base::SeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::IndexType::LexicographicCompare > TSeedsInterface;
 
-      typedef MoriRegionGrow                                             Self;
-      typedef itk::ImageToImageFilter< TInputImage, TOutputImage > Superclass;
-      typedef itk::SmartPointer< Self >                               Pointer;
-      typedef itk::SmartPointer< const Self >                    ConstPointer;
-
-      typedef typename TInputImage::IndexType  TIndex;
-      typedef typename TInputImage::RegionType TRegion;
-      typedef typename TInputImage::PixelType  TInputPixel;
-      typedef typename TOutputImage::PixelType TOutputPixel;
-
-      struct TCurveData
-      {
-        TInputPixel XValue;
-        unsigned long YValue;
-        double Diff1;
-        TCurveData( TInputPixel v, unsigned long c )
-          {
-            this->XValue = v;
-            this->YValue = c;
-            this->Diff1 = double( 0 );
-          }
-      };
-      typedef std::vector< TCurveData > TCurve;
-      typedef itk::BinaryThresholdImageFilter< TAuxiliaryImage, TOutputImage > TThresholdFilter;
+      // Smart pointers
+      typedef MoriRegionGrow Self;
+      typedef fpa::Base::MoriRegionGrow< TFilter, TMarksInterface, TSeedsInterface > Superclass;
+      typedef itk::SmartPointer< Self > Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
 
     public:
       itkNewMacro( Self );
-      itkTypeMacro( fpa::Image::MoriRegionGrow, itk::ImageToImageFilter );
-
-      itkGetConstMacro( Seed, TIndex );
-      itkGetConstMacro( InsideValue, TOutputPixel );
-      itkGetConstMacro( OutsideValue, TOutputPixel );
-      itkGetConstMacro( LowerThreshold, TInputPixel );
-      itkGetConstMacro( UpperThreshold, TInputPixel );
-      itkGetConstMacro( DeltaThreshold, TInputPixel );
-      itkGetConstMacro( OptimumThreshold, TInputPixel );
-      itkGetConstMacro( Curve, TCurve );
-
-      itkSetMacro( Seed, TIndex );
-      itkSetMacro( InsideValue, TOutputPixel );
-      itkSetMacro( OutsideValue, TOutputPixel );
-      itkSetMacro( LowerThreshold, TInputPixel );
-      itkSetMacro( UpperThreshold, TInputPixel );
-      itkSetMacro( DeltaThreshold, TInputPixel );
-
-    public:
-      TAuxiliaryImage* GetAuxiliaryImage( );
-      const TAuxiliaryImage* GetAuxiliaryImage( ) const;
-
-      void SetThresholdRange(
-        const TInputPixel& lower, const TInputPixel& upper,
-        const TInputPixel& delta = TInputPixel( 1 )
-        );
+      itkTypeMacro( fpa::Image::MoriRegionGrow, fpa::Base::MoriRegionGrow );
 
     protected:
-      MoriRegionGrow( );
-      virtual ~MoriRegionGrow( );
-
-      virtual void GenerateInputRequestedRegion( ) override;
-      virtual void EnlargeOutputRequestedRegion(
-        itk::DataObject* output
-        ) override;
-      virtual void GenerateData( ) override;
+      MoriRegionGrow( ) : Superclass( ) { }
+      virtual ~MoriRegionGrow( )        { }
 
     private:
-      // Purposely not implemented
       MoriRegionGrow( const Self& other );
       Self& operator=( const Self& other );
-
-    protected:
-      TIndex       m_Seed;
-      TOutputPixel m_InsideValue;
-      TOutputPixel m_OutsideValue;
-      TInputPixel  m_LowerThreshold;
-      TInputPixel  m_UpperThreshold;
-      TInputPixel  m_DeltaThreshold;
-      TInputPixel  m_OptimumThreshold;
-
-      TCurve m_Curve;
-      typename TThresholdFilter::Pointer m_ThresholdFilter;
     };
 
   } // ecapseman
 
 } // ecapseman
 
-#ifndef ITK_MANUAL_INSTANTIATION
-#  include <fpa/Image/MoriRegionGrow.hxx>
-#endif // ITK_MANUAL_INSTANTIATION
-
 #endif // __fpa__Image__MoriRegionGrow__h__
 
 // eof - $RCSfile$
diff --git a/libs/fpa/Image/MoriRegionGrow.hxx b/libs/fpa/Image/MoriRegionGrow.hxx
deleted file mode 100644 (file)
index 5efdf65..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-// =========================================================================
-// @author Leonardo Florez Valencia
-// @email florez-l@javeriana.edu.co
-// =========================================================================
-
-#ifndef __fpa__Image__MoriRegionGrow__hxx__
-#define __fpa__Image__MoriRegionGrow__hxx__
-
-#include <queue>
-#include <itkProgressReporter.h>
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage, class _TAuxiliaryPixel >
-typename
-fpa::Image::MoriRegionGrow< _TInputImage, _TOutputImage, _TAuxiliaryPixel >::
-TAuxiliaryImage*
-fpa::Image::MoriRegionGrow< _TInputImage, _TOutputImage, _TAuxiliaryPixel >::
-GetAuxiliaryImage( )
-{
-  return(
-    dynamic_cast< TAuxiliaryImage* >(
-      this->itk::ProcessObject::GetOutput( 1 )
-      )
-    );
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage, class _TAuxiliaryPixel >
-const typename
-fpa::Image::MoriRegionGrow< _TInputImage, _TOutputImage, _TAuxiliaryPixel >::
-TAuxiliaryImage*
-fpa::Image::MoriRegionGrow< _TInputImage, _TOutputImage, _TAuxiliaryPixel >::
-GetAuxiliaryImage( ) const
-{
-  return(
-    dynamic_cast< const TAuxiliaryImage* >(
-      this->itk::ProcessObject::GetOutput( 1 )
-      )
-    );
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage, class _TAuxiliaryPixel >
-void
-fpa::Image::MoriRegionGrow< _TInputImage, _TOutputImage, _TAuxiliaryPixel >::
-SetThresholdRange(
-  const TInputPixel& lower, const TInputPixel& upper,
-  const TInputPixel& delta
-  )
-{
-  this->SetLowerThreshold( lower );
-  this->SetUpperThreshold( upper );
-  this->SetDeltaThreshold( delta );
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage, class _TAuxiliaryPixel >
-fpa::Image::MoriRegionGrow< _TInputImage, _TOutputImage, _TAuxiliaryPixel >::
-MoriRegionGrow( )
-  : Superclass( )
-{
-  this->m_InsideValue = TOutputPixel( 1 );
-  this->m_OutsideValue = TOutputPixel( 0 );
-  this->m_UpperThreshold = std::numeric_limits< TInputPixel >::max( );
-  if( std::numeric_limits< TInputPixel >::is_integer )
-    this->m_LowerThreshold = std::numeric_limits< TInputPixel >::min( );
-  else
-    this->m_LowerThreshold = -this->m_UpperThreshold;
-  this->m_DeltaThreshold = TInputPixel( 1 );
-
-  this->SetNumberOfRequiredOutputs( 2 );
-  this->SetNthOutput( 0, TOutputImage::New( ) );
-  this->SetNthOutput( 1, TAuxiliaryImage::New( ) );
-
-  this->m_ThresholdFilter = TThresholdFilter::New( );
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage, class _TAuxiliaryPixel >
-fpa::Image::MoriRegionGrow< _TInputImage, _TOutputImage, _TAuxiliaryPixel >::
-~MoriRegionGrow( )
-{
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage, class _TAuxiliaryPixel >
-void
-fpa::Image::MoriRegionGrow< _TInputImage, _TOutputImage, _TAuxiliaryPixel >::
-GenerateInputRequestedRegion( )
-{
-  this->Superclass::GenerateInputRequestedRegion( );
-  if( this->GetInput( ) )
-  {
-    TInputImage* input =
-      const_cast< TInputImage* >( this->GetInput( ) );
-    input->SetRequestedRegionToLargestPossibleRegion( );
-
-  } // fi
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage, class _TAuxiliaryPixel >
-void
-fpa::Image::MoriRegionGrow< _TInputImage, _TOutputImage, _TAuxiliaryPixel >::
-EnlargeOutputRequestedRegion( itk::DataObject* output )
-{
-  this->Superclass::EnlargeOutputRequestedRegion( output );
-  output->SetRequestedRegionToLargestPossibleRegion( );
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage, class _TAuxiliaryPixel >
-void fpa::Image::MoriRegionGrow< _TInputImage, _TOutputImage, _TAuxiliaryPixel >::
-GenerateData( )
-{
-  const TInputImage* input = this->GetInput( );
-  TAuxiliaryImage* auxiliary = this->GetAuxiliaryImage( );
-  TRegion region = input->GetRequestedRegion( );
-
-  // Prepare progress counter
-  double prog_size = double( this->m_UpperThreshold - this->m_LowerThreshold );
-  prog_size /= double( this->m_DeltaThreshold );
-  itk::ProgressReporter progress( this, 0, prog_size, 100, 0, 0.7 );
-
-  // Configure outputs
-  auxiliary->SetBufferedRegion( region );
-  auxiliary->Allocate( );
-  auxiliary->FillBuffer( 0 );
-
-  // 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 );
-
-  // Prepare queues
-  std::queue< TIndex > queues[ 2 ];
-  queues[ 0 ].push( this->m_Seed );
-  unsigned int cur_queue = 0;
-  unsigned int aux_queue = 1;
-
-  // Incremental strategy
-  TInputPixel upper = this->m_LowerThreshold + this->m_DeltaThreshold;
-  this->m_Curve.clear( );
-  unsigned long count = 0;
-  while( upper <= this->m_UpperThreshold )
-  {
-    // Main growing strategy
-    while( queues[ cur_queue ].size( ) > 0 )
-    {
-      // Get next candidate
-      TIndex node = queues[ cur_queue ].front( );
-      queues[ cur_queue ].pop( );
-      if( marks->GetPixel( node ) )
-        continue;
-      marks->SetPixel( node, true );
-
-      // Apply inclusion predicate
-      TInputPixel value = input->GetPixel( node );
-      bool in = ( ( this->m_LowerThreshold < value ) && ( value < upper ) );
-      if( !in )
-      {
-        if( value < this->m_UpperThreshold )
-          queues[ aux_queue ].push( node );
-        marks->SetPixel( node, false );
-        continue;
-
-      } // fi
-
-      // Ok, pixel lays inside region
-      auxiliary->SetPixel( node, this->m_Curve.size( ) + 1 );
-      count++;
-
-      // Add neighborhood
-      for( unsigned int d = 0; d < TInputImage::ImageDimension; ++d )
-      {
-        TIndex neigh = node;
-        for( int i = -1; i <= 1; i += 2 )
-        {
-          neigh[ d ] = node[ d ] + i;
-          if( region.IsInside( neigh ) )
-            queues[ cur_queue ].push( neigh );
-
-        } // rof
-
-      } // rof
-
-    } // elihw
-
-    // Update curve
-    if( this->m_Curve.size( ) > 0 )
-    {
-      if( this->m_Curve.back( ).YValue < count )
-        this->m_Curve.push_back( TCurveData( upper, count ) );
-      if( this->m_Curve.size( ) > 2 )
-      {
-        long j = this->m_Curve.size( ) - 2;
-        double yp = double( this->m_Curve[ j + 1 ].YValue );
-        double yn = double( this->m_Curve[ j - 1 ].YValue );
-        double xp = double( this->m_Curve[ j + 1 ].XValue );
-        double xn = double( this->m_Curve[ j - 1 ].XValue );
-        this->m_Curve[ j ].Diff1 = ( yp - yn ) / ( xp - xn );
-
-      } // fi
-    }
-    else
-      this->m_Curve.push_back( TCurveData( upper, count ) );
-
-    // Update queue
-    cur_queue = aux_queue;
-    aux_queue = ( cur_queue + 1 ) % 2;
-
-    // Update threshold
-    upper += this->m_DeltaThreshold;
-    progress.CompletedPixel( );
-
-  } // elihw
-
-  // Compute optimum threshold
-  double dmax = -std::numeric_limits< double >::max( );
-  int jmax = 0;
-  for( int j = 1; j < this->m_Curve.size( ) - 1; ++j )
-  {
-    double dp = this->m_Curve[ j + 1 ].Diff1;
-    double dn = this->m_Curve[ j - 1 ].Diff1;
-    double xp = double( this->m_Curve[ j + 1 ].XValue );
-    double xn = double( this->m_Curve[ j - 1 ].XValue );
-    double d2 = ( dp - dn ) / ( xp - xn );
-    if( d2 > dmax )
-    {
-      dmax = d2;
-      jmax = j;
-
-    } // fi
-
-  } // rof
-  this->m_OptimumThreshold = this->m_Curve[ jmax ].XValue;
-
-  // Final threshold
-  this->m_ThresholdFilter->SetInput( auxiliary );
-  this->m_ThresholdFilter->SetInsideValue( this->m_InsideValue );
-  this->m_ThresholdFilter->SetOutsideValue( this->m_OutsideValue );
-  this->m_ThresholdFilter->SetLowerThreshold( 1 );
-  this->m_ThresholdFilter->SetUpperThreshold( jmax );
-  this->m_ThresholdFilter->Update( );
-  this->GetOutput( )->Graft( this->m_ThresholdFilter->GetOutput( ) );
-}
-
-#endif // __fpa__Image__MoriRegionGrow__hxx__
-
-// eof - $RCSfile$
index f60847982cff93c6225b3138634e3b22999d6d7c..5d7b4db227fabcbf2aeda4fd19f4b09a3041400b 100644 (file)
@@ -6,10 +6,10 @@
 #ifndef __fpa__Image__RegionGrow__h__
 #define __fpa__Image__RegionGrow__h__
 
-#include <itkImageToImageFilter.h>
-#include <itkFunctionBase.h>
+#include <fpa/Base/RegionGrow.h>
 #include <fpa/Base/SeedsInterface.h>
 #include <fpa/Image/MarksInterface.h>
+#include <fpa/Image/Filter.h>
 
 namespace fpa
 {
@@ -19,70 +19,37 @@ 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::Image::MarksInterface< _TInputImage::ImageDimension >
+      : public fpa::Base::RegionGrow< fpa::Image::Filter< _TInputImage, _TOutputImage >, fpa::Image::MarksInterface< _TInputImage::ImageDimension >, fpa::Base::SeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::IndexType::LexicographicCompare > >
     {
     public:
-      typedef _TInputImage  TInputImage;
-      typedef _TOutputImage TOutputImage;
-      typedef typename TInputImage::IndexType  TIndex;
-      typedef typename TInputImage::RegionType TRegion;
-      typedef typename TInputImage::PixelType  TInputPixel;
-      typedef typename TOutputImage::PixelType TOutputPixel;
-      typedef typename TIndex::LexicographicCompare TIndexCompare;
-
-      typedef RegionGrow                                                 Self;
-      typedef itk::ImageToImageFilter< TInputImage, TOutputImage > Superclass;
-      typedef itk::SmartPointer< Self >                               Pointer;
-      typedef itk::SmartPointer< const Self >                    ConstPointer;
-
-      typedef fpa::Base::SeedsInterface< TIndex, TIndexCompare > TSeedsInterface;
+      // Interfaces
+      typedef fpa::Image::Filter< _TInputImage, _TOutputImage > TFilter;
       typedef fpa::Image::MarksInterface< _TInputImage::ImageDimension > TMarksInterface;
-      typedef itk::FunctionBase< TInputPixel, bool > TIntensityFunctor;
-
-    public:
-      itkNewMacro( Self );
-      itkTypeMacro( fpa::Image::RegionGrow, itk::ImageToImageFilter );
-
-      itkGetConstMacro( InsideValue, TOutputPixel );
-      itkGetConstMacro( OutsideValue, TOutputPixel );
+      typedef fpa::Base::SeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::IndexType::LexicographicCompare > TSeedsInterface;
 
-      itkSetMacro( InsideValue, TOutputPixel );
-      itkSetMacro( OutsideValue, TOutputPixel );
+      // Smart pointers
+      typedef RegionGrow Self;
+      typedef fpa::Base::RegionGrow< TFilter, TMarksInterface, TSeedsInterface > Superclass;
+      typedef itk::SmartPointer< Self > Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
 
     public:
-      void SetPredicate( TIntensityFunctor* functor );
+      itkNewMacro( Self );
+      itkTypeMacro( fpa::Image::RegionGrow, fpa::Base::RegionGrow );
 
     protected:
-      RegionGrow( );
-      virtual ~RegionGrow( );
-
-      virtual void GenerateInputRequestedRegion( ) override;
-      virtual void EnlargeOutputRequestedRegion(
-        itk::DataObject* output
-        ) override;
-      virtual void GenerateData( ) override;
+      RegionGrow( ) : Superclass( ) { }
+      virtual ~RegionGrow( )        { }
 
     private:
-      // Purposely not implemented
       RegionGrow( const Self& other );
       Self& operator=( const Self& other );
-
-    protected:
-      typename TIntensityFunctor::Pointer m_IntensityFunctor;
-      TOutputPixel m_InsideValue;
-      TOutputPixel m_OutsideValue;
     };
 
   } // ecapseman
 
 } // ecapseman
 
-#ifndef ITK_MANUAL_INSTANTIATION
-#  include <fpa/Image/RegionGrow.hxx>
-#endif // ITK_MANUAL_INSTANTIATION
-
 #endif // __fpa__Image__RegionGrow__h__
 
 // eof - $RCSfile$
diff --git a/libs/fpa/Image/RegionGrow.hxx b/libs/fpa/Image/RegionGrow.hxx
deleted file mode 100644 (file)
index 2208070..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-// =========================================================================
-// @author Leonardo Florez Valencia
-// @email florez-l@javeriana.edu.co
-// =========================================================================
-
-#ifndef __fpa__Image__RegionGrow__hxx__
-#define __fpa__Image__RegionGrow__hxx__
-
-#include <queue>
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage >
-void fpa::Image::RegionGrow< _TInputImage, _TOutputImage >::
-SetPredicate( TIntensityFunctor* functor )
-{
-  if( this->m_IntensityFunctor.GetPointer( ) != functor )
-  {
-    this->m_IntensityFunctor = functor;
-    this->Modified( );
-
-  } // fi
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage >
-fpa::Image::RegionGrow< _TInputImage, _TOutputImage >::
-RegionGrow( )
-  : Superclass( ),
-    TSeedsInterface( this ),
-    TMarksInterface( this ),
-    m_InsideValue( TInputPixel( 0 ) ),
-    m_OutsideValue( TInputPixel( 0 ) )
-{
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage >
-fpa::Image::RegionGrow< _TInputImage, _TOutputImage >::
-~RegionGrow( )
-{
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage >
-void fpa::Image::RegionGrow< _TInputImage, _TOutputImage >::
-GenerateInputRequestedRegion( )
-{
-  this->Superclass::GenerateInputRequestedRegion( );
-  if( this->GetInput( ) )
-  {
-    TInputImage* input =
-      const_cast< TInputImage* >( this->GetInput( ) );
-    input->SetRequestedRegionToLargestPossibleRegion( );
-
-  } // fi
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage >
-void fpa::Image::RegionGrow< _TInputImage, _TOutputImage >::
-EnlargeOutputRequestedRegion( itk::DataObject* output )
-{
-  this->Superclass::EnlargeOutputRequestedRegion( output );
-  output->SetRequestedRegionToLargestPossibleRegion( );
-}
-
-// -------------------------------------------------------------------------
-template< class _TInputImage, class _TOutputImage >
-void fpa::Image::RegionGrow< _TInputImage, _TOutputImage >::
-GenerateData( )
-{
-  const TInputImage* input = this->GetInput( );
-  TOutputImage* output = this->GetOutput( );
-  TRegion region = input->GetRequestedRegion( );
-
-  // Configure output
-  output->SetBufferedRegion( region );
-  output->Allocate( );
-  output->FillBuffer( this->m_OutsideValue );
-
-  // Init marks
-  this->_InitMarks( this->GetNumberOfSeeds( ) );
-
-  // Init queue
-  typedef std::pair< TIndex, unsigned long > _TNode;
-  std::queue< _TNode > q;
-  unsigned long frontId = 1;
-  for( TIndex seed: this->GetSeeds( ) )
-    q.push( _TNode( seed, frontId++ ) );
-
-  // Main loop
-  while( q.size( ) > 0 )
-  {
-    // Get next candidate
-    _TNode node = q.front( );
-    q.pop( );
-    if( this->_IsMarked( node.first ) )
-      continue;
-    this->_Mark( node.first, node.second );
-
-    // Apply inclusion predicate
-    TInputPixel value = input->GetPixel( node.first );
-    bool inside = false;
-    if( this->m_IntensityFunctor.IsNotNull( ) )
-      inside = this->m_IntensityFunctor->Evaluate( value );
-    if( !inside )
-      continue;
-
-    // Ok, pixel lays inside region
-    output->SetPixel( node.first, this->m_InsideValue );
-
-    // Add neighborhood
-    for( unsigned int d = 0; d < TInputImage::ImageDimension; ++d )
-    {
-      TIndex neigh = node.first;
-      for( int i = -1; i <= 1; i += 2 )
-      {
-        neigh[ d ] = node.first[ d ] + i;
-        if( region.IsInside( 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__
-
-// eof - $RCSfile$