-#include <itkCommand.h>
#include <itkImage.h>
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
+#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[] )
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 )
{
} // 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 );
}
-#include <itkCommand.h>
#include <itkImage.h>
#include <itkImageFileWriter.h>
--- /dev/null
+// =========================================================================
+// @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$
--- /dev/null
+// =========================================================================
+// @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$
--- /dev/null
+// =========================================================================
+// @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$
--- /dev/null
+// =========================================================================
+// @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$
--- /dev/null
+// =========================================================================
+// @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$
--- /dev/null
+// =========================================================================
+// @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$
--- /dev/null
+// =========================================================================
+// @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$
--- /dev/null
+// =========================================================================
+// @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$
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 );
}
// -------------------------------------------------------------------------
#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
{
{
/**
*/
- 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$
+++ /dev/null
-// =========================================================================
-// @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$
#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
{
*/
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$
+++ /dev/null
-// =========================================================================
-// @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$