From 20916948d3878c722b73e7ee86df87ff2df9d0fe Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leonardo=20Fl=C3=B3rez-Valencia?= Date: Thu, 16 Mar 2017 16:42:33 -0500 Subject: [PATCH] ... --- data/input_mori_binary.png | Bin 0 -> 2563 bytes ...mentationWithBinaryThresholdRegionGrow.cxx | 116 ++++++++++++++++++ .../BronchiiInitialSegmentationWithMori.cxx | 55 ++++++++- examples/CMakeLists.txt | 2 + examples/CreateMoriInputImage.cxx | 64 ++++++++++ libs/fpa/Base/Algorithm.h | 4 +- libs/fpa/Base/Algorithm.hxx | 15 ++- libs/fpa/Base/RegionGrow.h | 11 +- libs/fpa/Base/RegionGrow.hxx | 31 +++-- libs/fpa/Image/Algorithm.h | 2 +- libs/fpa/Image/Algorithm.hxx | 7 +- .../Functors/RegionGrow/BinaryThreshold.hxx | 3 + libs/fpa/Image/MoriFilter.h | 19 +-- libs/fpa/Image/MoriFilter.hxx | 24 +++- libs/fpa/Image/MoriFilterHelper.h | 111 ++++++++++------- libs/fpa/Image/MoriFilterHelper.hxx | 64 +++++++--- 16 files changed, 429 insertions(+), 99 deletions(-) create mode 100644 data/input_mori_binary.png create mode 100644 examples/BronchiiInitialSegmentationWithBinaryThresholdRegionGrow.cxx create mode 100644 examples/CreateMoriInputImage.cxx diff --git a/data/input_mori_binary.png b/data/input_mori_binary.png new file mode 100644 index 0000000000000000000000000000000000000000..d6052476e0b2a2675e6f9b21be2f497f09e7e6d3 GIT binary patch literal 2563 zcmd5;d0Z3M7QRW)fXXC_AgGZ<1Q)gfD%gRFf-IFqp9(6XSWFR=m?42dkvb?yFo@bd zC6&dhEw~{S6b6PR+C)S_t+oYaqH$!g4;|u$qFCN90eq#ef4o26ALn=Oz2A4wojK>s zcPDFEh`;HW$zuQjrhx&z{{VpTN^izY0D$ks01W`ZL>#b20>D@^y)nSid`kcTTN)U= zg#C!cndsm!tk?4<4RtW3s_ti`v#BX!2C^uk%ESYRw~LrSYxmT61(}L#$wa_mMEN zU}|wj>$!-v2%3;@@kO~PR;_77*2BH zx>BMAO{&Ly@n@9CG3e?ZzW8%WBxq`|;fup4k$F&~&Lm%fM=;A>lbBt0bk6=PE046h zW@y7zGW)2~Y9A3Dy<=~Xc7|GW!NupXt+N4U=1DV^3**2@V+4lDm1GM(jkOfceBlU%j*977u}Zl2 z)pXj)msogcfYY6NpvQXPON~D%&;|GR<{~H^xrpgBoq|4`=xr&z`|C8M1!5k%ajgEU zL323u zeQQVWSoxr3o(xXk(EdDI#ZxwGZdiX= zDS~ciGY{0@-7q(~Rjmi2o#=Ov(KIpAg7S5n<%BI@axUQ!qxd=xIgtUFoH9IOEMI3V zCpti;yH2-{FlRK(zkTOqcTDvW0d|h4YO_=>NR*%%>`j_x4a8uD{*Xu5dtR%?PxkP; zsT|dwb8o0>U(7QDF{XX(wj8b3h6RtFOh_S^!q{z@TG70BO) zjLwJj;t?67v>K0ol#^r1+$`<)G8j-0hQBYc^KjM=SbQ4DQkK?v8x{K* z`QG>;8Pcmr!JD^PT#rS=JBGZ^+eHgK{Qt5D3`g*3vf*J3C=UD>^rI^2rAK4@QM3#q zHL@x6{nGW%Gpp7j)Pv?|IN)*d-%+YY{u}#We6P=LVifI`cHZ5vr9D$ge^`nLxD;|3>Cget#Nn5a29?s zi}2Dmt?)(}bM9e)6e^cItWL|MNGCNeyYT zuy!#=M4wOZ%XJ97?Ps++54O2kLGH;TESjn}r9NLX@a}bl<)f|_M90h1CG4WEPCBQv=ANmrGFC(< z{Twsb-R!4k&AjG~<(5Z+NvmC7$7huMxQz<=Wn%>=?8@~lczM@7yH<9@Oxl+h3rATw z6yj!yXS`DLqTZ+q^2?tcZ(~fEMYrdRZ>^<-k)+9juENqfdjh}vM{CN_3C`Uz_z6)a zhxyOToM>gcYOEY*EzioGh_FvgaJHi$U)%M5DxU1~8cYTsT(MolMft@q5(Kn&z!TfW qWLj_4BqM|!wc-Ewe+8@kVAS7zqTPJ@Tm=9C1TG2jJ-;|=_rC!e`cZWN literal 0 HcmV?d00001 diff --git a/examples/BronchiiInitialSegmentationWithBinaryThresholdRegionGrow.cxx b/examples/BronchiiInitialSegmentationWithBinaryThresholdRegionGrow.cxx new file mode 100644 index 0000000..8381cff --- /dev/null +++ b/examples/BronchiiInitialSegmentationWithBinaryThresholdRegionGrow.cxx @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +static const unsigned int Dim = 3; +typedef short TPixel; +typedef itk::Image< TPixel, Dim > TImage; + +// ------------------------------------------------------------------------- +std::string GetFullPath( const std::string& filename ) +{ + /* On windows: + #include + TCHAR full_path[MAX_PATH]; + GetFullPathName(_T("foo.dat"), MAX_PATH, full_path, NULL); + */ + + char* buffer = realpath( filename.c_str( ), NULL ); + std::string path = buffer; + std::free( buffer ); + return( path ); +} + +// ------------------------------------------------------------------------- +std::string GetFullPathToDirectory( const std::string& filename ) +{ + std::string path = GetFullPath( filename ); + std::size_t found = path.find_last_of( "/\\" ); + return( path.substr( 0, found + 1 ) ); +} + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Command configuration + if( argc < 5 ) + { + std::cerr + << "Usage: " << argv[ 0 ] << " input_image output_image lower upper" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_filename = GetFullPath( argv[ 1 ] ); + std::string output_image_filename = argv[ 2 ]; + std::string output_auxiliary_image_filename = output_image_filename + "_aux.mhd"; + TPixel lower = std::atoi( argv[ 3 ] ); + TPixel upper = std::atoi( argv[ 4 ] ); + + // Try to guess initial seed + std::string seed_filename = GetFullPathToDirectory( argv[ 1 ] ) + "seed.txt"; + std::ifstream seed_str( seed_filename.c_str( ) ); + if( !seed_str ) + { + std::cerr + << "No \"seed.txt\" file in the same input image directory." + << std::endl; + return( 1 ); + + } // fi + TImage::IndexType seed; + seed_str >> seed[ 0 ] >> seed[ 1 ] >> seed[ 2 ]; + seed_str.close( ); + + // Read image + typedef itk::ImageFileReader< TImage > TReader; + TReader::Pointer reader = TReader::New( ); + reader->SetFileName( input_image_filename ); + + // Growing predicate + typedef fpa::Image::Functors::RegionGrow::BinaryThreshold< TImage, TImage::PixelType > TPredicate; + TPredicate::Pointer predicate = TPredicate::New( ); + predicate->SetLower( lower ); + predicate->SetUpper( upper ); + + // RegionGrow algorithm + typedef fpa::Image::RegionGrow< TImage, TImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( reader->GetOutput( ) ); + filter->AddSeed( seed, 1 ); + filter->SetInsideValue( 1 ); + filter->SetOutsideValue( 0 ); + filter->SetGrowFunction( predicate ); + + // Write results + typedef itk::ImageFileWriter< TImage > TWriter; + TWriter::Pointer writer = TWriter::New( ); + writer->SetInput( filter->GetOutput( ) ); + writer->SetFileName( output_image_filename ); + + // Execute pipeline + try + { + writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/examples/BronchiiInitialSegmentationWithMori.cxx b/examples/BronchiiInitialSegmentationWithMori.cxx index ed0c294..fa940d5 100644 --- a/examples/BronchiiInitialSegmentationWithMori.cxx +++ b/examples/BronchiiInitialSegmentationWithMori.cxx @@ -52,6 +52,7 @@ int main( int argc, char* argv[] ) } // fi std::string input_image_filename = GetFullPath( argv[ 1 ] ); std::string output_image_filename = argv[ 2 ]; + std::string output_auxiliary_image_filename = output_image_filename + "_aux.mhd"; // Try to guess initial seed std::string seed_filename = GetFullPathToDirectory( argv[ 1 ] ) + "seed.txt"; @@ -66,6 +67,7 @@ int main( int argc, char* argv[] ) } // fi TImage::IndexType seed; seed_str >> seed[ 0 ] >> seed[ 1 ] >> seed[ 2 ]; + seed_str.close( ); // Read image typedef itk::ImageFileReader< TImage > TReader; @@ -77,7 +79,7 @@ int main( int argc, char* argv[] ) TFilter::Pointer filter = TFilter::New( ); filter->SetInput( reader->GetOutput( ) ); filter->SetSeed( seed ); - filter->SetThresholdRange( -1024, 0 ); + filter->SetThresholdRange( -200, 100, 1 ); filter->SetInsideValue( 1 ); filter->SetOutsideValue( 0 ); @@ -98,6 +100,57 @@ int main( int argc, char* argv[] ) return( 1 ); } // yrt + + // Write auxiliary image + typedef itk::ImageFileWriter< TFilter::TAuxImage > TAuxWriter; + TAuxWriter::Pointer aux_writer = TAuxWriter::New( ); + aux_writer->SetInput( filter->GetAuxiliaryImage( ) ); + aux_writer->SetFileName( output_auxiliary_image_filename ); + + // Execute pipeline + try + { + aux_writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + // Write result signal + std::string output_signal_filename = output_image_filename + ".csv"; + std::ofstream output_signal_str( output_signal_filename.c_str( ) ); + TFilter::TCurve curve = filter->GetCurve( ); + unsigned long max_count = 0; + for( TFilter::TCurve::value_type d : curve ) + { + output_signal_str << d.first << " " << d.second << std::endl; + if( max_count < d.second ) + max_count = d.second; + + } // rof + output_signal_str.close( ); + + // Write gnuplot script + std::string output_gnuplot_filename = output_image_filename + ".gnuplot"; + std::ofstream output_gnuplot_str( output_gnuplot_filename.c_str( ) ); + unsigned int thr_pos = filter->GetOptimumThreshold( ); + int thr = curve[ thr_pos ].first; + output_gnuplot_str + << "set term png" << std::endl + << "set output \"" << output_image_filename << ".png\"" << std::endl + << "set arrow 1 from " << thr + << ",0 to " << thr << "," << max_count + << std::endl + << "show arrow 1" << std::endl + << "plot \"" << output_signal_filename + << "\" using 1:2 with linespoints title \"Evolution (" + << thr << "," << thr_pos << ") " << "\"" + << std::endl; + output_gnuplot_str.close( ); + return( 0 ); } diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 8205f49..0b9e558 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -2,7 +2,9 @@ OPTION(BUILD_EXAMPLES "Build cpPlugins-free examples." OFF) IF(BUILD_EXAMPLES) SET( _examples + CreateMoriInputImage BronchiiInitialSegmentationWithMori + BronchiiInitialSegmentationWithBinaryThresholdRegionGrow ) INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/libs diff --git a/examples/CreateMoriInputImage.cxx b/examples/CreateMoriInputImage.cxx new file mode 100644 index 0000000..144ed6e --- /dev/null +++ b/examples/CreateMoriInputImage.cxx @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +static const unsigned int Dim = 2; +typedef short TInputPixel; +typedef float TOutputPixel; +typedef itk::Image< TInputPixel, Dim > TInputImage; +typedef itk::Image< TOutputPixel, Dim > TOutputImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Command configuration + if( argc < 3 ) + { + std::cerr + << "Usage: " << argv[ 0 ] << " input_image output_image" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_filename = argv[ 1 ]; + std::string output_image_filename = argv[ 2 ]; + + // Read image + typedef itk::ImageFileReader< TInputImage > TReader; + TReader::Pointer reader = TReader::New( ); + reader->SetFileName( input_image_filename ); + + // Distance map + typedef itk::SignedMaurerDistanceMapImageFilter< TInputImage, TOutputImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( reader->GetOutput( ) ); + filter->SetBackgroundValue( 0 ); + filter->InsideIsPositiveOn( ); + filter->SquaredDistanceOff( ); + filter->UseImageSpacingOn( ); + + // Write image + typedef itk::ImageFileWriter< TOutputImage > TWriter; + TWriter::Pointer writer = TWriter::New( ); + writer->SetInput( filter->GetOutput( ) ); + writer->SetFileName( output_image_filename ); + + // Execute pipeline + try + { + writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/libs/fpa/Base/Algorithm.h b/libs/fpa/Base/Algorithm.h index 6625467..232c4b3 100644 --- a/libs/fpa/Base/Algorithm.h +++ b/libs/fpa/Base/Algorithm.h @@ -102,14 +102,14 @@ namespace fpa virtual bool _ValidLoop( ) const; virtual void _UpdateCollisions( const TVertex& a, const TVertex& b ); - virtual _TOutput _GetInputValue( const _TQueueNode& v, const _TQueueNode& p ); + virtual _TOutput _GetInputValue( const TVertex& v, const TVertex& p ); + virtual bool _UpdateResult( _TQueueNode& n ); virtual void _InitMarks( ) = 0; virtual void _InitResults( const TOutput& init_value ) = 0; virtual bool _IsMarked( const _TVertex& v ) const = 0; virtual void _Mark( const _TQueueNode& n ) = 0; virtual TFrontId _GetMark( const _TVertex& v ) const = 0; - virtual void _UpdateResult( const _TQueueNode& n ) = 0; virtual TOutput _GetResult( const _TVertex& v ) const = 0; virtual unsigned int _GetNumberOfDimensions( ) const = 0; diff --git a/libs/fpa/Base/Algorithm.hxx b/libs/fpa/Base/Algorithm.hxx index c29ff03..2b82a4f 100644 --- a/libs/fpa/Base/Algorithm.hxx +++ b/libs/fpa/Base/Algorithm.hxx @@ -137,8 +137,9 @@ _Loop( ) if( this->_IsMarked( node.Vertex ) ) continue; this->_Mark( node ); - this->_UpdateResult( node ); this->InvokeEvent( TMarkEvent( node.Vertex, node.FrontId ) ); + if( !( this->_UpdateResult( node ) ) ) + continue; // Add neighbors to queue TNeighborhood neighs = this->m_NeighborhoodFunction->Evaluate( node.Vertex ); @@ -254,16 +255,24 @@ _UpdateCollisions( const TVertex& a, const TVertex& b ) // ------------------------------------------------------------------------- template < class _TFilter, class _TVertex, class _TOutput > _TOutput fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: -_GetInputValue( const _TQueueNode& v, const _TQueueNode& p ) +_GetInputValue( const TVertex& v, const TVertex& p ) { _TOutput res = this->m_InitResult; if( this->m_VertexFunction.IsNotNull( ) ) - res = this->m_VertexFunction->Evaluate( v.Vertex, p.Vertex ); + res = this->m_VertexFunction->Evaluate( v, p ); if( this->m_ConversionFunction.IsNotNull( ) ) res = this->m_ConversionFunction->Evaluate( res ); return( res ); } +// ------------------------------------------------------------------------- +template < class _TFilter, class _TVertex, class _TOutput > +bool fpa::Base::Algorithm< _TFilter, _TVertex, _TOutput >:: +_UpdateResult( _TQueueNode& n ) +{ + return( true ); +} + #endif // __fpa__Base__Algorithm__hxx__ // eof - $RCSfile$ diff --git a/libs/fpa/Base/RegionGrow.h b/libs/fpa/Base/RegionGrow.h index 4790b85..ea9008a 100644 --- a/libs/fpa/Base/RegionGrow.h +++ b/libs/fpa/Base/RegionGrow.h @@ -48,13 +48,10 @@ namespace fpa virtual bool _UpdateValue( _TQueueNode& v, const _TQueueNode& p ) override; - virtual TOutput _GetInputValue( const _TQueueNode& v, const _TQueueNode& p ) override - { - TOutput res = this->m_InitResult; - if( this->m_GrowFunction.IsNotNull( ) ) - res = this->m_GrowFunction->Evaluate( v.Vertex, p.Vertex ); - return( res ); - } + virtual TOutput _GetInputValue( + const TVertex& v, const TVertex& p + ) override; + virtual bool _UpdateResult( _TQueueNode& n ) override; private: diff --git a/libs/fpa/Base/RegionGrow.hxx b/libs/fpa/Base/RegionGrow.hxx index c3cb9f3..3def0a7 100644 --- a/libs/fpa/Base/RegionGrow.hxx +++ b/libs/fpa/Base/RegionGrow.hxx @@ -9,7 +9,6 @@ typename fpa::Base::RegionGrow< _TSuperclass >:: TGrowFunction* fpa::Base::RegionGrow< _TSuperclass >:: GetGrowFunction( ) { - // TODO: return( dynamic_cast< TGrowFunction* >( this->GetVertexFunction( ) ) ); return( this->m_GrowFunction ); } @@ -19,11 +18,6 @@ const typename fpa::Base::RegionGrow< _TSuperclass >:: TGrowFunction* fpa::Base::RegionGrow< _TSuperclass >:: GetGrowFunction( ) const { - /* TODO - return( - dynamic_cast< const TGrowFunction* >( this->GetVertexFunction( ) ) - ); - */ return( this->m_GrowFunction ); } @@ -119,8 +113,29 @@ template< class _TSuperclass > bool fpa::Base::RegionGrow< _TSuperclass >:: _UpdateValue( _TQueueNode& v, const _TQueueNode& p ) { - v.Result = this->_GetInputValue( v, p ); - return( v.Result == this->GetInsideValue( ) ); + return( true ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +typename fpa::Base::RegionGrow< _TSuperclass >:: +TOutput fpa::Base::RegionGrow< _TSuperclass >:: +_GetInputValue( const TVertex& v, const TVertex& p ) +{ + TOutput res = this->m_InitResult; + if( this->m_GrowFunction.IsNotNull( ) ) + res = this->m_GrowFunction->Evaluate( v, p ); + return( res ); +} + +// ------------------------------------------------------------------------- +template< class _TSuperclass > +bool fpa::Base::RegionGrow< _TSuperclass >:: +_UpdateResult( _TQueueNode& n ) +{ + n.Result = this->_GetInputValue( n.Vertex, n.Parent ); + this->Superclass::_UpdateResult( n ); + return( n.Result == this->GetInsideValue( ) ); } #endif // __fpa__Base__RegionGrow__hxx__ diff --git a/libs/fpa/Image/Algorithm.h b/libs/fpa/Image/Algorithm.h index 0105cc3..11c1cb2 100644 --- a/libs/fpa/Image/Algorithm.h +++ b/libs/fpa/Image/Algorithm.h @@ -48,7 +48,7 @@ namespace fpa virtual bool _IsMarked( const TVertex& v ) const override; virtual void _Mark( const _TQueueNode& n ) override; virtual TFrontId _GetMark( const TVertex& v ) const override; - virtual void _UpdateResult( const _TQueueNode& n ) override; + virtual bool _UpdateResult( _TQueueNode& n ) override; virtual TOutput _GetResult( const TVertex& v ) const override; virtual unsigned int _GetNumberOfDimensions( ) const override; diff --git a/libs/fpa/Image/Algorithm.hxx b/libs/fpa/Image/Algorithm.hxx index 3c33e4e..00077d3 100644 --- a/libs/fpa/Image/Algorithm.hxx +++ b/libs/fpa/Image/Algorithm.hxx @@ -118,10 +118,13 @@ _GetMark( const TVertex& v ) const // ------------------------------------------------------------------------- template< class _TInputImage, class _TOutputImage > -void fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: -_UpdateResult( const _TQueueNode& n ) +bool fpa::Image::Algorithm< _TInputImage, _TOutputImage >:: +_UpdateResult( _TQueueNode& n ) { + bool res = this->Superclass::_UpdateResult( n ); + std::cout << n.Vertex << " " << n.Result << std::endl; this->GetOutput( )->SetPixel( n.Vertex, n.Result ); + return( res ); } // ------------------------------------------------------------------------- diff --git a/libs/fpa/Image/Functors/RegionGrow/BinaryThreshold.hxx b/libs/fpa/Image/Functors/RegionGrow/BinaryThreshold.hxx index 7f2b9dc..b41db08 100644 --- a/libs/fpa/Image/Functors/RegionGrow/BinaryThreshold.hxx +++ b/libs/fpa/Image/Functors/RegionGrow/BinaryThreshold.hxx @@ -14,6 +14,9 @@ Evaluate( const TIndex& a, const TIndex& b ) const if( im != NULL ) { TPixel v = im->GetPixel( b ); + + std::cout << a << " " << v << " " << this->m_Lower << " " << this->m_Upper << std::endl; + return( ( this->m_Lower < v && v < this->m_Upper )? this->m_InsideValue: diff --git a/libs/fpa/Image/MoriFilter.h b/libs/fpa/Image/MoriFilter.h index 0707ff5..a78aab7 100644 --- a/libs/fpa/Image/MoriFilter.h +++ b/libs/fpa/Image/MoriFilter.h @@ -16,18 +16,19 @@ namespace fpa : public itk::ImageToImageFilter< _TInputImage, _TOutputImage > { public: - typedef MoriFilter Self; + typedef MoriFilter Self; typedef itk::ImageToImageFilter< _TInputImage, _TOutputImage > Superclass; typedef itk::SmartPointer< Self > Pointer; typedef itk::SmartPointer< const Self > ConstPointer; typedef itk::Image< _TAuxPixel, _TInputImage::ImageDimension > TAuxImage; - typedef fpa::Image::MoriFilterHelper< _TInputImage, TAuxImage > THelper; + typedef fpa::Image::MoriFilterHelper< _TInputImage, TAuxImage > THelper; typedef itk::BinaryThresholdImageFilter< TAuxImage, _TOutputImage > TThreshold; typedef typename _TInputImage::IndexType TIndex; typedef typename _TInputImage::PixelType TInputPixel; typedef typename _TOutputImage::PixelType TOutputPixel; + typedef typename THelper::TCurve TCurve; public: itkNewMacro( Self ); @@ -45,6 +46,8 @@ namespace fpa TInputPixel GetStep( ) const; TOutputPixel GetInsideValue( ) const; TOutputPixel GetOutsideValue( ) const; + TOutputPixel GetOptimumThreshold( ) const; + TCurve GetCurve( ) const; void SetLower( const TInputPixel& v ); void SetUpper( const TInputPixel& v ); @@ -56,18 +59,6 @@ namespace fpa void SetInsideValue( const TOutputPixel& v ); void SetOutsideValue( const TOutputPixel& v ); - - /* TODO - itkGetConstMacro( Lower, TPixel ); - itkGetConstMacro( Upper, TPixel ); - itkGetConstMacro( Step, TPixel ); - itkGetConstMacro( Sensitivity, double ); - itkSetMacro( Lower, TPixel ); - itkSetMacro( Upper, TPixel ); - itkSetMacro( Step, TPixel ); - itkSetMacro( Sensitivity, double ); - */ - protected: MoriFilter( ); virtual ~MoriFilter( ); diff --git a/libs/fpa/Image/MoriFilter.hxx b/libs/fpa/Image/MoriFilter.hxx index 9f822c9..6c749c6 100644 --- a/libs/fpa/Image/MoriFilter.hxx +++ b/libs/fpa/Image/MoriFilter.hxx @@ -78,6 +78,27 @@ GetOutsideValue( ) const return( this->m_Threshold->GetInsideValue( ) ); } +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TAuxPixel > +typename +fpa::Image::MoriFilter< _TInputImage, _TOutputImage, _TAuxPixel >:: +TOutputPixel +fpa::Image::MoriFilter< _TInputImage, _TOutputImage, _TAuxPixel >:: +GetOptimumThreshold( ) const +{ + return( this->m_Helper->GetOptimumThreshold( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TAuxPixel > +typename +fpa::Image::MoriFilter< _TInputImage, _TOutputImage, _TAuxPixel >:: +TCurve fpa::Image::MoriFilter< _TInputImage, _TOutputImage, _TAuxPixel >:: +GetCurve( ) const +{ + return( this->m_Helper->GetCurve( ) ); +} + // ------------------------------------------------------------------------- template< class _TInputImage, class _TOutputImage, class _TAuxPixel > void fpa::Image::MoriFilter< _TInputImage, _TOutputImage, _TAuxPixel >:: @@ -157,8 +178,7 @@ template< class _TInputImage, class _TOutputImage, class _TAuxPixel > void fpa::Image::MoriFilter< _TInputImage, _TOutputImage, _TAuxPixel >:: GenerateData( ) { - this->m_Helper->ClearSeeds( ); - this->m_Helper->AddSeed( this->m_Seed, this->GetOutsideValue( ) ); + this->m_Helper->SetSeed( this->m_Seed ); this->m_Helper->SetInput( this->GetInput( ) ); this->m_Helper->Update( ); diff --git a/libs/fpa/Image/MoriFilterHelper.h b/libs/fpa/Image/MoriFilterHelper.h index 6d55ec7..d9a4a3d 100644 --- a/libs/fpa/Image/MoriFilterHelper.h +++ b/libs/fpa/Image/MoriFilterHelper.h @@ -1,10 +1,13 @@ #ifndef __fpa__Image__MoriFilterHelper__h__ #define __fpa__Image__MoriFilterHelper__h__ +/* TODO + #include + #include +*/ #include #include -#include -#include +#include namespace fpa { @@ -14,52 +17,68 @@ namespace fpa */ template< class _TInputImage, class _TOutputImage > class MoriFilterHelper - : public fpa::Image::RegionGrow< _TInputImage, _TOutputImage > + : public itk::ImageToImageFilter< _TInputImage, _TOutputImage > { public: - typedef MoriFilterHelper Self; - typedef fpa::Image::RegionGrow< _TInputImage, _TOutputImage > Superclass; - typedef itk::SmartPointer< Self > Pointer; - typedef itk::SmartPointer< const Self > ConstPointer; - - typedef typename Superclass::TOutput TOutput; - typedef typename Superclass::TVertex TVertex; - typedef typename Superclass::TGrowFunction TGrowFunction; - typedef typename _TInputImage::PixelType TPixel; - typedef fpa::Image::Functors::RegionGrow::BinaryThreshold< _TInputImage, TOutput > TBinThresholdFunction; - - protected: - typedef typename Superclass::_TQueueNode _TQueueNode; - typedef typename Superclass::_TQueue _TQueue; - - typedef std::pair< TPixel, unsigned long > TCurveData; - typedef std::vector< TCurveData > TCurve; + typedef MoriFilterHelper 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 TIndex; + typedef typename TInputImage::PixelType TInputPixel; + typedef typename TOutputImage::PixelType TOutputPixel; + + typedef std::pair< TInputPixel, unsigned long > TCurveData; + typedef std::vector< TCurveData > TCurve; + + /* TODO + typedef typename Superclass::TOutput TOutput; + typedef typename Superclass::TVertex TVertex; + typedef typename Superclass::TGrowFunction TGrowFunction; + typedef typename _TInputImage::PixelType TPixel; + typedef fpa::Image::Functors::RegionGrow::BinaryThreshold< _TInputImage, TOutput > TBinThresholdFunction; + protected: + typedef typename Superclass::_TQueueNode _TQueueNode; + typedef typename Superclass::_TQueue _TQueue; + */ public: itkNewMacro( Self ); - itkTypeMacro( fpa::Image::MoriFilterHelper, fpa::Image::RegionGrow ); + itkTypeMacro( fpa::Image::MoriFilterHelper, itk::ImageToImageFilter ); - itkGetConstMacro( Lower, TPixel ); - itkGetConstMacro( Upper, TPixel ); - itkGetConstMacro( Step, TPixel ); + itkGetConstMacro( Seed, TIndex ); + itkGetConstMacro( Lower, TInputPixel ); + itkGetConstMacro( Upper, TInputPixel ); + itkGetConstMacro( Step, TInputPixel ); itkGetConstMacro( OptimumThreshold, typename _TOutputImage::PixelType ); + itkGetConstMacro( Curve, TCurve ); - itkSetMacro( Lower, TPixel ); - itkSetMacro( Upper, TPixel ); - itkSetMacro( Step, TPixel ); - + itkSetMacro( Seed, TIndex ); + itkSetMacro( Lower, TInputPixel ); + itkSetMacro( Upper, TInputPixel ); + itkSetMacro( Step, TInputPixel ); protected: - MoriFilterHelper( ); - virtual ~MoriFilterHelper( ); - - virtual bool _ContinueGenerateData( ) override; - virtual void _BeforeGenerateData( ) override; - virtual void _AfterGenerateData( ) override; - virtual void _BeforeLoop( ) override; - virtual void _AfterLoop( ) override; - virtual bool _UpdateValue( _TQueueNode& v, const _TQueueNode& p ) override; - virtual void _UpdateResult( const _TQueueNode& n ) override; + MoriFilterHelper( ) + : Superclass( ) + { + } + virtual ~MoriFilterHelper( ) + { + } + + /* TODO + virtual bool _ContinueGenerateData( ) override; + virtual void _BeforeGenerateData( ) override; + virtual void _AfterGenerateData( ) override; + virtual void _BeforeLoop( ) override; + virtual void _AfterLoop( ) override; + virtual bool _UpdateValue( _TQueueNode& v, const _TQueueNode& p ) override; + virtual bool _UpdateResult( _TQueueNode& n ) override; + */ private: // Purposely not defined @@ -67,12 +86,12 @@ namespace fpa Self& operator=( const Self& other ); protected: - TPixel m_Lower; - TPixel m_Upper; - TPixel m_Step; + TIndex m_Seed; + TInputPixel m_Lower; + TInputPixel m_Upper; + TInputPixel m_Step; typename _TOutputImage::PixelType m_OptimumThreshold; - _TQueue m_NextQueue; unsigned long m_ActualCount; TCurve m_Curve; }; @@ -81,9 +100,11 @@ namespace fpa } // ecapseman -#ifndef ITK_MANUAL_INSTANTIATION -# include -#endif // ITK_MANUAL_INSTANTIATION +/* TODO + #ifndef ITK_MANUAL_INSTANTIATION + # include + #endif // ITK_MANUAL_INSTANTIATION +*/ #endif // __fpa__Image__MoriFilterHelper__h__ diff --git a/libs/fpa/Image/MoriFilterHelper.hxx b/libs/fpa/Image/MoriFilterHelper.hxx index 4ddb234..fb6826a 100644 --- a/libs/fpa/Image/MoriFilterHelper.hxx +++ b/libs/fpa/Image/MoriFilterHelper.hxx @@ -32,11 +32,10 @@ _ContinueGenerateData( ) { TBinThresholdFunction* functor = dynamic_cast< TBinThresholdFunction* >( this->GetGrowFunction( ) ); - TPixel u = functor->GetUpper( ); // Update flooding data + TPixel u = functor->GetUpper( ); this->m_Curve.push_back( TCurveData( u, this->m_ActualCount ) ); - std::cout << u << " " << this->m_ActualCount << std::endl; // Update thresholds if( u < this->m_Upper ) @@ -45,9 +44,30 @@ _ContinueGenerateData( ) if( u > this->m_Upper ) u = this->m_Upper; functor->SetUpper( u ); - this->m_Queue = this->m_NextQueue; + + while( this->m_Queue.size( ) > 0 ) + this->m_Queue.pop( ); + // TODO: std::cout << "-----> " << this->m_NextQueue.size( ) << " " << u << std::endl; while( this->m_NextQueue.size( ) > 0 ) + { + this->m_Queue.push( this->m_NextQueue.front( ) ); + // TODO: std::cout << "\t" << this->m_NextQueue.front( ).Vertex << std::endl; this->m_NextQueue.pop( ); + + } // elihw + + /* TODO: ensure pixels belong to new threshold? + while( this->m_Queue.size( ) > 0 ) + this->m_Queue.pop( ); + while( this->m_NextQueue.size( ) > 0 ) + { + _TQueueNode n = this->m_NextQueue.front( ); + this->m_NextQueue.pop( ); + + if( ??? ) + this->m_Queue.push( n ); + } + */ return( true ); } else @@ -122,22 +142,38 @@ template< class _TInputImage, class _TOutputImage > bool fpa::Image::MoriFilterHelper< _TInputImage, _TOutputImage >:: _UpdateValue( _TQueueNode& v, const _TQueueNode& p ) { - typedef typename _TOutputImage::PixelType _TOut; - - bool ret = this->Superclass::_UpdateValue( v, p ); - v.Result = _TOut( this->m_Curve.size( ) + 1 ); - if( !ret ) - this->m_NextQueue.push( v ); - return( ret ); + return( this->Superclass::_UpdateValue( v, p ) ); + /* TODO + typedef typename _TOutputImage::PixelType _TOut; + + bool ret = this->Superclass::_UpdateValue( v, p ); + v.Result = _TOut( this->m_Curve.size( ) + 1 ); + if( !ret ) + this->m_NextQueue.push( v ); + return( ret ); + */ } // ------------------------------------------------------------------------- template< class _TInputImage, class _TOutputImage > -void fpa::Image::MoriFilterHelper< _TInputImage, _TOutputImage >:: -_UpdateResult( const _TQueueNode& n ) +bool fpa::Image::MoriFilterHelper< _TInputImage, _TOutputImage >:: +_UpdateResult( _TQueueNode& n ) { - this->Superclass::_UpdateResult( n ); - this->m_ActualCount += 1; + typedef typename _TOutputImage::PixelType _TOut; + + n.Result = _TOut( this->m_Curve.size( ) + 1 ); + if( this->Superclass::_UpdateResult( n ) ) + { + this->m_ActualCount += 1; + std::cout << this->m_ActualCount << std::endl; + return( true ); + } + else + { + this->m_NextQueue.push( n ); + return( false ); + + } // fi } #endif // __fpa__Image__MoriFilterHelper__hxx__ -- 2.47.1