From: Leonardo Flórez-Valencia Date: Thu, 6 Jul 2017 04:03:15 +0000 (-0500) Subject: ... X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?p=FrontAlgorithms.git;a=commitdiff_plain;h=f8a18f8692f5d4ef2c6aceb8a75838382be2eb4e ... --- diff --git a/data/input_mori_binary.png b/data/input_mori_binary.png index d605247..53ac575 100644 Binary files a/data/input_mori_binary.png and b/data/input_mori_binary.png differ diff --git a/lib/fpa/Base/Algorithm.h b/lib/fpa/Base/Algorithm.h index 8750c5f..43f7a08 100644 --- a/lib/fpa/Base/Algorithm.h +++ b/lib/fpa/Base/Algorithm.h @@ -90,6 +90,7 @@ namespace fpa virtual void GenerateData( ) override; virtual void _BeforeGenerateData( ); virtual void _AfterGenerateData( ); + virtual void _FinishOneLoop( ); virtual void _QueueInit( ); @@ -98,7 +99,7 @@ namespace fpa virtual TInputValue _GetInputValue( const TVertex& v ) const = 0; virtual TOutputValue _GetOutputValue( const TVertex& v ) const = 0; - virtual TOutputValue _ComputeOutputValue( const TNode& n ) = 0; + virtual bool _ComputeOutputValue( TNode& n ) = 0; virtual void _UpdateOutputValue( const TNode& n ) = 0; virtual void _QueueClear( ) = 0; virtual void _QueuePush( const TNode& node ) = 0; diff --git a/lib/fpa/Base/Algorithm.hxx b/lib/fpa/Base/Algorithm.hxx index 44d2520..3a8b2d0 100644 --- a/lib/fpa/Base/Algorithm.hxx +++ b/lib/fpa/Base/Algorithm.hxx @@ -167,9 +167,12 @@ GenerateData( ) nnode.Vertex = *nIt; nnode.Parent = node.Vertex; nnode.FrontId = node.FrontId; - nnode.Value = this->_ComputeOutputValue( nnode ); - this->_QueuePush( nnode ); - this->InvokeEvent( TEvent( nnode.Vertex, nnode.FrontId, true ) ); + if( this->_ComputeOutputValue( nnode ) ) + { + this->_QueuePush( nnode ); + this->InvokeEvent( TEvent( nnode.Vertex, nnode.FrontId, true ) ); + + } // fi } // fi ++nIt; @@ -179,6 +182,7 @@ GenerateData( ) } // fi } // fi + this->_FinishOneLoop( ); } // elihw @@ -201,6 +205,13 @@ _AfterGenerateData( ) { } +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >:: +_FinishOneLoop( ) +{ +} + // ------------------------------------------------------------------------- template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >:: diff --git a/lib/fpa/Base/Functors/RegionGrow/BinaryThreshold.h b/lib/fpa/Base/Functors/RegionGrow/BinaryThreshold.h index ce533f6..0ac4618 100644 --- a/lib/fpa/Base/Functors/RegionGrow/BinaryThreshold.h +++ b/lib/fpa/Base/Functors/RegionGrow/BinaryThreshold.h @@ -36,21 +36,29 @@ namespace fpa itk::FunctionBase ); + itkBooleanMacro( Strict ); + itkGetConstMacro( Lower, _TValue ); itkGetConstMacro( Upper, _TValue ); + itkGetConstMacro( Strict, bool ); itkSetMacro( Lower, _TValue ); itkSetMacro( Upper, _TValue ); + itkSetMacro( Strict, bool ); public: virtual bool Evaluate( const _TValue& input ) const override { - return( this->m_Lower < input && input < this->m_Upper ); + if( this->m_Strict ) + return( this->m_Lower < input && input < this->m_Upper ); + else + return( this->m_Lower <= input && input <= this->m_Upper ); } protected: BinaryThreshold( ) - : Superclass( ) + : Superclass( ), + m_Strict( true ) { this->m_Upper = std::numeric_limits< _TValue >::max( ); if( std::numeric_limits< _TValue >::is_integer ) @@ -71,6 +79,7 @@ namespace fpa protected: _TValue m_Lower; _TValue m_Upper; + bool m_Strict; }; } // ecapseman diff --git a/lib/fpa/Base/Mori.h b/lib/fpa/Base/Mori.h index d927784..6863278 100644 --- a/lib/fpa/Base/Mori.h +++ b/lib/fpa/Base/Mori.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -37,6 +38,8 @@ namespace fpa typedef std::deque< TNode > TQueue; typedef std::set< TInputValue > TThresholds; + typedef std::pair< TInputValue, unsigned long > TSignalData; + typedef std::map< TFrontId, TSignalData > TSignal; typedef fpa::Base::Functors::RegionGrow::BinaryThreshold< TInputValue > TPredicate; public: @@ -59,7 +62,7 @@ namespace fpa void SetThresholds( const TInputValue& init, const TInputValue& end, - unsigned long number_of_thresholds + const TInputValue& delta ); protected: @@ -68,7 +71,8 @@ namespace fpa virtual void _BeforeGenerateData( ) override; virtual void _AfterGenerateData( ) override; - virtual TOutputValue _ComputeOutputValue( const TNode& n ) override; + virtual void _FinishOneLoop( ) override; + virtual bool _ComputeOutputValue( TNode& n ) override; virtual void _QueueClear( ) override; virtual TNode _QueuePop( ) override; virtual void _QueuePush( const TNode& node ) override; @@ -83,8 +87,11 @@ namespace fpa protected: typename TPredicate::Pointer m_Predicate; TThresholds m_Thresholds; + typename TThresholds::const_iterator m_CurrentThreshold; TQueue m_Queues[ 2 ]; unsigned int m_CurrentQueue; + unsigned long m_Count; + TSignal m_Signal; TOutputValue m_InsideValue; }; diff --git a/lib/fpa/Base/Mori.hxx b/lib/fpa/Base/Mori.hxx index cff5fe8..f014144 100644 --- a/lib/fpa/Base/Mori.hxx +++ b/lib/fpa/Base/Mori.hxx @@ -57,15 +57,11 @@ void fpa::Base::Mori< _TAlgorithm >:: SetThresholds( const TInputValue& init, const TInputValue& end, - unsigned long number_of_thresholds + const TInputValue& delta ) { - double i = double( init ); - double e = double( end ); - double n = double( number_of_thresholds ); - double d = ( e - i ) / n; - for( unsigned long c = 0; c <= number_of_thresholds; ++c ) - this->AddThreshold( TInputValue( i + ( d * double( c ) ) ) ); + for( TInputValue thr = init; thr <= end; thr += delta ) + this->AddThreshold( thr ); } // ------------------------------------------------------------------------- @@ -77,6 +73,7 @@ Mori( ) { this->SetInitValue( TOutputValue( 0 ) ); this->m_Predicate = TPredicate::New( ); + this->m_Predicate->StrictOff( ); } // ------------------------------------------------------------------------- @@ -95,6 +92,12 @@ _BeforeGenerateData( ) this->_QueueClear( ); this->m_CurrentQueue = 0; + this->m_CurrentThreshold = this->m_Thresholds.begin( ); + this->m_Predicate->SetLower( *( this->m_CurrentThreshold ) ); + this->m_CurrentThreshold++; + this->m_Predicate->SetUpper( *( this->m_CurrentThreshold ) ); + this->m_Count = 0; + this->m_Signal.clear( ); } // ------------------------------------------------------------------------- @@ -102,24 +105,57 @@ template< class _TAlgorithm > void fpa::Base::Mori< _TAlgorithm >:: _AfterGenerateData( ) { + // https://stackoverflow.com/questions/22583391/peak-signal-detection-in-realtime-timeseries-data this->Superclass::_AfterGenerateData( ); + + typename TSignal::const_iterator sIt = this->m_Signal.begin( ); + for( ; sIt != this->m_Signal.end( ); ++sIt ) + { + std::cout << int( sIt->first ) << " " << int( sIt->second.first ) << " " << sIt->second.second << std::endl; + + } // rof + std::cerr << ( this->m_CurrentThreshold != this->m_Thresholds.end( ) ) << std::endl; } // ------------------------------------------------------------------------- template< class _TAlgorithm > -typename fpa::Base::Mori< _TAlgorithm >:: -TOutputValue fpa::Base::Mori< _TAlgorithm >:: -_ComputeOutputValue( const TNode& n ) +void fpa::Base::Mori< _TAlgorithm >:: +_FinishOneLoop( ) +{ + if( this->m_Queues[ this->m_CurrentQueue ].size( ) == 0 ) + { + this->m_Signal[ this->m_Signal.size( ) + 1 ] = + TSignalData( *this->m_CurrentThreshold, this->m_Count ); + std::cerr << *( this->m_CurrentThreshold ) << std::endl; + this->m_CurrentThreshold++; + this->m_CurrentQueue = ( this->m_CurrentQueue + 1 ) % 2; + if( this->m_CurrentThreshold != this->m_Thresholds.end( ) ) + { + this->m_Predicate->SetUpper( *( this->m_CurrentThreshold ) ); + this->m_Count = 0; + } + else + this->_QueueClear( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +bool fpa::Base::Mori< _TAlgorithm >:: +_ComputeOutputValue( TNode& n ) { TInputValue value = this->_GetInputValue( n.Vertex ); bool inside = this->m_Predicate->Evaluate( value ); + n.Value = this->m_InsideValue; if( !inside ) { - // TODO: Update new queue - return( this->m_InitValue ); + n.FrontId++; + this->m_Queues[ ( this->m_CurrentQueue + 1 ) % 2 ].push_back( n ); } else - return( this->m_InsideValue ); + this->m_Count++; + return( inside ); } // ------------------------------------------------------------------------- @@ -147,7 +183,6 @@ template< class _TAlgorithm > void fpa::Base::Mori< _TAlgorithm >:: _QueuePush( const TNode& node ) { - // TODO: Update mark this->m_Queues[ this->m_CurrentQueue ].push_back( node ); } @@ -169,14 +204,6 @@ _PrepareSeeds( TNodes& nodes ) nIt->Value = this->m_InsideValue; } -/* TODO - typename TPredicate::Pointer m_Predicate; - TThresholds m_Thresholds; - TQueue m_Queues[ 2 ]; - unsigned int m_CurrentQueue; - TOutputValue m_InsideValue; -*/ - #endif // __fpa__Base__Mori__hxx__ // eof - $RCSfile$ diff --git a/lib/fpa/Base/RegionGrow.h b/lib/fpa/Base/RegionGrow.h index 34bb085..28657d6 100644 --- a/lib/fpa/Base/RegionGrow.h +++ b/lib/fpa/Base/RegionGrow.h @@ -63,7 +63,7 @@ namespace fpa RegionGrow( ); virtual ~RegionGrow( ); - virtual TOutputValue _ComputeOutputValue( const TNode& n ) override; + virtual bool _ComputeOutputValue( TNode& n ) override; virtual void _QueueClear( ) override; virtual TNode _QueuePop( ) override; virtual void _QueuePush( const TNode& node ) override; diff --git a/lib/fpa/Base/RegionGrow.hxx b/lib/fpa/Base/RegionGrow.hxx index 247cf94..503222c 100644 --- a/lib/fpa/Base/RegionGrow.hxx +++ b/lib/fpa/Base/RegionGrow.hxx @@ -90,9 +90,8 @@ fpa::Base::RegionGrow< _TAlgorithm >:: // ------------------------------------------------------------------------- template< class _TAlgorithm > -typename fpa::Base::RegionGrow< _TAlgorithm >:: -TOutputValue fpa::Base::RegionGrow< _TAlgorithm >:: -_ComputeOutputValue( const TNode& n ) +bool fpa::Base::RegionGrow< _TAlgorithm >:: +_ComputeOutputValue( TNode& n ) { TInputValue value = this->_GetInputValue( n.Vertex ); bool inside = false; @@ -100,7 +99,8 @@ _ComputeOutputValue( const TNode& n ) inside = this->m_ValuePredicate->Evaluate( value ); if( this->m_VertexPredicate.IsNotNull( ) ) inside &= this->m_VertexPredicate->Evaluate( n.Vertex ); - return( ( inside )? this->m_InsideValue: this->m_InitValue ); + n.Value = ( inside )? this->m_InsideValue: this->m_InitValue; + return( inside ); } // ------------------------------------------------------------------------- diff --git a/lib/fpa/Image/Algorithm.hxx b/lib/fpa/Image/Algorithm.hxx index 9ac7548..a94f131 100644 --- a/lib/fpa/Image/Algorithm.hxx +++ b/lib/fpa/Image/Algorithm.hxx @@ -88,7 +88,7 @@ _UnifySeeds( ) } else sIt->IsUnified = false; - + } // rof return( nodes ); diff --git a/lib/fpa/Image/Mori.h b/lib/fpa/Image/Mori.h index 21c1748..a81016c 100644 --- a/lib/fpa/Image/Mori.h +++ b/lib/fpa/Image/Mori.h @@ -17,20 +17,20 @@ namespace fpa { /** */ - template< class _TInputImage, class _TOutputImage, class _TFrontId = unsigned char > + template< class _TInputImage, class _TOutputImage > class Mori - : public fpa::Base::Mori< fpa::Image::Algorithm< _TInputImage, _TOutputImage, fpa::Base::MarksInterface< typename _TInputImage::IndexType >, fpa::Base::SingleSeedInterface< typename _TInputImage::IndexType, typename _TInputImage::PointType, typename _TInputImage::PixelType, typename _TOutputImage::PixelType, _TFrontId, typename _TInputImage::IndexType::LexicographicCompare > > > + : public fpa::Base::Mori< fpa::Image::Algorithm< _TInputImage, _TOutputImage, fpa::Base::MarksInterface< typename _TInputImage::IndexType >, fpa::Base::SingleSeedInterface< typename _TInputImage::IndexType, typename _TInputImage::PointType, typename _TInputImage::PixelType, typename _TOutputImage::PixelType, typename _TOutputImage::PixelType, typename _TInputImage::IndexType::LexicographicCompare > > > { public: typedef _TInputImage TInputImage; typedef _TOutputImage TOutputImage; - typedef _TFrontId TFrontId; typedef typename TInputImage::IndexType TVertex; typedef typename TInputImage::PointType TPoint; typedef typename TVertex::LexicographicCompare TVertexCompare; typedef typename TInputImage::PixelType TInputValue; typedef typename TOutputImage::PixelType TOutputValue; + typedef typename TOutputImage::PixelType TFrontId; typedef fpa::Base::MarksInterface< TVertex > TMarksInterface; typedef fpa::Base::SingleSeedInterface< TVertex, TPoint, TInputValue, TOutputValue, TFrontId, TVertexCompare > TSeedsInterface; diff --git a/tests/image/MoriSegmentation.cxx b/tests/image/MoriSegmentation.cxx index e02b359..d1b26f5 100644 --- a/tests/image/MoriSegmentation.cxx +++ b/tests/image/MoriSegmentation.cxx @@ -3,22 +3,24 @@ #include // ------------------------------------------------------------------------- -const unsigned int Dim = 2; -typedef unsigned char TPixel; +const unsigned int Dim = 3; +typedef short TPixel; +typedef unsigned short TLabel; -typedef itk::Image< TPixel, Dim > TImage; -typedef fpa::Image::Mori< TImage, TImage > TFilter; +typedef itk::Image< TPixel, Dim > TInputImage; +typedef itk::Image< TLabel, Dim > TLabelImage; +typedef fpa::Image::Mori< TInputImage, TLabelImage > TFilter; // ------------------------------------------------------------------------- int main( int argc, char* argv[] ) { // Get arguments - if( argc < 9 ) + if( argc < 8 + Dim ) { std::cerr << "Usage: " << argv[ 0 ] << " input_image output_image output_levels" - << " init_threshold end_threshold number_of_threshold seed_x seed_y" + << " init_threshold end_threshold delta [index/point] seed" << std::endl; return( 1 ); @@ -26,15 +28,24 @@ int main( int argc, char* argv[] ) std::string input_image_filename = argv[ 1 ]; std::string output_image_filename = argv[ 2 ]; std::string output_levels_filename = argv[ 3 ]; - unsigned char init_threshold = std::atoi( argv[ 4 ] ); - unsigned char end_threshold = std::atoi( argv[ 5 ] ); - unsigned char number_of_thresholds = std::atoi( argv[ 6 ] ); - TImage::IndexType seed; - seed[ 0 ] = std::atoi( argv[ 7 ] ); - seed[ 1 ] = std::atoi( argv[ 8 ] ); + TPixel init_threshold = std::atoi( argv[ 4 ] ); + TPixel end_threshold = std::atoi( argv[ 5 ] ); + TPixel delta = std::atoi( argv[ 6 ] ); + std::string seed_type = argv[ 7 ]; + + TInputImage::IndexType iseed; + TInputImage::PointType pseed; + for( unsigned int i = 0; i < Dim; ++i ) + { + if( seed_type == "index" ) + iseed[ i ] = std::atoi( argv[ 8 + i ] ); + else + pseed[ i ] = std::atof( argv[ 8 + i ] ); + + } // rof // Create image - TImage::Pointer input_image; + TInputImage::Pointer input_image; std::string err0 = fpa::tests::image::Read( input_image, input_image_filename ); if( err0 != "" ) std::cerr << err0 << std::endl; @@ -42,8 +53,11 @@ int main( int argc, char* argv[] ) // Prepare filter TFilter::Pointer filter = TFilter::New( ); filter->SetInput( input_image ); - filter->SetSeed( seed ); - filter->SetThresholds( init_threshold, end_threshold, number_of_thresholds ); + if( seed_type == "index" ) + filter->SetSeed( iseed ); + else + filter->SetSeed( pseed ); + filter->SetThresholds( init_threshold, end_threshold, delta ); filter->SetInsideValue( 255 ); filter->SetOutsideValue( 0 );