From 5e0c313e26ec0a292b5ee965b5a22a2ed60c1021 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leonardo=20Fl=C3=B3rez-Valencia?= Date: Wed, 22 Mar 2017 19:17:12 -0500 Subject: [PATCH] ... --- examples/RegionGrow_BinaryThreshold.cxx | 1 - examples/RegionGrow_Mori.cxx | 82 ++++++-- examples/RegionGrow_Tautology.cxx | 1 - libs/fpa/Base/Dijkstra.h | 92 +++++++++ libs/fpa/Base/Dijkstra.hxx | 83 ++++++++ libs/fpa/Base/MoriRegionGrow.h | 96 +++++++++ libs/fpa/Base/MoriRegionGrow.hxx | 186 +++++++++++++++++ libs/fpa/Base/RegionGrow.h | 82 ++++++++ libs/fpa/Base/RegionGrow.hxx | 147 ++++++++++++++ libs/fpa/Image/Filter.h | 60 ++++++ libs/fpa/Image/Filter.hxx | 103 ++++++++++ libs/fpa/Image/MarksInterface.hxx | 2 +- libs/fpa/Image/MoriRegionGrow.h | 101 ++-------- libs/fpa/Image/MoriRegionGrow.hxx | 254 ------------------------ libs/fpa/Image/RegionGrow.h | 63 ++---- libs/fpa/Image/RegionGrow.hxx | 143 ------------- 16 files changed, 944 insertions(+), 552 deletions(-) create mode 100644 libs/fpa/Base/Dijkstra.h create mode 100644 libs/fpa/Base/Dijkstra.hxx create mode 100644 libs/fpa/Base/MoriRegionGrow.h create mode 100644 libs/fpa/Base/MoriRegionGrow.hxx create mode 100644 libs/fpa/Base/RegionGrow.h create mode 100644 libs/fpa/Base/RegionGrow.hxx create mode 100644 libs/fpa/Image/Filter.h create mode 100644 libs/fpa/Image/Filter.hxx delete mode 100644 libs/fpa/Image/MoriRegionGrow.hxx delete mode 100644 libs/fpa/Image/RegionGrow.hxx diff --git a/examples/RegionGrow_BinaryThreshold.cxx b/examples/RegionGrow_BinaryThreshold.cxx index d490885..3e0b95a 100644 --- a/examples/RegionGrow_BinaryThreshold.cxx +++ b/examples/RegionGrow_BinaryThreshold.cxx @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/examples/RegionGrow_Mori.cxx b/examples/RegionGrow_Mori.cxx index 7fd51b4..cf20cfa 100644 --- a/examples/RegionGrow_Mori.cxx +++ b/examples/RegionGrow_Mori.cxx @@ -1,18 +1,38 @@ +#include #include #include #include #include +#include #include // ------------------------------------------------------------------------- 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 ); } diff --git a/examples/RegionGrow_Tautology.cxx b/examples/RegionGrow_Tautology.cxx index 88cdd0a..8bee856 100644 --- a/examples/RegionGrow_Tautology.cxx +++ b/examples/RegionGrow_Tautology.cxx @@ -1,4 +1,3 @@ -#include #include #include diff --git a/libs/fpa/Base/Dijkstra.h b/libs/fpa/Base/Dijkstra.h new file mode 100644 index 0000000..2c49c06 --- /dev/null +++ b/libs/fpa/Base/Dijkstra.h @@ -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 + +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 +#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 index 0000000..9e8e529 --- /dev/null +++ b/libs/fpa/Base/Dijkstra.hxx @@ -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 index 0000000..d8f2ee0 --- /dev/null +++ b/libs/fpa/Base/MoriRegionGrow.h @@ -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 +#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 index 0000000..b619bce --- /dev/null +++ b/libs/fpa/Base/MoriRegionGrow.hxx @@ -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 +#include + +// ------------------------------------------------------------------------- +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 index 0000000..2586033 --- /dev/null +++ b/libs/fpa/Base/RegionGrow.h @@ -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 + +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 +#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 index 0000000..9e7bb7b --- /dev/null +++ b/libs/fpa/Base/RegionGrow.hxx @@ -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 + +// ------------------------------------------------------------------------- +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 index 0000000..ab86f81 --- /dev/null +++ b/libs/fpa/Image/Filter.h @@ -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 +#include + +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 +#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 index 0000000..ad8053b --- /dev/null +++ b/libs/fpa/Image/Filter.hxx @@ -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$ diff --git a/libs/fpa/Image/MarksInterface.hxx b/libs/fpa/Image/MarksInterface.hxx index 47ed11f..4d639ac 100644 --- a/libs/fpa/Image/MarksInterface.hxx +++ b/libs/fpa/Image/MarksInterface.hxx @@ -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 ); } // ------------------------------------------------------------------------- diff --git a/libs/fpa/Image/MoriRegionGrow.h b/libs/fpa/Image/MoriRegionGrow.h index 606d4f7..182e004 100644 --- a/libs/fpa/Image/MoriRegionGrow.h +++ b/libs/fpa/Image/MoriRegionGrow.h @@ -6,8 +6,10 @@ #ifndef __fpa__Image__MoriRegionGrow__h__ #define __fpa__Image__MoriRegionGrow__h__ -#include -#include +#include +#include +#include +#include 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 -#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 index 5efdf65..0000000 --- a/libs/fpa/Image/MoriRegionGrow.hxx +++ /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 -#include - -// ------------------------------------------------------------------------- -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$ diff --git a/libs/fpa/Image/RegionGrow.h b/libs/fpa/Image/RegionGrow.h index f608479..5d7b4db 100644 --- a/libs/fpa/Image/RegionGrow.h +++ b/libs/fpa/Image/RegionGrow.h @@ -6,10 +6,10 @@ #ifndef __fpa__Image__RegionGrow__h__ #define __fpa__Image__RegionGrow__h__ -#include -#include +#include #include #include +#include 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 -#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 index 2208070..0000000 --- a/libs/fpa/Image/RegionGrow.hxx +++ /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 - -// ------------------------------------------------------------------------- -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$ -- 2.47.1