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