From b70a564ee2d7bc180b77a05c37ab431ab9c393e7 Mon Sep 17 00:00:00 2001 From: Leonardo Florez-Valencia Date: Sat, 4 Apr 2015 11:24:17 -0500 Subject: [PATCH] Major refactoring --- appli/CMakeLists.txt | 9 +- appli/examples/CMakeLists.txt | 121 +++--- ...rithmRegionGrow_GaussianModelEstimator.cxx | 24 +- .../example_Image_Dijkstra_CostFromInput.cxx | 177 +++++++++ ...xample_Image_Dijkstra_CostFromRGBInput.cxx | 178 +++++++++ .../example_Image_Dijkstra_DanielssonCost.cxx | 204 ++++++++++ .../example_Image_RegionGrow_AllPixels.cxx | 163 ++++++++ .../example_Image_RegionGrow_AllRGBPixels.cxx | 165 ++++++++ doc/UML/fpa.dia | Bin 0 -> 4287 bytes lib/CMakeLists.txt | 20 +- lib/fpa/Base/Algorithm.h | 196 +++++----- lib/fpa/Base/Algorithm.hxx | 353 +++++++++--------- lib/fpa/Base/Dijkstra.h | 123 +++--- lib/fpa/Base/Dijkstra.hxx | 82 ++-- lib/fpa/Base/Events.h | 195 +++------- lib/fpa/Base/Functors/InvertCostFunction.h | 2 +- lib/fpa/Base/Functors/TautologyFunction.h | 53 +++ lib/fpa/Base/RegionGrow.h | 111 +++--- lib/fpa/Base/RegionGrow.hxx | 70 ++-- lib/fpa/Image/Algorithm.h | 165 +++----- lib/fpa/Image/Algorithm.hxx | 171 ++++----- lib/fpa/Image/Dijkstra.h | 77 ++-- lib/fpa/Image/Dijkstra.hxx | 59 +++ lib/fpa/Image/Functors/ImageCostFunction.h | 90 +++++ lib/fpa/Image/Functors/ImageFunction.h | 62 --- lib/fpa/Image/RegionGrow.h | 82 ++-- lib/fpa/Image/RegionGrow.hxx | 41 ++ lib/fpa/VTK/Image2DObserver.h | 31 +- lib/fpa/VTK/Image2DObserver.hxx | 248 +++++++----- 29 files changed, 2103 insertions(+), 1169 deletions(-) create mode 100644 appli/examples/example_Image_Dijkstra_CostFromInput.cxx create mode 100644 appli/examples/example_Image_Dijkstra_CostFromRGBInput.cxx create mode 100644 appli/examples/example_Image_Dijkstra_DanielssonCost.cxx create mode 100644 appli/examples/example_Image_RegionGrow_AllPixels.cxx create mode 100644 appli/examples/example_Image_RegionGrow_AllRGBPixels.cxx create mode 100644 doc/UML/fpa.dia create mode 100644 lib/fpa/Base/Functors/TautologyFunction.h create mode 100644 lib/fpa/Image/Dijkstra.hxx create mode 100644 lib/fpa/Image/Functors/ImageCostFunction.h delete mode 100644 lib/fpa/Image/Functors/ImageFunction.h create mode 100644 lib/fpa/Image/RegionGrow.hxx diff --git a/appli/CMakeLists.txt b/appli/CMakeLists.txt index 71b459c..61d2cd0 100644 --- a/appli/CMakeLists.txt +++ b/appli/CMakeLists.txt @@ -1,6 +1,7 @@ - -SUBDIRS( - examples - ) +IF(BUILD_EXAMPLES) + SUBDIRS( + examples + ) +ENDIF(BUILD_EXAMPLES) ## eof - $RCSfile$ diff --git a/appli/examples/CMakeLists.txt b/appli/examples/CMakeLists.txt index ad80e0a..985071e 100644 --- a/appli/examples/CMakeLists.txt +++ b/appli/examples/CMakeLists.txt @@ -1,58 +1,73 @@ -IF(BUILD_EXAMPLES) +IF(USE_VTK) SET( - APPLIS - example_Thinning - example_BinaryDistanceMap - example_HausdorffDistance - example_ImageAlgorithmRegionGrow_00 - example_ImageAlgorithmDijkstra_00 - example_ImageAlgorithmFastMarching_00 + SIMPLE_VTK_EXAMPLES + example_Image_RegionGrow_AllPixels + example_Image_RegionGrow_AllRGBPixels + example_Image_Dijkstra_CostFromInput + example_Image_Dijkstra_CostFromRGBInput + example_Image_Dijkstra_DanielssonCost ) + FOREACH(EX ${SIMPLE_VTK_EXAMPLES}) + ADD_EXECUTABLE(${EX} ${EX}.cxx) + TARGET_LINK_LIBRARIES(${EX} FrontAlgorithms) + ENDFOREACH(EX) +ENDIF(USE_VTK) - FOREACH(APP ${APPLIS}) - ADD_EXECUTABLE(${APP} ${APP}.cxx) - TARGET_LINK_LIBRARIES(${APP} FrontAlgorithms) - ENDFOREACH(APP) - - IF(USE_VTK) - SET( - vtk_APPLIS - example_ImageAlgorithmRegionGrow_01 - example_ImageAlgorithmRegionGrow_MultipleThresholds - example_ImageAlgorithmDijkstra_01 - example_ImageAlgorithmDijkstra_02 - example_ImageAlgorithmDijkstra_03 - example_ImageAlgorithmFastMarching_01 - example_ImageAlgorithm_Skeletonization - ) - - FOREACH(APP ${vtk_APPLIS}) - ADD_EXECUTABLE(${APP} ${APP}.cxx) - TARGET_LINK_LIBRARIES( - ${APP} - FrontAlgorithms - ${VTK_LIBRARIES} vtkIOLegacy - ) - ENDFOREACH(APP) - - IF(USE_cpPlugins) - SET( - cpPlugins_APPLIS - example_ImageAlgorithmRegionGrow_GaussianModelEstimator - ) - - FOREACH(APP ${cpPlugins_APPLIS}) - ADD_EXECUTABLE(${APP} ${APP}.cxx) - TARGET_LINK_LIBRARIES( - ${APP} - FrontAlgorithms - ${cpPlugins_Extensions_LIBRARY_NAME} - ) - ENDFOREACH(APP) - - ENDIF(USE_cpPlugins) - - ENDIF(USE_VTK) -ENDIF(BUILD_EXAMPLES) +#IF(BUILD_EXAMPLES) +# SET( +# APPLIS +# example_Thinning +# example_BinaryDistanceMap +# example_HausdorffDistance +# example_ImageAlgorithmRegionGrow_00 +# example_ImageAlgorithmDijkstra_00 +# example_ImageAlgorithmFastMarching_00 +# ) + +# FOREACH(APP ${APPLIS}) +# ADD_EXECUTABLE(${APP} ${APP}.cxx) +# TARGET_LINK_LIBRARIES(${APP} FrontAlgorithms) +# ENDFOREACH(APP) + +# IF(USE_VTK) +# SET( +# vtk_APPLIS +# example_ImageAlgorithmRegionGrow_01 +# example_ImageAlgorithmRegionGrow_MultipleThresholds +# example_ImageAlgorithmDijkstra_01 +# example_ImageAlgorithmDijkstra_02 +# example_ImageAlgorithmDijkstra_03 +# example_ImageAlgorithmFastMarching_01 +# example_ImageAlgorithm_Skeletonization +# ) + +# FOREACH(APP ${vtk_APPLIS}) +# ADD_EXECUTABLE(${APP} ${APP}.cxx) +# TARGET_LINK_LIBRARIES( +# ${APP} +# FrontAlgorithms +# ${VTK_LIBRARIES} vtkIOLegacy +# ) +# ENDFOREACH(APP) + +# IF(USE_cpPlugins) +# SET( +# cpPlugins_APPLIS +# example_ImageAlgorithmRegionGrow_GaussianModelEstimator +# ) + +# FOREACH(APP ${cpPlugins_APPLIS}) +# ADD_EXECUTABLE(${APP} ${APP}.cxx) +# TARGET_LINK_LIBRARIES( +# ${APP} +# FrontAlgorithms +# ${cpPlugins_Extensions_LIBRARY_NAME} +# ) +# ENDFOREACH(APP) + +# ENDIF(USE_cpPlugins) + +# ENDIF(USE_VTK) +#ENDIF(BUILD_EXAMPLES) ## eof - $RCSfile$ diff --git a/appli/examples/example_ImageAlgorithmRegionGrow_GaussianModelEstimator.cxx b/appli/examples/example_ImageAlgorithmRegionGrow_GaussianModelEstimator.cxx index 850ef5a..04fa936 100644 --- a/appli/examples/example_ImageAlgorithmRegionGrow_GaussianModelEstimator.cxx +++ b/appli/examples/example_ImageAlgorithmRegionGrow_GaussianModelEstimator.cxx @@ -22,6 +22,7 @@ #include #include #include +#include // ------------------------------------------------------------------------- const unsigned int Dim = 2; @@ -57,6 +58,7 @@ public: typedef typename Superclass::TIndex TIndex; typedef cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, 3 > TEstimator; + typedef cpPlugins::Extensions::Algorithms::RGBToYPbPrFunction< S > TYPbPrFunction; public: itkNewMacro( Self ); @@ -96,22 +98,26 @@ public: { if( !( this->m_Marks->GetPixel( idx ) ) ) { - this->m_Estimator->AddSample( - S( rgb.GetRed( ) ), - S( rgb.GetGreen( ) ), - S( rgb.GetBlue( ) ) - ); + this->m_Estimator->AddSample( this->m_YPbPrFunction( rgb ) ); this->m_Marks->SetPixel( idx, true ); -#error CONTINUE HERE!!!! - std::cout << this->m_Estimator->GetNumberOfSamples( ) << " " << this->m_ModelSupport << std::endl; if( this->m_Estimator->GetNumberOfSamples( ) == this->m_ModelSupport ) + { this->m_Estimating = true; + this->m_Estimator->UpdateModel( ); + std::cout << this->m_Estimator->GetMinimumProbability( ) << std::endl; + std::cout << this->m_Estimator->GetMaximumProbability( ) << std::endl; + + } // fi } // fi return( true ); } else - return( false ); + { + S p = this->m_Estimator->Probability( this->m_YPbPrFunction( rgb ) ); + return( p > this->m_Estimator->GetMinimumProbability( ) ); + + } // fi } protected: @@ -133,6 +139,8 @@ private: protected: typename TEstimator::Pointer m_Estimator; + TYPbPrFunction m_YPbPrFunction; + unsigned long m_ModelSupport; mutable bool m_Estimating; typename TMarks::Pointer m_Marks; diff --git a/appli/examples/example_Image_Dijkstra_CostFromInput.cxx b/appli/examples/example_Image_Dijkstra_CostFromInput.cxx new file mode 100644 index 0000000..65003e2 --- /dev/null +++ b/appli/examples/example_Image_Dijkstra_CostFromInput.cxx @@ -0,0 +1,177 @@ +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TInputPixel; +typedef float TOutputPixel; + +typedef itk::Image< TInputPixel, Dim > TInputImage; +typedef itk::Image< TOutputPixel, Dim > TOutputImage; +typedef itk::ImageToVTKImageFilter< TInputImage > TVTKInputImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + if( argc < 5 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image output_image neighborhood_order stop_at_one_front" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_fn = argv[ 1 ]; + std::string output_image_fn = argv[ 2 ]; + unsigned int neighborhood_order = std::atoi( argv[ 3 ] ); + bool stop_at_one_front = ( std::atoi( argv[ 4 ] ) != 0 ); + + // Read image + itk::ImageFileReader< TInputImage >::Pointer input_image_reader = + itk::ImageFileReader< TInputImage >::New( ); + input_image_reader->SetFileName( input_image_fn ); + try + { + input_image_reader->Update( ); + } + catch( itk::ExceptionObject& err ) + { + std::cerr + << "Error while reading image from " << input_image_fn << ": " + << err << std::endl; + return( 1 ); + + } // yrt + TInputImage::ConstPointer input_image = input_image_reader->GetOutput( ); + TVTKInputImage::Pointer vtk_input_image = TVTKInputImage::New( ); + vtk_input_image->SetInput( input_image ); + vtk_input_image->Update( ); + + // VTK visualization + vtkSmartPointer< vtkImageActor > actor = + vtkSmartPointer< vtkImageActor >::New( ); + actor->SetInputData( vtk_input_image->GetOutput( ) ); + + vtkSmartPointer< vtkRenderer > renderer = + vtkSmartPointer< vtkRenderer >::New( ); + renderer->SetBackground( 0.1, 0.2, 0.7 ); + renderer->AddActor( actor ); + vtkSmartPointer< vtkRenderWindow > window = + vtkSmartPointer< vtkRenderWindow >::New( ); + window->SetSize( 800, 800 ); + window->AddRenderer( renderer ); + + // Correct camera due to the loaded image + vtkCamera* camera = renderer->GetActiveCamera( ); + camera->SetViewUp( 0, -1, 0 ); + camera->SetPosition( 0, 0, -1 ); + camera->SetFocalPoint( 0, 0, 0 ); + + // VTK interaction + vtkSmartPointer< vtkInteractorStyleImage > imageStyle = + vtkSmartPointer< vtkInteractorStyleImage >::New( ); + vtkSmartPointer< vtkRenderWindowInteractor > interactor = + vtkSmartPointer< vtkRenderWindowInteractor >::New( ); + interactor->SetInteractorStyle( imageStyle ); + window->SetInteractor( interactor ); + + // Create the widget and its representation + vtkSmartPointer< vtkPointHandleRepresentation3D > handle = + vtkSmartPointer< vtkPointHandleRepresentation3D >::New( ); + handle->GetProperty( )->SetColor( 1, 0, 0 ); + vtkSmartPointer< vtkSeedRepresentation > rep = + vtkSmartPointer< vtkSeedRepresentation >::New( ); + rep->SetHandleRepresentation( handle ); + + vtkSmartPointer< vtkSeedWidget > widget = + vtkSmartPointer< vtkSeedWidget >::New( ); + widget->SetInteractor( interactor ); + widget->SetRepresentation( rep ); + + // Let some interaction + interactor->Initialize( ); + renderer->ResetCamera( ); + window->Render( ); + widget->On( ); + interactor->Start( ); + + // Prepare region grow filter + typedef fpa::Image::Dijkstra< TInputImage, TOutputImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( input_image ); + filter->SetNeighborhoodOrder( neighborhood_order ); + filter->SetStopAtOneFront( stop_at_one_front ); + + // Get user-given seeds + for( unsigned int s = 0; s < rep->GetNumberOfSeeds( ); s++ ) + { + double pos[ 3 ]; + rep->GetSeedWorldPosition( s, pos ); + + TInputImage::PointType pnt; + pnt[ 0 ] = TInputImage::PointType::ValueType( pos[ 0 ] ); + pnt[ 1 ] = TInputImage::PointType::ValueType( pos[ 1 ] ); + + TInputImage::IndexType idx; + if( input_image->TransformPhysicalPointToIndex( pnt, idx ) ) + filter->AddSeed( idx, 0 ); + + } // rof + + // Prepare graphical debugger + typedef fpa::VTK::Image2DObserver< TFilter, vtkRenderWindow > TDebugger; + TDebugger::Pointer debugger = TDebugger::New( ); + debugger->SetRenderWindow( window ); + debugger->SetRenderPercentage( 0.001 ); + filter->AddObserver( itk::AnyEvent( ), debugger ); + filter->ThrowEventsOn( ); + + // Go! + filter->Update( ); + + // Save final total cost map + itk::ImageFileWriter< TOutputImage >::Pointer output_image_writer = + itk::ImageFileWriter< TOutputImage >::New( ); + output_image_writer->SetFileName( output_image_fn ); + output_image_writer->SetInput( filter->GetOutput( ) ); + try + { + output_image_writer->Update( ); + } + catch( itk::ExceptionObject& err ) + { + std::cerr + << "Error while writing image to " << output_image_fn << ": " + << err << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/example_Image_Dijkstra_CostFromRGBInput.cxx b/appli/examples/example_Image_Dijkstra_CostFromRGBInput.cxx new file mode 100644 index 0000000..c181359 --- /dev/null +++ b/appli/examples/example_Image_Dijkstra_CostFromRGBInput.cxx @@ -0,0 +1,178 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef itk::RGBPixel< unsigned char > TInputPixel; +typedef float TOutputPixel; + +typedef itk::Image< TInputPixel, Dim > TInputImage; +typedef itk::Image< TOutputPixel, Dim > TOutputImage; +typedef itk::ImageToVTKImageFilter< TInputImage > TVTKInputImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + if( argc < 5 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image output_image neighborhood_order stop_at_one_front" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_fn = argv[ 1 ]; + std::string output_image_fn = argv[ 2 ]; + unsigned int neighborhood_order = std::atoi( argv[ 3 ] ); + bool stop_at_one_front = ( std::atoi( argv[ 4 ] ) != 0 ); + + // Read image + itk::ImageFileReader< TInputImage >::Pointer input_image_reader = + itk::ImageFileReader< TInputImage >::New( ); + input_image_reader->SetFileName( input_image_fn ); + try + { + input_image_reader->Update( ); + } + catch( itk::ExceptionObject& err ) + { + std::cerr + << "Error while reading image from " << input_image_fn << ": " + << err << std::endl; + return( 1 ); + + } // yrt + TInputImage::ConstPointer input_image = input_image_reader->GetOutput( ); + TVTKInputImage::Pointer vtk_input_image = TVTKInputImage::New( ); + vtk_input_image->SetInput( input_image ); + vtk_input_image->Update( ); + + // VTK visualization + vtkSmartPointer< vtkImageActor > actor = + vtkSmartPointer< vtkImageActor >::New( ); + actor->SetInputData( vtk_input_image->GetOutput( ) ); + + vtkSmartPointer< vtkRenderer > renderer = + vtkSmartPointer< vtkRenderer >::New( ); + renderer->SetBackground( 0.1, 0.2, 0.7 ); + renderer->AddActor( actor ); + vtkSmartPointer< vtkRenderWindow > window = + vtkSmartPointer< vtkRenderWindow >::New( ); + window->SetSize( 800, 800 ); + window->AddRenderer( renderer ); + + // Correct camera due to the loaded image + vtkCamera* camera = renderer->GetActiveCamera( ); + camera->SetViewUp( 0, -1, 0 ); + camera->SetPosition( 0, 0, -1 ); + camera->SetFocalPoint( 0, 0, 0 ); + + // VTK interaction + vtkSmartPointer< vtkInteractorStyleImage > imageStyle = + vtkSmartPointer< vtkInteractorStyleImage >::New( ); + vtkSmartPointer< vtkRenderWindowInteractor > interactor = + vtkSmartPointer< vtkRenderWindowInteractor >::New( ); + interactor->SetInteractorStyle( imageStyle ); + window->SetInteractor( interactor ); + + // Create the widget and its representation + vtkSmartPointer< vtkPointHandleRepresentation3D > handle = + vtkSmartPointer< vtkPointHandleRepresentation3D >::New( ); + handle->GetProperty( )->SetColor( 1, 0, 0 ); + vtkSmartPointer< vtkSeedRepresentation > rep = + vtkSmartPointer< vtkSeedRepresentation >::New( ); + rep->SetHandleRepresentation( handle ); + + vtkSmartPointer< vtkSeedWidget > widget = + vtkSmartPointer< vtkSeedWidget >::New( ); + widget->SetInteractor( interactor ); + widget->SetRepresentation( rep ); + + // Let some interaction + interactor->Initialize( ); + renderer->ResetCamera( ); + window->Render( ); + widget->On( ); + interactor->Start( ); + + // Prepare region grow filter + typedef fpa::Image::Dijkstra< TInputImage, TOutputImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( input_image ); + filter->SetNeighborhoodOrder( neighborhood_order ); + filter->SetStopAtOneFront( stop_at_one_front ); + + // Get user-given seeds + for( unsigned int s = 0; s < rep->GetNumberOfSeeds( ); s++ ) + { + double pos[ 3 ]; + rep->GetSeedWorldPosition( s, pos ); + + TInputImage::PointType pnt; + pnt[ 0 ] = TInputImage::PointType::ValueType( pos[ 0 ] ); + pnt[ 1 ] = TInputImage::PointType::ValueType( pos[ 1 ] ); + + TInputImage::IndexType idx; + if( input_image->TransformPhysicalPointToIndex( pnt, idx ) ) + filter->AddSeed( idx, 0 ); + + } // rof + + // Prepare graphical debugger + typedef fpa::VTK::Image2DObserver< TFilter, vtkRenderWindow > TDebugger; + TDebugger::Pointer debugger = TDebugger::New( ); + debugger->SetRenderWindow( window ); + debugger->SetRenderPercentage( 0.001 ); + filter->AddObserver( itk::AnyEvent( ), debugger ); + filter->ThrowEventsOn( ); + + // Go! + filter->Update( ); + + // Save final total cost map + itk::ImageFileWriter< TOutputImage >::Pointer output_image_writer = + itk::ImageFileWriter< TOutputImage >::New( ); + output_image_writer->SetFileName( output_image_fn ); + output_image_writer->SetInput( filter->GetOutput( ) ); + try + { + output_image_writer->Update( ); + } + catch( itk::ExceptionObject& err ) + { + std::cerr + << "Error while writing image to " << output_image_fn << ": " + << err << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/example_Image_Dijkstra_DanielssonCost.cxx b/appli/examples/example_Image_Dijkstra_DanielssonCost.cxx new file mode 100644 index 0000000..3eb387f --- /dev/null +++ b/appli/examples/example_Image_Dijkstra_DanielssonCost.cxx @@ -0,0 +1,204 @@ +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TInputPixel; +typedef float TOutputPixel; + +typedef itk::Image< TInputPixel, Dim > TInputImage; +typedef itk::Image< TOutputPixel, Dim > TOutputImage; +typedef itk::ImageToVTKImageFilter< TInputImage > TVTKInputImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + if( argc < 5 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image output_image neighborhood_order stop_at_one_front" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_fn = argv[ 1 ]; + std::string output_image_fn = argv[ 2 ]; + unsigned int neighborhood_order = std::atoi( argv[ 3 ] ); + bool stop_at_one_front = ( std::atoi( argv[ 4 ] ) != 0 ); + + // Read image + itk::ImageFileReader< TInputImage >::Pointer input_image_reader = + itk::ImageFileReader< TInputImage >::New( ); + input_image_reader->SetFileName( input_image_fn ); + try + { + input_image_reader->Update( ); + } + catch( itk::ExceptionObject& err ) + { + std::cerr + << "Error while reading image from " << input_image_fn << ": " + << err << std::endl; + return( 1 ); + + } // yrt + TInputImage::ConstPointer input_image = input_image_reader->GetOutput( ); + TVTKInputImage::Pointer vtk_input_image = TVTKInputImage::New( ); + vtk_input_image->SetInput( input_image ); + vtk_input_image->Update( ); + + // VTK visualization + vtkSmartPointer< vtkImageActor > actor = + vtkSmartPointer< vtkImageActor >::New( ); + actor->SetInputData( vtk_input_image->GetOutput( ) ); + + vtkSmartPointer< vtkRenderer > renderer = + vtkSmartPointer< vtkRenderer >::New( ); + renderer->SetBackground( 0.1, 0.2, 0.7 ); + renderer->AddActor( actor ); + vtkSmartPointer< vtkRenderWindow > window = + vtkSmartPointer< vtkRenderWindow >::New( ); + window->SetSize( 800, 800 ); + window->AddRenderer( renderer ); + + // Correct camera due to the loaded image + vtkCamera* camera = renderer->GetActiveCamera( ); + camera->SetViewUp( 0, -1, 0 ); + camera->SetPosition( 0, 0, -1 ); + camera->SetFocalPoint( 0, 0, 0 ); + + // VTK interaction + vtkSmartPointer< vtkInteractorStyleImage > imageStyle = + vtkSmartPointer< vtkInteractorStyleImage >::New( ); + vtkSmartPointer< vtkRenderWindowInteractor > interactor = + vtkSmartPointer< vtkRenderWindowInteractor >::New( ); + interactor->SetInteractorStyle( imageStyle ); + window->SetInteractor( interactor ); + + // Create the widget and its representation + vtkSmartPointer< vtkPointHandleRepresentation3D > handle = + vtkSmartPointer< vtkPointHandleRepresentation3D >::New( ); + handle->GetProperty( )->SetColor( 1, 0, 0 ); + vtkSmartPointer< vtkSeedRepresentation > rep = + vtkSmartPointer< vtkSeedRepresentation >::New( ); + rep->SetHandleRepresentation( handle ); + + vtkSmartPointer< vtkSeedWidget > widget = + vtkSmartPointer< vtkSeedWidget >::New( ); + widget->SetInteractor( interactor ); + widget->SetRepresentation( rep ); + + // Let some interaction + interactor->Initialize( ); + renderer->ResetCamera( ); + window->Render( ); + widget->On( ); + interactor->Start( ); + + // Invert input image + itk::MinimumMaximumImageCalculator< TInputImage >::Pointer minmax = + itk::MinimumMaximumImageCalculator< TInputImage >::New( ); + minmax->SetImage( input_image ); + minmax->Compute( ); + + itk::InvertIntensityImageFilter< TInputImage >::Pointer invert = + itk::InvertIntensityImageFilter< TInputImage >::New( ); + invert->SetInput( input_image ); + invert->SetMaximum( minmax->GetMaximum( ) ); + + itk::DanielssonDistanceMapImageFilter< TInputImage, TOutputImage >::Pointer dmap = + itk::DanielssonDistanceMapImageFilter< TInputImage, TOutputImage >::New( ); + dmap->SetInput( invert->GetOutput( ) ); + dmap->InputIsBinaryOn( ); + dmap->SquaredDistanceOn( ); + dmap->UseImageSpacingOn( ); + dmap->Update( ); + + typedef fpa::Base::Functors::InvertCostFunction< TOutputPixel > TFunction; + TFunction::Pointer function = TFunction::New( ); + + // Prepare region grow filter + typedef fpa::Image::Dijkstra< TOutputImage, TOutputImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( dmap->GetOutput( ) ); + filter->SetConversionFunction( function ); + filter->SetNeighborhoodOrder( neighborhood_order ); + filter->SetStopAtOneFront( stop_at_one_front ); + + // Get user-given seeds + for( unsigned int s = 0; s < rep->GetNumberOfSeeds( ); s++ ) + { + double pos[ 3 ]; + rep->GetSeedWorldPosition( s, pos ); + + TInputImage::PointType pnt; + pnt[ 0 ] = TInputImage::PointType::ValueType( pos[ 0 ] ); + pnt[ 1 ] = TInputImage::PointType::ValueType( pos[ 1 ] ); + + TInputImage::IndexType idx; + if( input_image->TransformPhysicalPointToIndex( pnt, idx ) ) + filter->AddSeed( idx, 0 ); + + } // rof + + // Prepare graphical debugger + typedef fpa::VTK::Image2DObserver< TFilter, vtkRenderWindow > TDebugger; + TDebugger::Pointer debugger = TDebugger::New( ); + debugger->SetRenderWindow( window ); + debugger->SetRenderPercentage( 0.001 ); + filter->AddObserver( itk::AnyEvent( ), debugger ); + filter->ThrowEventsOn( ); + + // Go! + filter->Update( ); + + // Save final total cost map + itk::ImageFileWriter< TOutputImage >::Pointer output_image_writer = + itk::ImageFileWriter< TOutputImage >::New( ); + output_image_writer->SetFileName( output_image_fn ); + output_image_writer->SetInput( filter->GetOutput( ) ); + try + { + output_image_writer->Update( ); + } + catch( itk::ExceptionObject& err ) + { + std::cerr + << "Error while writing image to " << output_image_fn << ": " + << err << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/example_Image_RegionGrow_AllPixels.cxx b/appli/examples/example_Image_RegionGrow_AllPixels.cxx new file mode 100644 index 0000000..fffb58a --- /dev/null +++ b/appli/examples/example_Image_RegionGrow_AllPixels.cxx @@ -0,0 +1,163 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TPixel; + +typedef itk::Image< TPixel, Dim > TImage; +typedef itk::ImageToVTKImageFilter< TImage > TVTKImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + if( argc < 4 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image neighborhood_order stop_at_one_front" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_fn = argv[ 1 ]; + unsigned int neighborhood_order = std::atoi( argv[ 2 ] ); + bool stop_at_one_front = ( std::atoi( argv[ 3 ] ) != 0 ); + + // Read image + itk::ImageFileReader< TImage >::Pointer input_image_reader = + itk::ImageFileReader< TImage >::New( ); + input_image_reader->SetFileName( input_image_fn ); + try + { + input_image_reader->Update( ); + } + catch( itk::ExceptionObject& err ) + { + std::cerr + << "Error while reading image from " << input_image_fn << ": " + << err << std::endl; + return( 1 ); + + } // yrt + TImage::ConstPointer input_image = input_image_reader->GetOutput( ); + TVTKImage::Pointer vtk_input_image = TVTKImage::New( ); + vtk_input_image->SetInput( input_image ); + vtk_input_image->Update( ); + + // VTK visualization + vtkSmartPointer< vtkImageActor > actor = + vtkSmartPointer< vtkImageActor >::New( ); + actor->SetInputData( vtk_input_image->GetOutput( ) ); + + vtkSmartPointer< vtkRenderer > renderer = + vtkSmartPointer< vtkRenderer >::New( ); + renderer->SetBackground( 0.1, 0.2, 0.7 ); + renderer->AddActor( actor ); + vtkSmartPointer< vtkRenderWindow > window = + vtkSmartPointer< vtkRenderWindow >::New( ); + window->SetSize( 800, 800 ); + window->AddRenderer( renderer ); + + // Correct camera due to the loaded image + vtkCamera* camera = renderer->GetActiveCamera( ); + camera->SetViewUp( 0, -1, 0 ); + camera->SetPosition( 0, 0, -1 ); + camera->SetFocalPoint( 0, 0, 0 ); + + // VTK interaction + vtkSmartPointer< vtkInteractorStyleImage > imageStyle = + vtkSmartPointer< vtkInteractorStyleImage >::New( ); + vtkSmartPointer< vtkRenderWindowInteractor > interactor = + vtkSmartPointer< vtkRenderWindowInteractor >::New( ); + interactor->SetInteractorStyle( imageStyle ); + window->SetInteractor( interactor ); + + // Create the widget and its representation + vtkSmartPointer< vtkPointHandleRepresentation3D > handle = + vtkSmartPointer< vtkPointHandleRepresentation3D >::New( ); + handle->GetProperty( )->SetColor( 1, 0, 0 ); + vtkSmartPointer< vtkSeedRepresentation > rep = + vtkSmartPointer< vtkSeedRepresentation >::New( ); + rep->SetHandleRepresentation( handle ); + + vtkSmartPointer< vtkSeedWidget > widget = + vtkSmartPointer< vtkSeedWidget >::New( ); + widget->SetInteractor( interactor ); + widget->SetRepresentation( rep ); + + // Let some interaction + interactor->Initialize( ); + renderer->ResetCamera( ); + window->Render( ); + widget->On( ); + interactor->Start( ); + + // Prepare region grow function + typedef fpa::Base::Functors::TautologyFunction< TImage::PixelType > TFunction; + TFunction::Pointer function = TFunction::New( ); + + // Prepare region grow filter + typedef fpa::Image::RegionGrow< TImage, TImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( input_image ); + filter->SetMembershipFunction( function ); + filter->SetNeighborhoodOrder( neighborhood_order ); + filter->SetOutsideValue( TPixel( 0 ) ); + filter->SetInsideValue( std::numeric_limits< TPixel >::max( ) ); + filter->SetStopAtOneFront( stop_at_one_front ); + + // Get user-given seeds + for( unsigned int s = 0; s < rep->GetNumberOfSeeds( ); s++ ) + { + double pos[ 3 ]; + rep->GetSeedWorldPosition( s, pos ); + + TImage::PointType pnt; + pnt[ 0 ] = TImage::PointType::ValueType( pos[ 0 ] ); + pnt[ 1 ] = TImage::PointType::ValueType( pos[ 1 ] ); + + TImage::IndexType idx; + if( input_image->TransformPhysicalPointToIndex( pnt, idx ) ) + filter->AddSeed( idx, 0 ); + + } // rof + + // Prepare graphical debugger + typedef fpa::VTK::Image2DObserver< TFilter, vtkRenderWindow > TDebugger; + TDebugger::Pointer debugger = TDebugger::New( ); + debugger->SetRenderWindow( window ); + debugger->SetRenderPercentage( 0.001 ); + filter->AddObserver( itk::AnyEvent( ), debugger ); + filter->ThrowEventsOn( ); + + // Go! + filter->Update( ); + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/example_Image_RegionGrow_AllRGBPixels.cxx b/appli/examples/example_Image_RegionGrow_AllRGBPixels.cxx new file mode 100644 index 0000000..fdb90fa --- /dev/null +++ b/appli/examples/example_Image_RegionGrow_AllRGBPixels.cxx @@ -0,0 +1,165 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TPixel; + +typedef itk::Image< itk::RGBPixel< TPixel >, Dim > TColorImage; +typedef itk::Image< TPixel, Dim > TImage; +typedef itk::ImageToVTKImageFilter< TColorImage > TVTKImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + if( argc < 4 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image neighborhood_order stop_at_one_front" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_fn = argv[ 1 ]; + unsigned int neighborhood_order = std::atoi( argv[ 2 ] ); + bool stop_at_one_front = ( std::atoi( argv[ 3 ] ) != 0 ); + + // Read image + itk::ImageFileReader< TColorImage >::Pointer input_image_reader = + itk::ImageFileReader< TColorImage >::New( ); + input_image_reader->SetFileName( input_image_fn ); + try + { + input_image_reader->Update( ); + } + catch( itk::ExceptionObject& err ) + { + std::cerr + << "Error while reading image from " << input_image_fn << ": " + << err << std::endl; + return( 1 ); + + } // yrt + TColorImage::ConstPointer input_image = input_image_reader->GetOutput( ); + TVTKImage::Pointer vtk_input_image = TVTKImage::New( ); + vtk_input_image->SetInput( input_image ); + vtk_input_image->Update( ); + + // VTK visualization + vtkSmartPointer< vtkImageActor > actor = + vtkSmartPointer< vtkImageActor >::New( ); + actor->SetInputData( vtk_input_image->GetOutput( ) ); + + vtkSmartPointer< vtkRenderer > renderer = + vtkSmartPointer< vtkRenderer >::New( ); + renderer->SetBackground( 0.1, 0.2, 0.7 ); + renderer->AddActor( actor ); + vtkSmartPointer< vtkRenderWindow > window = + vtkSmartPointer< vtkRenderWindow >::New( ); + window->SetSize( 800, 800 ); + window->AddRenderer( renderer ); + + // Correct camera due to the loaded image + vtkCamera* camera = renderer->GetActiveCamera( ); + camera->SetViewUp( 0, -1, 0 ); + camera->SetPosition( 0, 0, -1 ); + camera->SetFocalPoint( 0, 0, 0 ); + + // VTK interaction + vtkSmartPointer< vtkInteractorStyleImage > imageStyle = + vtkSmartPointer< vtkInteractorStyleImage >::New( ); + vtkSmartPointer< vtkRenderWindowInteractor > interactor = + vtkSmartPointer< vtkRenderWindowInteractor >::New( ); + interactor->SetInteractorStyle( imageStyle ); + window->SetInteractor( interactor ); + + // Create the widget and its representation + vtkSmartPointer< vtkPointHandleRepresentation3D > handle = + vtkSmartPointer< vtkPointHandleRepresentation3D >::New( ); + handle->GetProperty( )->SetColor( 1, 0, 0 ); + vtkSmartPointer< vtkSeedRepresentation > rep = + vtkSmartPointer< vtkSeedRepresentation >::New( ); + rep->SetHandleRepresentation( handle ); + + vtkSmartPointer< vtkSeedWidget > widget = + vtkSmartPointer< vtkSeedWidget >::New( ); + widget->SetInteractor( interactor ); + widget->SetRepresentation( rep ); + + // Let some interaction + interactor->Initialize( ); + renderer->ResetCamera( ); + window->Render( ); + widget->On( ); + interactor->Start( ); + + // Prepare region grow function + typedef fpa::Base::Functors::TautologyFunction< TColorImage::PixelType > TFunction; + TFunction::Pointer function = TFunction::New( ); + + // Prepare region grow filter + typedef fpa::Image::RegionGrow< TColorImage, TImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( input_image ); + filter->SetMembershipFunction( function ); + filter->SetNeighborhoodOrder( neighborhood_order ); + filter->SetOutsideValue( TPixel( 0 ) ); + filter->SetInsideValue( std::numeric_limits< TPixel >::max( ) ); + filter->SetStopAtOneFront( stop_at_one_front ); + + // Get user-given seeds + for( unsigned int s = 0; s < rep->GetNumberOfSeeds( ); s++ ) + { + double pos[ 3 ]; + rep->GetSeedWorldPosition( s, pos ); + + TImage::PointType pnt; + pnt[ 0 ] = TImage::PointType::ValueType( pos[ 0 ] ); + pnt[ 1 ] = TImage::PointType::ValueType( pos[ 1 ] ); + + TImage::IndexType idx; + if( input_image->TransformPhysicalPointToIndex( pnt, idx ) ) + filter->AddSeed( idx, 0 ); + + } // rof + + // Prepare graphical debugger + typedef fpa::VTK::Image2DObserver< TFilter, vtkRenderWindow > TDebugger; + TDebugger::Pointer debugger = TDebugger::New( ); + debugger->SetRenderWindow( window ); + debugger->SetRenderPercentage( 0.001 ); + filter->AddObserver( itk::AnyEvent( ), debugger ); + filter->ThrowEventsOn( ); + + // Go! + filter->Update( ); + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/doc/UML/fpa.dia b/doc/UML/fpa.dia new file mode 100644 index 0000000000000000000000000000000000000000..8ed637d5d84ae80a5ad9bf0ad473ccfdc1189409 GIT binary patch literal 4287 zcmZ{lWl$6h*M^lP7Nxscx#nUY$^!uMTaY;bo^V^@;oj) z#g6${ppV`psd%Jkb}p{pj|?$IJiBL?CluD9A(9017ViB_zx=sp+oiWU4?qFpgG@cl z558H>(h9DeshS=O1ax;dEO&noMKvC$Jw1Da%+SyZ>3`bSUAJsMQAN48mztUimLdc? zbs;5%xjyba5HGOpF~fsyk857IJqP4_k#tdZYl))^?~`V-)z~jTuW>}*rcXK+t=W_( z%;4va{+S1O*Du${!)rnroZfb2Po{jYa!|gNWkc_q2MpA#@MWMfZ}OLPD|x+?No0%J z!R1KOdn*mnswc|KZ!UkMq>fRg>Swf*K^{EL+`wX@aAcqc9bELJl!sW1wVVwm`E zliTJ-gkioPsRS;Gw#Zzj44Oj)Jn5^k^d$@|J$-(P7HdSS?0*pR*(WJ2D~^@pH?bDd zxzm2msw5DvZY{ZwpL@ziuISN}Ajr(FG4JkD9aC*6#Z%91W`B@0Bu%fK#pXe-B{~x6 z;aurAh)l^n{dMM0mvlaTyOVCclCZud^G+b z`qa2uFj~JV?qQr?Qy#OMPpctBgz?j@e48-HVAME7u_DplLqNBw`2%&0odKAw+BhK# zo>46&1#VJsw~z_-4Trf!`-MXf=>zaziuv(TQ--=Ygt;4elzLh7!bh>-oxA;jp ztU2=tkjZWRLtF$q^ftL7PupaLH6O)KSBMIp@j6PuU6nL-2O<3l z$kuJikS_d`ca0j-TDGWrviK#T+tK|k&MfhucC^bB zMP^|ySwh3=)GxbyYw`@rn3cpM-=VW^3c~8?gY$PL>~J9;@z${YV5{Q`MGNYI70RZG+^~9`&d4 zEmzot5=I(xuq{1isC)t)arhq`jK`4?^75daJt3Q1%DXHtj3 zHl3PL!3ZFDkRzN~hs8@SfpDZ{1+L--pL z*3SeZQF-z^>VwoT1ehjLtP0lNAE}&kBxifqlS(`3yZ%jUIKkG@)Zo$#9R>|P%`r&o z6U>-8&Ypv*;ibG6W|LnwZvp#SC z5Gx;@tvHPAiNC_3i7ck(H7rnJCb(YbrBaHGko~AAcs4XZOL{s}6eysL*hl!sA5%kv zb3;#~l|7aDLV-?1Kp-*($jWwc9Q|Iml7F)%3wD6{`YYk`(vhgceM~v$y&)ai?~O4j zDsIa;7GM5Y$2XdN#IJb{qR8vM>=fpI=Pj&JLFFzs?v{?qH^sW z(HCA3bLS3=l+d}ZtQ9E<1LQ2}&Z5Hr*IQ|ZNjviDGMUEL5KnF zRwF4&V=VC~~7fx?`^GfyX zW%D2|a_G=YD!w8D_EGS%b#NA7h05nJNm;G5yA!>%J)f?R=~&}n3!v2<9vpm*>-_pl zdDr-Svsf%!vSxGZQr%IOm^P6jhDe+mKp#>^qkv4A^gl1Mwl%BjqjWIpv$(!V+ z)iS-x@db88CZ%V(!O_n&hz`KIO}cG=wqG2yrKkn-qf|AxLo3}IX|OrU(y3N;WYRu8 zp&t6kGF*ttv3l&@W3|gsCAu|^wS0)BED=+(-M$3u|7qgy|GQAk5=Q_G>15J654*B) zQ)f?+>UP!3{Sn1QJ>}1{@is^Gm23JSe*SfeKFOYmyJ8-R*}N(-!b*6d>$qd0^-O~>r%CBJh6%TJc}4$&BPAOsYCXHcOcp{o8~SmTI_=YIZrPIQ!G>naDvOnY zBoip-FxZ%TaOCGOSrPs4GDx(xNVZ)L+0@%Ew}?u~sr}`4yr%T##AoghZmMg%bd5R^u)3*4a5%9YRU0qD;Nxr0s`lpooz+J6Yk6%jeqU7RXr%HZ6Bx9w~-=j?0~xc9$? zRnmarb{_>)((zan;V3PY4C6C3s-PO*Gy!<6I>qKnN*d$N0rJ9Iz_q+jCkLW^sBUd8 zCT!>$S52mA!KG?xrn4($+4rgfR$*NQobEPl)pi)ln{>o?jT1i~`_eEaJo-pxT;b@+ zbaVWadn^<7*aaqE3{D>@-}$A6o3^wRK~H}kNc`;fdZxzTr`+SZjxOBP=E1X6js1zS z%vGsHR_b$eA?@)bMP}}}IS@y@dV;)R2L>F@7mH$^sr)?za?T!6NT59Ri zx$C@6a8hKbeiFsc(6=QT#oy&THMo|7>;AjPkx*H?-@k$W8KnXUL_`DxmS2X==rsy1 zZygIJDQ@67dwrHB(Uru*cQ*v&Z@e>48}=76j}f}2(S_+{shu3u(g$L~ExoTu;g;Sv z7cjl>`vXj3!otsMjZ0rn`%ZdKdQaw@(7+>xBZLC>z)_h~sS`sB^R0Z;`Vp}TnbiN4 z1*L_v&C;8MaqfRbAyJ>aq(Plb+f&%_$_~T3gZQr`bT<&WgEF3vzfpgqZoYqcXsduN zaeU}{>RQJjj(H(9b_y!^|6jhDy^UKPWqYAae@Lm5V)BlyeceSAw^cWm1U4b&EY&QP zJ0enGEtK_MhT_ETd?T`_&)VP~*anz=eDKImo_`zc|7j=3aI}@q?+p3S)0CZOkP$xS z#y8`sH^aT|xRhnw#8XV2UG555MkZ%lYcwdbDhYK!-c{#;Ntp8?tO29UdmS>h*_yj; zGCHCaDRp9j_K>ci)M)dEWS8Q7^~(mdZ16yqOREsRY31gKh*e%3&y3e=nmXo14nHfG^0ykw1uF5CGa^OcW*D?sJyQi;9k-9g4?}9 zGOE_NMQ-=SXY?#7_mtngHD~XhjET?pD$V-#D$N`=Bcsf}8W@DqtQu87z-+Xt?;Rj< ze$_l+1UYO|wQ4%}vof05Txs4v2FYbAP@EcUV4vmMcUd0C?2_$yq)8*1!vv{OpVqwH z>T4HTU;4_!HE4E3;=RAlW5q7CJ?7MiT`gyGRs6j9ynB@qPB&1e;}g6{V@ma^M_TWf z($7@AZ?GAT+Gl4+fe!$usN-4x!+*fjcmD@G%YVVkEUu87Nh@`M#ug`!1lyQs2#;a4 zeex*_wjm!*qg1bCtI3HnY4;i9RvVwJ*2ygrVYZ$b8K0EMh$<$`kVe~K_@7;Lbe>of znC`D1#n(ZUbTjZyqY@-78{iyKIbq|LCKiq5|bUyj&-NF6Z-P%a76InH_ z+0 znxWBw|8wD-7P)Z4z}wAZxu7@UXtvI~#BOV$s{0kwM7e?Pbg0)G+dIZo+>22+42(zr E0q!qiOaK4? literal 0 HcmV?d00001 diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ebff103..28c4df3 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -57,11 +57,19 @@ GENERATE_EXPORT_HEADER( EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/lib/fpa/${LIB_NAME}_Export.h STATIC_DEFINE ${LIB_NAME}_BUILT_AS_STATIC ) -TARGET_LINK_LIBRARIES( - ${LIB_NAME} - ${${LIB_NAME}_LINK_LIBRARIES} - ${ITK_LIBRARIES} - vtkInteractionWidgets - ) +IF(USE_VTK) + TARGET_LINK_LIBRARIES( + ${LIB_NAME} + ${${LIB_NAME}_LINK_LIBRARIES} + ${ITK_LIBRARIES} + vtkInteractionWidgets + ) +ELSE(USE_VTK) + TARGET_LINK_LIBRARIES( + ${LIB_NAME} + ${${LIB_NAME}_LINK_LIBRARIES} + ${ITK_LIBRARIES} + ) +ENDIF(USE_VTK) ## eof - $RCSfile$ diff --git a/lib/fpa/Base/Algorithm.h b/lib/fpa/Base/Algorithm.h index c9b2e1a..35c6a37 100644 --- a/lib/fpa/Base/Algorithm.h +++ b/lib/fpa/Base/Algorithm.h @@ -1,9 +1,8 @@ #ifndef __FPA__BASE__ALGORITHM__H__ #define __FPA__BASE__ALGORITHM__H__ -#include -#include #include +#include #include namespace fpa @@ -16,67 +15,85 @@ namespace fpa * vertex could be marked as "visited", "in the front", "not yet there" * or "freezed". * - * @param T Traits used for this algorithm + * @param V Vertex type. + * @param C Vertex value type. + * @param R Result value type. + * @param B Base class for this algorithm. It should be any itk-based + * filter (itk::ProcessObject). + * */ - template< class T, class B > + template< class V, class C, class R, class B > class Algorithm : public B { public: - // Standard class typdedefs typedef Algorithm Self; typedef B Superclass; typedef itk::SmartPointer< Self > Pointer; typedef itk::SmartPointer< const Self > ConstPointer; - /// Templated types - typedef T TTraits; - typedef B TBaseFilter; - typedef typename T::TCost TCost; - typedef typename T::TResult TResult; - typedef typename T::TVertex TVertex; - typedef typename T::TVertexValue TVertexValue; - - protected: - typedef typename T::TFrontId _TFrontId; - typedef typename T::TNode _TNode; - typedef typename T::TNodes _TNodes; - typedef typename T::TVertexCmp _TVertexCmp; - - typedef std::map< TVertex, _TNode, _TVertexCmp > _TMarks; + typedef V TVertex; + typedef C TValue; + typedef R TResult; - typedef std::pair< TVertex, bool > _TCollision; - typedef std::vector< _TCollision > _TCollisionSitesRow; - typedef std::vector< _TCollisionSitesRow > _TCollisionSites; + fpa_Base_NewEvent( TStartEvent ); + fpa_Base_NewEvent( TStartLoopEvent ); + fpa_Base_NewEvent( TEndEvent ); + fpa_Base_NewEvent( TEndLoopEvent ); + fpa_Base_NewEventWithVertex( TAliveEvent, TVertex ); + fpa_Base_NewEventWithVertex( TFrontEvent, TVertex ); + fpa_Base_NewEventWithVertex( TFreezeEvent, TVertex ); - public: - typedef BaseEvent< _TNode > TEvent; - typedef FrontEvent< _TNode > TFrontEvent; - typedef MarkEvent< _TNode > TMarkEvent; - typedef CollisionEvent< _TNode > TCollisionEvent; - typedef EndEvent< _TNode > TEndEvent; - typedef BacktrackingEvent< TVertex > TBacktrackingEvent; - typedef EndBacktrackingEvent< TVertex > TEndBacktrackingEvent; + protected: + typedef std::vector< TVertex > _TVertices; + typedef std::pair< TVertex, bool > _TCollision; + typedef std::vector< _TCollision > _TCollisionsRow; + typedef std::vector< _TCollisionsRow > _TCollisions; + + /** + */ + enum _TNodeLabel + { + FarLabel = 0, + FrontLabel, + AliveLabel + }; + + /** + */ + class _TNode + { + public: + _TNode( ); + virtual ~_TNode( ); + + public: + TVertex Vertex; + TVertex Parent; + TResult Result; + long FrontId; + _TNodeLabel Label; + }; + typedef std::vector< _TNode > _TNodes; public: - itkTypeMacro( Algorithm, itkProcessObject ); + itkTypeMacro( Algorithm, B ); - itkBooleanMacro( StopAtOneFront ); itkBooleanMacro( ThrowEvents ); + itkBooleanMacro( StopAtOneFront ); - itkGetConstMacro( StopAtOneFront, bool ); itkGetConstMacro( ThrowEvents, bool ); + itkGetConstMacro( StopAtOneFront, bool ); - itkSetMacro( StopAtOneFront, bool ); itkSetMacro( ThrowEvents, bool ); + itkSetMacro( StopAtOneFront, bool ); public: virtual void InvokeEvent( const itk::EventObject& e ); virtual void InvokeEvent( const itk::EventObject& e ) const; - /// Seeds manipulation - void AddSeed( const TVertex& s, const TResult& v ); - const TVertex& GetSeed( const unsigned long& i ) const; + void AddSeed( const TVertex& s, const TResult& r ); + const TVertex& GetSeed( const unsigned int& id ) const; void ClearSeeds( ); unsigned long GetNumberOfSeeds( ) const; @@ -84,66 +101,63 @@ namespace fpa Algorithm( ); virtual ~Algorithm( ); - /// itk::ProcessObject + // Connection with itk's pipeline virtual void GenerateData( ); - /// Base interface - virtual void _BeforeMainLoop ( ); - virtual void _AfterMainLoop ( ); - virtual void _BeforeLoop ( ); - virtual void _AfterLoop ( ); - virtual void _Loop ( ); - virtual bool _CheckCollisions ( const _TNode& a, const _TNode& b ); - virtual bool _CheckStopCondition ( ); - virtual bool _UpdateResult ( _TNode& n ); - - /// Marks management - virtual void _InitializeMarks ( ); - virtual bool _IsMarked ( const TVertex& v ) const; - virtual _TFrontId _FrontId ( const TVertex& v ) const; - virtual TVertex _Parent ( const TVertex& v ) const; - virtual void _Mark ( const _TNode& n ); - - /// Pure virtual interface: vertices - virtual unsigned long _NumberOfVertices ( ) const = 0; - virtual TVertexValue _Value ( const TVertex& v ) const = 0; - virtual TResult _Result ( const TVertex& v ) const = 0; - - /// Pure virtual interface: edges - virtual double _Norm ( const TVertex& a, const TVertex& b ) const = 0; - virtual bool _Edge ( const TVertex& a, const TVertex& b ) const = 0; - virtual TCost _Cost ( const TVertex& a, const TVertex& b ) const = 0; - - /// Pure virtual interface: neighborhood - virtual void _Neighs ( const _TNode& n, _TNodes& N ) const = 0; - virtual bool _UpdateNeigh ( _TNode& nn, const _TNode& n ) = 0; - virtual void _NeighsInDim ( const _TNode& n, - const unsigned int& d, - _TNodes& N ) = 0; - - /// Pure virtual interface: queue - virtual void _InitializeQueue ( ) = 0; - virtual bool _IsQueueEmpty ( ) const = 0; - virtual void _QueuePush ( const _TNode& n ) = 0; - virtual _TNode _QueuePop ( ) = 0; - virtual void _QueueClear ( ) = 0; - - /// Pure virtual interface: results - virtual void _InitializeResults ( ) = 0; + // Main loop algorithm + virtual void _Loop( ); + + // Supporting methods for loop + virtual void _BeforeGenerateData( ); + virtual void _AfterGenerateData( ); + virtual void _BeforeLoop( ); + virtual void _AfterLoop( ); + + // Methods to control forced stops + virtual bool _UpdateCollisions( const TVertex& a, const TVertex& b ); + virtual bool _NeedToStop( ) const; + + // Graph-related abstract methods + virtual unsigned long _NumberOfVertices( ) const = 0; + virtual const TValue& _VertexValue( const TVertex& v ) const = 0; + virtual double _Distance( + const TVertex& a, const TVertex& b + ) const = 0; + virtual bool _HasEdge( const TVertex& a, const TVertex& b ) const = 0; + virtual void _Neighborhood( + _TVertices& neighborhood, const TVertex& v + ) const = 0; + + // Results-related abstract methods + virtual bool _ComputeNeighborResult( + TResult& result, const TVertex& neighbor, const TVertex& parent + ) const = 0; + virtual void _InitResults( ) = 0; + virtual const TResult& _Result( const TVertex& v ) const = 0; + virtual void _SetResult( const TVertex& v, const TResult& r ) = 0; + + // Marks-related abstract methods + virtual const _TNode& _Node( const TVertex& v ) const = 0; + virtual void _InitMarks( ) = 0; + virtual void _Mark( const _TNode& node ) = 0; + + // Queue-related abstract methods + virtual void _InitQueue( ); + virtual bool _IsQueueEmpty( ) const = 0; + virtual void _QueuePush( const _TNode& n ) = 0; + virtual _TNode _QueuePop( ) = 0; + virtual void _QueueClear( ) = 0; private: // Purposely not implemented - Algorithm( const Self& ); - void operator=( const Self& ); + Algorithm( const Self& other ); + Self& operator=( const Self& other ); protected: - bool m_StopAtOneFront; - bool m_ThrowEvents; - - _TNodes m_Seeds; - _TMarks m_Marks; - - _TCollisionSites m_CollisionSites; + bool m_ThrowEvents; + bool m_StopAtOneFront; + _TNodes m_Seeds; + _TCollisions m_Collisions; }; } // ecapseman diff --git a/lib/fpa/Base/Algorithm.hxx b/lib/fpa/Base/Algorithm.hxx index a58f2a6..21670ef 100644 --- a/lib/fpa/Base/Algorithm.hxx +++ b/lib/fpa/Base/Algorithm.hxx @@ -1,13 +1,28 @@ #ifndef __FPA__BASE__ALGORITHM__HXX__ #define __FPA__BASE__ALGORITHM__HXX__ -#include -#include #include // ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: +template< class V, class C, class R, class B > +fpa::Base::Algorithm< V, C, R, B >::_TNode:: +_TNode( ) + : Result( TResult( 0 ) ), + FrontId( -1 ), + Label( Self::FarLabel ) +{ +} + +// ------------------------------------------------------------------------- +template< class V, class C, class R, class B > +fpa::Base::Algorithm< V, C, R, B >::_TNode:: +~_TNode( ) +{ +} + +// ------------------------------------------------------------------------- +template< class V, class C, class R, class B > +void fpa::Base::Algorithm< V, C, R, B >:: InvokeEvent( const itk::EventObject& e ) { if( this->m_ThrowEvents ) @@ -15,8 +30,8 @@ InvokeEvent( const itk::EventObject& e ) } // ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: +template< class V, class C, class R, class B > +void fpa::Base::Algorithm< V, C, R, B >:: InvokeEvent( const itk::EventObject& e ) const { if( this->m_ThrowEvents ) @@ -24,26 +39,32 @@ InvokeEvent( const itk::EventObject& e ) const } // ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: -AddSeed( const TVertex& s, const TResult& v ) +template< class V, class C, class R, class B > +void fpa::Base::Algorithm< V, C, R, B >:: +AddSeed( const TVertex& s, const TResult& r ) { - this->m_Seeds.push_back( _TNode( s, v, this->m_Seeds.size( ) ) ); + _TNode ns; + ns.Vertex = s; + ns.Parent = s; + ns.Result = r; + ns.FrontId = this->m_Seeds.size( ); + ns.Label = Self::FrontLabel; + this->m_Seeds.push_back( ns ); this->Modified( ); } // ------------------------------------------------------------------------- -template< class T, class B > -const typename fpa::Base::Algorithm< T, B >:: -TVertex& fpa::Base::Algorithm< T, B >:: -GetSeed( const unsigned long& i ) const +template< class V, class C, class R, class B > +const typename fpa::Base::Algorithm< V, C, R, B >:: +TVertex& fpa::Base::Algorithm< V, C, R, B >:: +GetSeed( const unsigned int& id ) const { - return( this->m_Seeds[ i ].Vertex ); + return( this->m_Seeds[ id ].Vertex ); } // ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: +template< class V, class C, class R, class B > +void fpa::Base::Algorithm< V, C, R, B >:: ClearSeeds( ) { this->m_Seeds.clear( ); @@ -51,170 +72,184 @@ ClearSeeds( ) } // ------------------------------------------------------------------------- -template< class T, class B > -unsigned long fpa::Base::Algorithm< T, B >:: +template< class V, class C, class R, class B > +unsigned long fpa::Base::Algorithm< V, C, R, B >:: GetNumberOfSeeds( ) const { return( this->m_Seeds.size( ) ); } // ------------------------------------------------------------------------- -template< class T, class B > -fpa::Base::Algorithm< T, B >:: +template< class V, class C, class R, class B > +fpa::Base::Algorithm< V, C, R, B >:: Algorithm( ) : Superclass( ), - m_StopAtOneFront( false ), - m_ThrowEvents( false ) + m_ThrowEvents( false ), + m_StopAtOneFront( false ) { } // ------------------------------------------------------------------------- -template< class T, class B > -fpa::Base::Algorithm< T, B >:: +template< class V, class C, class R, class B > +fpa::Base::Algorithm< V, C, R, B >:: ~Algorithm( ) { } // ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: +template< class V, class C, class R, class B > +void fpa::Base::Algorithm< V, C, R, B >:: GenerateData( ) { - this->AllocateOutputs( ); - unsigned long N = this->m_Seeds.size( ); if( N == 0 ) return; - this->m_CollisionSites.clear( ); - this->m_CollisionSites. - resize( N, _TCollisionSitesRow( N, _TCollision( TVertex( ), false ) ) ); - - this->_BeforeMainLoop( ); - this->_InitializeMarks( ); - this->_InitializeResults( ); - this->_InitializeQueue( ); - this->_Loop( ); - this->_AfterMainLoop( ); - this->InvokeEvent( TEndEvent( ) ); -} - -// ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: -_BeforeMainLoop( ) -{ -} -// ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: -_AfterMainLoop( ) -{ -} + this->InvokeEvent( TStartEvent( ) ); + this->_BeforeGenerateData( ); -// ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: -_BeforeLoop( ) -{ -} - -// ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: -_AfterLoop( ) -{ + this->m_Collisions.clear( ); + this->m_Collisions. + resize( N, _TCollisionsRow( N, _TCollision( TVertex( ), false ) ) ); + this->_InitResults( ); + this->_InitMarks( ); + this->_InitQueue( ); + this->_Loop( ); + this->_AfterGenerateData( ); + this->InvokeEvent( TEndEvent( ) ); } // ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: +template< class V, class C, class R, class B > +void fpa::Base::Algorithm< V, C, R, B >:: _Loop( ) { + this->InvokeEvent( TStartLoopEvent( ) ); this->_BeforeLoop( ); while( !( this->_IsQueueEmpty( ) ) ) { - _TNode n = this->_QueuePop( ); - if( this->_IsMarked( n.Vertex ) ) + // Get next candidate + _TNode candidate = this->_QueuePop( ); + if( this->_Node( candidate.Vertex ).Label == Self::AliveLabel ) continue; - this->_Mark( n ); - this->InvokeEvent( TMarkEvent( n ) ); - if( this->_UpdateResult( n ) ) + // Mark it as "Alive" and update final result + candidate.Label = Self::AliveLabel; + this->_Mark( candidate ); + this->_SetResult( candidate.Vertex, candidate.Result ); + this->InvokeEvent( TAliveEvent( candidate.Vertex, candidate.FrontId ) ); + + // Check if a forced stop condition arises + if( !( this->_NeedToStop( ) ) ) { - if( !( this->_CheckStopCondition( ) ) ) + // Compute neighborhood + _TVertices neighborhood; + this->_Neighborhood( neighborhood, candidate.Vertex ); + + // Iterate over neighbors + typename _TVertices::iterator nIt = neighborhood.begin( ); + for( ; nIt != neighborhood.end( ); ++nIt ) { - _TNodes N; - this->_Neighs( n, N ); - typename _TNodes::iterator nnIt = N.begin( ); - while( nnIt != N.end( ) ) + _TNode neighbor = this->_Node( *nIt ); + neighbor.Vertex = *nIt; + if( neighbor.Label == Self::AliveLabel ) { - if( this->_IsMarked( nnIt->Vertex ) ) + // Update collisions + if( this->_UpdateCollisions( candidate.Vertex, *nIt ) ) { - // Update real front identifier - nnIt->FrontId = this->_FrontId( nnIt->Vertex ); + this->_QueueClear( ); + nIt = neighborhood.end( ); - // Update collisions - if( this->_CheckCollisions( n, *nnIt ) ) - { - if( this->m_StopAtOneFront ) - { - this->_QueueClear( ); - nnIt = N.end( ); - - } // fi - - } // fi + } // fi + } + else + { + // Add new candidate to queue + if( + this->_ComputeNeighborResult( + neighbor.Result, *nIt, candidate.Vertex + ) + ) + { + neighbor.FrontId = candidate.FrontId; + neighbor.Parent = candidate.Vertex; + neighbor.Label = Self::FrontLabel; + this->_QueuePush( neighbor ); + this->_Mark( neighbor ); + this->InvokeEvent( TFrontEvent( *nIt, candidate.FrontId ) ); } else - { - if( this->_UpdateNeigh( *nnIt, n ) ) - { - nnIt->Parent = n.Vertex; - this->_QueuePush( *nnIt ); - this->InvokeEvent( TFrontEvent( *nnIt ) ); + this->InvokeEvent( TFreezeEvent( *nIt, candidate.FrontId ) ); - } // fi + } // fi - } // fi - if( nnIt != N.end( ) ) - nnIt++; - - } // elihw - } - else - this->_QueueClear( ); - - } // fi + } // rof + } + else + this->_QueueClear( ); } // elihw this->_AfterLoop( ); + this->InvokeEvent( TEndLoopEvent( ) ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class R, class B > +void fpa::Base::Algorithm< V, C, R, B >:: +_BeforeGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class V, class C, class R, class B > +void fpa::Base::Algorithm< V, C, R, B >:: +_AfterGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class V, class C, class R, class B > +void fpa::Base::Algorithm< V, C, R, B >:: +_BeforeLoop( ) +{ +} + +// ------------------------------------------------------------------------- +template< class V, class C, class R, class B > +void fpa::Base::Algorithm< V, C, R, B >:: +_AfterLoop( ) +{ } // ------------------------------------------------------------------------- -template< class T, class B > -bool fpa::Base::Algorithm< T, B >:: -_CheckCollisions( const _TNode& a, const _TNode& b ) +template< class V, class C, class R, class B > +bool fpa::Base::Algorithm< V, C, R, B >:: +_UpdateCollisions( const TVertex& a, const TVertex& b ) { bool ret = false; - if( a.FrontId != b.FrontId ) + _TNode na = this->_Node( a ); + _TNode nb = this->_Node( b ); + long fa = na.FrontId; + long fb = na.FrontId; + + if( fa != fb ) { // Mark collision, if it is new - bool exists = this->m_CollisionSites[ a.FrontId ][ b.FrontId ].second; - exists &= this->m_CollisionSites[ b.FrontId ][ a.FrontId ].second; + bool exists = this->m_Collisions[ fa ][ fb ].second; + exists &= this->m_Collisions[ fb ][ fa ].second; if( !exists ) { - this->m_CollisionSites[ a.FrontId ][ b.FrontId ].first = a.Vertex; - this->m_CollisionSites[ a.FrontId ][ b.FrontId ].second = true; - this->m_CollisionSites[ b.FrontId ][ a.FrontId ].first = b.Vertex; - this->m_CollisionSites[ b.FrontId ][ a.FrontId ].second = true; + this->m_Collisions[ fa ][ fb ].first = na.Vertex; + this->m_Collisions[ fa ][ fb ].second = true; + this->m_Collisions[ fb ][ fa ].first = nb.Vertex; + this->m_Collisions[ fb ][ fa ].second = true; // Stop if one front is desired if( this->m_StopAtOneFront ) { // Perform a depth-first iteration on front graph unsigned long N = this->GetNumberOfSeeds( ); - unsigned long C = 0; + unsigned long count = 0; std::vector< bool > m( N, false ); std::queue< unsigned long > q; q.push( 0 ); @@ -226,14 +261,14 @@ _CheckCollisions( const _TNode& a, const _TNode& b ) if( m[ f ] ) continue; m[ f ] = true; - C++; + count++; for( unsigned int n = 0; n < N; ++n ) - if( this->m_CollisionSites[ f ][ n ].second && !m[ n ] ) + if( this->m_Collisions[ f ][ n ].second && !m[ n ] ) q.push( n ); } // elihw - ret = ( C == N ); + ret = ( count == N ); } // fi @@ -244,69 +279,29 @@ _CheckCollisions( const _TNode& a, const _TNode& b ) } // ------------------------------------------------------------------------- -template< class T, class B > -bool fpa::Base::Algorithm< T, B >:: -_CheckStopCondition( ) +template< class V, class C, class R, class B > +bool fpa::Base::Algorithm< V, C, R, B >:: +_NeedToStop( ) const { return( false ); } // ------------------------------------------------------------------------- -template< class T, class B > -bool fpa::Base::Algorithm< T, B >:: -_UpdateResult( _TNode& n ) +template< class V, class C, class R, class B > +void fpa::Base::Algorithm< V, C, R, B >:: +_InitQueue( ) { - return( true ); -} - -// ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: -_InitializeMarks( ) -{ - this->m_Marks.clear( ); -} - -// ------------------------------------------------------------------------- -template< class T, class B > -bool fpa::Base::Algorithm< T, B >:: -_IsMarked( const TVertex& v ) const -{ - return( this->m_Marks.find( v ) != this->m_Marks.end( ) ); -} - -// ------------------------------------------------------------------------- -template< class T, class B > -typename fpa::Base::Algorithm< T, B >:: -_TFrontId fpa::Base::Algorithm< T, B >:: -_FrontId( const TVertex& v ) const -{ - typename _TMarks::const_iterator mIt = this->m_Marks.find( v ); - if( mIt != this->m_Marks.end( ) ) - return( mIt->second.FrontId ); - else - return( std::numeric_limits< _TFrontId >::max( ) ); -} - -// ------------------------------------------------------------------------- -template< class T, class B > -typename fpa::Base::Algorithm< T, B >:: -TVertex fpa::Base::Algorithm< T, B >:: -_Parent( const TVertex& v ) const -{ - typename _TMarks::const_iterator mIt = this->m_Marks.find( v ); - if( mIt == this->m_Marks.end( ) ) - return( TVertex( ) ); - else - return( mIt->second.Parent ); -} + this->_QueueClear( ); + for( + typename _TNodes::const_iterator sIt = this->m_Seeds.begin( ); + sIt != this->m_Seeds.end( ); + sIt++ + ) + { + this->_QueuePush( *sIt ); + this->_Mark( *sIt ); -// ------------------------------------------------------------------------- -template< class T, class B > -void fpa::Base::Algorithm< T, B >:: -_Mark( const _TNode& n ) -{ - this->m_Marks[ n.Vertex ] = n; + } // rof } #endif // __FPA__BASE__ALGORITHM__HXX__ diff --git a/lib/fpa/Base/Dijkstra.h b/lib/fpa/Base/Dijkstra.h index a6212cf..3831526 100644 --- a/lib/fpa/Base/Dijkstra.h +++ b/lib/fpa/Base/Dijkstra.h @@ -8,105 +8,74 @@ namespace fpa { namespace Base { - /** - */ - template< class V, class C, class VV, class VC > - class DijkstraTraits - { - public: - typedef V TVertex; - typedef C TResult; - typedef C TCost; - typedef VV TVertexValue; - typedef VC TVertexCmp; - typedef long TFrontId; - - class TNode - { - public: - TNode( ) - : Cost( 0 ) - { } - TNode( const TVertex& v, const TFrontId& f ) - : Vertex( v ), - Parent( v ), - Result( TResult( 0 ) ), - FrontId( f ), - Cost( TCost( 0 ) ) - { } - TNode( const TVertex& v, const TResult& r, const TFrontId& f ) - : Vertex( v ), - Parent( v ), - Result( r ), - FrontId( f ), - Cost( TCost( 0 ) ) - { } - virtual ~TNode( ) - { } - - // NOTE: stl::heaps work as maximum priority queues - bool operator<( const TNode& other ) const - { return( other.Cost < this->Cost ); } - - TVertex Vertex; - TVertex Parent; - TResult Result; - TFrontId FrontId; - TCost Cost; - }; - - typedef std::vector< TNode > TNodes; - }; - /** * Dijkstra is a front propagation algorithm that minimizes costs + * + * @param V Vertex type. + * @param C Vertex value type. + * @param R Result value type. + * @param B Base class for this algorithm. It should be any itk-based + * filter (itk::ProcessObject). + * */ - template< class V, class C, class VV, class VC, class B > + template< class V, class C, class R, class B > class Dijkstra - : public Algorithm< DijkstraTraits< V, C, VV, VC >, B > + : public Algorithm< V, C, R, B > { public: - // Templated types - typedef V TVertex; - typedef C TCost; - typedef VV TVertexValue; - typedef B TBaseFilter; - typedef DijkstraTraits< V, C, VV, VC > TTraits; - - // Standard class typdedefs - typedef Dijkstra Self; - typedef Algorithm< TTraits, B > Superclass; - typedef itk::SmartPointer< Self > Pointer; - typedef itk::SmartPointer< const Self > ConstPointer; + typedef Dijkstra Self; + typedef Algorithm< V, C, R, B > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TVertex TVertex; + typedef typename Superclass::TValue TValue; + typedef typename Superclass::TResult TResult; protected: - typedef typename TTraits::TFrontId _TFrontId; - typedef typename TTraits::TNode _TNode; - typedef typename TTraits::TNodes _TNodes; + typedef typename Superclass::_TVertices _TVertices; + typedef typename Superclass::_TCollision _TCollision; + typedef typename Superclass::_TCollisionsRow _TCollisionsRow; + typedef typename Superclass::_TCollisions _TCollisions; + typedef typename Superclass::_TNode _TNode; + typedef typename Superclass::_TNodes _TNodes; typedef std::vector< _TNode > _TQueue; + struct _TNodeCompare + { + // Make the min-heap behave as a max-heap + bool operator()( const _TNode& a, const _TNode& b ) const + { return( b.Result < a.Result ); } + }; public: - itkTypeMacro( Dijkstra, Base ); + itkTypeMacro( Dijkstra, Algorithm ); protected: Dijkstra( ); virtual ~Dijkstra( ); - virtual void _InitializeQueue ( ); - virtual bool _IsQueueEmpty ( ) const; - virtual void _QueuePush ( const _TNode& n ); - virtual _TNode _QueuePop ( ); - virtual void _QueueClear ( ); - virtual bool _UpdateNeigh ( _TNode& nn, const _TNode& n ); + virtual TResult _Cost( const TVertex& v, const TVertex& p ) const = 0; + + // Results-related abstract methods + virtual bool _ComputeNeighborResult( + TResult& result, const TVertex& neighbor, const TVertex& parent + ) const; + + // Queue-related abstract methods + virtual bool _IsQueueEmpty( ) const; + virtual void _QueuePush( const _TNode& n ); + virtual _TNode _QueuePop( ); + virtual void _QueueClear( ); private: // Purposely not implemented - Dijkstra( const Self& ); - void operator=( const Self& ); + Dijkstra( const Self& other ); + Self& operator=( const Self& other ); - private: + protected: _TQueue m_Queue; + static _TNodeCompare m_NodeCompare; }; } // ecapseman diff --git a/lib/fpa/Base/Dijkstra.hxx b/lib/fpa/Base/Dijkstra.hxx index 4920ab5..7d65237 100644 --- a/lib/fpa/Base/Dijkstra.hxx +++ b/lib/fpa/Base/Dijkstra.hxx @@ -4,92 +4,78 @@ #include // ------------------------------------------------------------------------- -template< class V, class C, class VV, class VC, class B > -fpa::Base::Dijkstra< V, C, VV, VC, B >:: +template< class V, class C, class R, class B > +fpa::Base::Dijkstra< V, C, R, B >:: Dijkstra( ) : Superclass( ) { } // ------------------------------------------------------------------------- -template< class V, class C, class VV, class VC, class B > -fpa::Base::Dijkstra< V, C, VV, VC, B >:: +template< class V, class C, class R, class B > +fpa::Base::Dijkstra< V, C, R, B >:: ~Dijkstra( ) { } // ------------------------------------------------------------------------- -template< class V, class C, class VV, class VC, class B > -void fpa::Base::Dijkstra< V, C, VV, VC, B >:: -_InitializeQueue( ) +template< class V, class C, class R, class B > +bool fpa::Base::Dijkstra< V, C, R, B >:: +_ComputeNeighborResult( + TResult& result, const TVertex& neighbor, const TVertex& parent + ) const { - for( - typename _TNodes::const_iterator vIt = this->m_Seeds.begin( ); - vIt != this->m_Seeds.end( ); - vIt++ - ) - this->_QueuePush( *vIt ); + result = this->_Cost( neighbor, parent ); + result *= TResult( this->_Distance( neighbor, parent ) ); + + _TNode pn = this->_Node( parent ); + if( pn.Label == Self::AliveLabel ) + result += pn.Result; + + return( true ); } // ------------------------------------------------------------------------- -template< class V, class C, class VV, class VC, class B > -bool fpa::Base::Dijkstra< V, C, VV, VC, B >:: +template< class V, class C, class R, class B > +bool fpa::Base::Dijkstra< V, C, R, B >:: _IsQueueEmpty( ) const { return( this->m_Queue.empty( ) ); } // ------------------------------------------------------------------------- -template< class V, class C, class VV, class VC, class B > -void fpa::Base::Dijkstra< V, C, VV, VC, B >:: +template< class V, class C, class R, class B > +void fpa::Base::Dijkstra< V, C, R, B >:: _QueuePush( const _TNode& n ) { this->m_Queue.push_back( n ); - std::push_heap( this->m_Queue.begin( ), this->m_Queue.end( ) ); + std::push_heap( + this->m_Queue.begin( ), this->m_Queue.end( ), Self::m_NodeCompare + ); } // ------------------------------------------------------------------------- -template< class V, class C, class VV, class VC, class B > -typename fpa::Base::Dijkstra< V, C, VV, VC, B >:: -_TNode fpa::Base::Dijkstra< V, C, VV, VC, B >:: +template< class V, class C, class R, class B > +typename fpa::Base::Dijkstra< V, C, R, B >:: +_TNode fpa::Base::Dijkstra< V, C, R, B >:: _QueuePop( ) { - _TNode n; - if( !( this->m_Queue.empty( ) ) ) - { - // n = *( this->m_Queue.begin( ) ); - n = this->m_Queue.front( ); - std::pop_heap( this->m_Queue.begin( ), this->m_Queue.end( ) ); - this->m_Queue.pop_back( ); - - } // fi + _TNode n = this->m_Queue.front( ); + std::pop_heap( + this->m_Queue.begin( ), this->m_Queue.end( ), Self::m_NodeCompare + ); + this->m_Queue.pop_back( ); return( n ); } // ------------------------------------------------------------------------- -template< class V, class C, class VV, class VC, class B > -void fpa::Base::Dijkstra< V, C, VV, VC, B >:: +template< class V, class C, class R, class B > +void fpa::Base::Dijkstra< V, C, R, B >:: _QueueClear( ) { this->m_Queue.clear( ); } -// ------------------------------------------------------------------------- -template< class V, class C, class VV, class VC, class B > -bool fpa::Base::Dijkstra< V, C, VV, VC, B >:: -_UpdateNeigh( _TNode& nn, const _TNode& n ) -{ - TCost nc = this->_Cost( nn.Vertex, n.Vertex ); - if( C( 0 ) <= nc ) - { - nn.Cost = n.Cost + nc; - nn.Result = nn.Cost; - return( true ); - } - else - return( false ); -} - #endif // __FPA__BASE__DIJKSTRA__HXX__ // eof - $RCSfile$ diff --git a/lib/fpa/Base/Events.h b/lib/fpa/Base/Events.h index c92c4db..09f0637 100644 --- a/lib/fpa/Base/Events.h +++ b/lib/fpa/Base/Events.h @@ -4,15 +4,46 @@ #include #include +// ------------------------------------------------------------------------- +#define fpa_Base_NewEvent( name ) \ + class name \ + : public BaseEvent \ + { \ + public: \ + name( ) : BaseEvent( ) { } \ + virtual ~name( ) { } \ + const char* GetEventName( ) const \ + { return( "fpa::Base::##name" ); } \ + bool CheckEvent( const itk::EventObject* e ) const \ + { return( dynamic_cast< const name* >( e ) != NULL ); } \ + itk::EventObject* MakeObject( ) const \ + { return( new name( ) ); } \ + }; + +// ------------------------------------------------------------------------- +#define fpa_Base_NewEventWithVertex( name, type ) \ + class name \ + : public BaseEventWithVertex< type > \ + { \ + public: \ + name( ) : BaseEventWithVertex< type >( ) { } \ + name( const type& v, long fid ) \ + : BaseEventWithVertex< type >( v, fid ) { } \ + virtual ~name( ) { } \ + const char* GetEventName( ) const \ + { return( "fpa::Base::##name" ); } \ + bool CheckEvent( const itk::EventObject* e ) const \ + { return( dynamic_cast< const name* >( e ) != NULL ); } \ + itk::EventObject* MakeObject( ) const \ + { return( new name( ) ); } \ + }; + namespace fpa { namespace Base { /** - * Evolution event. An event is generated when a vertex changes its - * state. */ - template< class N > class BaseEvent : public itk::AnyEvent { @@ -20,171 +51,47 @@ namespace fpa BaseEvent( ) : itk::AnyEvent( ) { } - BaseEvent( const N& n ) - : itk::AnyEvent( ), - Node( n ) - { } virtual ~BaseEvent( ) { } - const char* GetEventName( ) const { return( "fpa::Base::BaseEvent" ); } bool CheckEvent( const itk::EventObject* e ) const - { return( dynamic_cast< const BaseEvent< N >* >( e ) != NULL ); } - itk::EventObject* MakeObject( ) const - { return( new BaseEvent< N >( ) ); } - - public: - N Node; - }; - - /** - */ - template< class N > - class FrontEvent - : public BaseEvent< N > - { - public: - FrontEvent( ) - : BaseEvent< N >( ) - { } - FrontEvent( const N& n ) - : BaseEvent< N >( n ) - { } - virtual ~FrontEvent( ) - { } - const char* GetEventName( ) const - { return( "fpa::Base::FrontEvent" ); } - bool CheckEvent( const itk::EventObject* e ) const - { return( dynamic_cast< const FrontEvent< N >* >( e ) != NULL ); } - itk::EventObject* MakeObject( ) const - { return( new FrontEvent< N >( ) ); } - }; - - /** - */ - template< class N > - class MarkEvent - : public BaseEvent< N > - { - public: - MarkEvent( ) - : BaseEvent< N >( ) - { } - MarkEvent( const N& n ) - : BaseEvent< N >( n ) - { } - virtual ~MarkEvent( ) - { } - const char* GetEventName( ) const - { return( "fpa::Base::MarkEvent" ); } - bool CheckEvent( const itk::EventObject* e ) const - { return( dynamic_cast< const MarkEvent< N >* >( e ) != NULL ); } - itk::EventObject* MakeObject( ) const - { return( new MarkEvent< N >( ) ); } - }; - - /** - */ - template< class N > - class CollisionEvent - : public BaseEvent< N > - { - public: - CollisionEvent( ) - : BaseEvent< N >( ) - { } - CollisionEvent( const N& n ) - : BaseEvent< N >( n ) - { } - virtual ~CollisionEvent( ) - { } - const char* GetEventName( ) const - { return( "fpa::Base::CollisionEvent" ); } - bool CheckEvent( const itk::EventObject* e ) const - { return( dynamic_cast< const CollisionEvent< N >* >( e ) != NULL ); } - itk::EventObject* MakeObject( ) const - { return( new CollisionEvent< N >( ) ); } - }; - - /** - */ - template< class N > - class EndEvent - : public BaseEvent< N > - { - public: - EndEvent( ) - : BaseEvent< N >( ) - { } - virtual ~EndEvent( ) - { } - const char* GetEventName( ) const - { return( "fpa::Base::EndEvent" ); } - bool CheckEvent( const itk::EventObject* e ) const - { return( dynamic_cast< const EndEvent< N >* >( e ) != NULL ); } + { return( dynamic_cast< const BaseEvent* >( e ) != NULL ); } itk::EventObject* MakeObject( ) const - { return( new EndEvent< N >( ) ); } + { return( new BaseEvent( ) ); } }; /** */ - template< class N > - class BacktrackingEvent - : public BaseEvent< N > + template< class V > + class BaseEventWithVertex + : public BaseEvent { public: - BacktrackingEvent( ) - : BaseEvent< N >( ) + BaseEventWithVertex( ) + : BaseEvent( ) { } - BacktrackingEvent( const N& n, const unsigned long& id ) - : BaseEvent< N >( n ), - BackId( id ) + BaseEventWithVertex( const V& v, long fid ) + : BaseEvent( ), + Vertex( v ), + FrontId( fid ) { } - virtual ~BacktrackingEvent( ) + virtual ~BaseEventWithVertex( ) { } const char* GetEventName( ) const - { return( "fpa::Base::BacktrackingEvent" ); } + { return( "fpa::Base::BaseEventWithVertex" ); } bool CheckEvent( const itk::EventObject* e ) const { return( - dynamic_cast< const BacktrackingEvent< N >* >( e ) != NULL + dynamic_cast< const BaseEventWithVertex< V >* >( e ) != NULL ); } itk::EventObject* MakeObject( ) const - { return( new BacktrackingEvent< N >( ) ); } - - unsigned long BackId; - }; + { return( new BaseEventWithVertex< V >( ) ); } - /** - */ - template< class N > - class EndBacktrackingEvent - : public BaseEvent< N > - { public: - EndBacktrackingEvent( ) - : BaseEvent< N >( ) - { } - EndBacktrackingEvent( const unsigned long& id ) - : BaseEvent< N >( ), - BackId( id ) - { } - virtual ~EndBacktrackingEvent( ) - { } - const char* GetEventName( ) const - { return( "fpa::Base::EndBacktrackingEvent" ); } - bool CheckEvent( const itk::EventObject* e ) const - { - return( - dynamic_cast< const EndBacktrackingEvent< N >* >( e ) != NULL - ); - } - itk::EventObject* MakeObject( ) const - { return( new EndBacktrackingEvent< N >( ) ); } - - unsigned long BackId; + V Vertex; + long FrontId; }; } // ecapseman diff --git a/lib/fpa/Base/Functors/InvertCostFunction.h b/lib/fpa/Base/Functors/InvertCostFunction.h index 278ae55..faf4fb2 100644 --- a/lib/fpa/Base/Functors/InvertCostFunction.h +++ b/lib/fpa/Base/Functors/InvertCostFunction.h @@ -29,7 +29,7 @@ namespace fpa public: virtual C Evaluate( const C& input ) const { - return( C( 1 ) / ( C( 0 ) + C( input ) ) ); + return( C( 1 ) / ( C( 1 ) + C( input ) ) ); } protected: diff --git a/lib/fpa/Base/Functors/TautologyFunction.h b/lib/fpa/Base/Functors/TautologyFunction.h new file mode 100644 index 0000000..f79666d --- /dev/null +++ b/lib/fpa/Base/Functors/TautologyFunction.h @@ -0,0 +1,53 @@ +#ifndef __FPA__BASE__FUNCTORS__TAUTOLOGYFUNCTION__H__ +#define __FPA__BASE__FUNCTORS__TAUTOLOGYFUNCTION__H__ + +#include + +namespace fpa +{ + namespace Base + { + namespace Functors + { + /** + */ + template< class V > + class TautologyFunction + : public itk::FunctionBase< V, bool > + { + public: + typedef TautologyFunction Self; + typedef itk::FunctionBase< V, bool > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( TautologyFunction, itkFunctionBase ); + + public: + virtual bool Evaluate( const V& input ) const + { return( true ); } + + protected: + TautologyFunction( ) + : Superclass( ) + { } + virtual ~TautologyFunction( ) + { } + + private: + // Purposely not implemented + TautologyFunction( const Self& ); + void operator=( const Self& ); + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __FPA__BASE__FUNCTORS__TAUTOLOGYFUNCTION__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/RegionGrow.h b/lib/fpa/Base/RegionGrow.h index f7f1562..6028b75 100644 --- a/lib/fpa/Base/RegionGrow.h +++ b/lib/fpa/Base/RegionGrow.h @@ -2,105 +2,80 @@ #define __FPA__BASE__REGIONGROW__H__ #include -#include #include namespace fpa { namespace Base { - /** - */ - template< class V, class R, class VV, class VC > - class RegionGrowTraits - { - public: - typedef R TResult; - typedef V TVertex; - typedef VV TVertexValue; - typedef VC TVertexCmp; - - typedef bool TCost; - typedef long TFrontId; - - class TNode - { - public: - TNode( ) - { } - TNode( const TVertex& v, const TFrontId& f ) - : Vertex( v ), - Parent( v ), - FrontId( f ) - { } - TNode( const TVertex& v, const TResult& r, const TFrontId& f ) - : Vertex( v ), - Parent( v ), - Result( r ), - FrontId( f ) - { } - virtual ~TNode( ) - { } - - TVertex Vertex; - TVertex Parent; - TResult Result; - TFrontId FrontId; - }; - - typedef std::vector< TNode > TNodes; - }; - /** * Region grow is a front propagation with no costs. + * + * @param V Vertex type. + * @param C Vertex value type. + * @param R Result value type. + * @param B Base class for this algorithm. It should be any itk-based + * filter (itk::ProcessObject). + * */ - template< class V, class R, class VV, class VC, class B > + template< class V, class C, class R, class B > class RegionGrow - : public Algorithm< RegionGrowTraits< V, R, VV, VC >, B > + : public Algorithm< V, C, R, B > { public: - typedef V TVertex; - typedef R TResult; - typedef VV TVertexValue; - typedef B TBaseFilter; - - /// Standard class typdedefs - typedef RegionGrowTraits< V, R, VV, VC > TTraits; typedef RegionGrow Self; - typedef Algorithm< TTraits, B > Superclass; + typedef Algorithm< V, C, R, B > Superclass; typedef itk::SmartPointer< Self > Pointer; typedef itk::SmartPointer< const Self > ConstPointer; - typedef typename TTraits::TCost TCost; + typedef typename Superclass::TVertex TVertex; + typedef typename Superclass::TValue TValue; + typedef typename Superclass::TResult TResult; protected: - typedef typename TTraits::TFrontId _TFrontId; - typedef typename TTraits::TNode _TNode; - typedef typename TTraits::TNodes _TNodes; - typedef std::queue< _TNode > _TQueue; + typedef typename Superclass::_TVertices _TVertices; + typedef typename Superclass::_TCollision _TCollision; + typedef typename Superclass::_TCollisionsRow _TCollisionsRow; + typedef typename Superclass::_TCollisions _TCollisions; + typedef typename Superclass::_TNode _TNode; + typedef typename Superclass::_TNodes _TNodes; + + typedef std::queue< _TNode > _TQueue; public: itkTypeMacro( RegionGrow, Algorithm ); + itkGetConstMacro( InsideValue, TResult ); + itkGetConstMacro( OutsideValue, TResult ); + + itkSetMacro( InsideValue, TResult ); + itkSetMacro( OutsideValue, TResult ); + protected: RegionGrow( ); virtual ~RegionGrow( ); - virtual bool _UpdateResult ( _TNode& n ); - virtual void _InitializeQueue ( ); - virtual bool _IsQueueEmpty ( ) const; - virtual void _QueuePush ( const _TNode& n ); - virtual _TNode _QueuePop ( ); - virtual void _QueueClear ( ); - virtual bool _UpdateNeigh ( _TNode& nn, const _TNode& n ); + virtual bool _CheckMembership( const TVertex& v ) const = 0; + + // Results-related abstract methods + virtual bool _ComputeNeighborResult( + TResult& result, const TVertex& neighbor, const TVertex& parent + ) const; - virtual bool _CheckMembership( const _TNode& n ) const = 0; + // Queue-related abstract methods + virtual bool _IsQueueEmpty( ) const; + virtual void _QueuePush( const _TNode& n ); + virtual _TNode _QueuePop( ); + virtual void _QueueClear( ); private: - RegionGrow( const Self& ); // Not impl. - void operator=( const Self& ); // Not impl. + // Purposely not implemented + RegionGrow( const Self& other ); + Self& operator=( const Self& other ); protected: + TResult m_InsideValue; + TResult m_OutsideValue; _TQueue m_Queue; }; diff --git a/lib/fpa/Base/RegionGrow.hxx b/lib/fpa/Base/RegionGrow.hxx index bdc1ed3..2d554c2 100644 --- a/lib/fpa/Base/RegionGrow.hxx +++ b/lib/fpa/Base/RegionGrow.hxx @@ -2,62 +2,62 @@ #define __FPA__BASE__REGIONGROWING__HXX__ // ------------------------------------------------------------------------- -template< class V, class R, class VV, class VC, class B > -fpa::Base::RegionGrow< V, R, VV, VC, B >:: +template< class V, class C, class R, class B > +fpa::Base::RegionGrow< V, C, R, B >:: RegionGrow( ) - : Superclass( ) + : Superclass( ), + m_InsideValue( TResult( 1 ) ), + m_OutsideValue( TResult( 0 ) ) { } // ------------------------------------------------------------------------- -template< class V, class R, class VV, class VC, class B > -fpa::Base::RegionGrow< V, R, VV, VC, B >:: +template< class V, class C, class R, class B > +fpa::Base::RegionGrow< V, C, R, B >:: ~RegionGrow( ) { } // ------------------------------------------------------------------------- -template< class V, class R, class VV, class VC, class B > -bool fpa::Base::RegionGrow< V, R, VV, VC, B >:: -_UpdateResult( _TNode& n ) +template< class V, class C, class R, class B > +bool fpa::Base::RegionGrow< V, C, R, B >:: +_ComputeNeighborResult( + TResult& result, const TVertex& neighbor, const TVertex& parent + ) const { - n.Result = R( this->_CheckMembership( n ) ); - return( n.Result ); -} + if( this->_CheckMembership( neighbor ) ) + { + result = this->m_InsideValue; + return( true ); + } + else + { + result = this->m_OutsideValue; + return( false ); -// ------------------------------------------------------------------------- -template< class V, class R, class VV, class VC, class B > -void fpa::Base::RegionGrow< V, R, VV, VC, B >:: -_InitializeQueue( ) -{ - for( - typename _TNodes::const_iterator vIt = this->m_Seeds.begin( ); - vIt != this->m_Seeds.end( ); - vIt++ - ) - this->_QueuePush( *vIt ); + } // fi } // ------------------------------------------------------------------------- -template< class V, class R, class VV, class VC, class B > -bool fpa::Base::RegionGrow< V, R, VV, VC, B >:: +template< class V, class C, class R, class B > +bool fpa::Base::RegionGrow< V, C, R, B >:: _IsQueueEmpty( ) const { return( this->m_Queue.empty( ) ); } // ------------------------------------------------------------------------- -template< class V, class R, class VV, class VC, class B > -void fpa::Base::RegionGrow< V, R, VV, VC, B >:: +template< class V, class C, class R, class B > +void fpa::Base::RegionGrow< V, C, R, B >:: _QueuePush( const _TNode& n ) { this->m_Queue.push( n ); } // ------------------------------------------------------------------------- -template< class V, class R, class VV, class VC, class B > -typename fpa::Base::RegionGrow< V, R, VV, VC, B >:: -_TNode fpa::Base::RegionGrow< V, R, VV, VC, B >:: +template< class V, class C, class R, class B > +typename fpa::Base::RegionGrow< V, C, R, B >:: +_TNode fpa::Base::RegionGrow< V, C, R, B >:: _QueuePop( ) { _TNode n = this->m_Queue.front( ); @@ -66,22 +66,14 @@ _QueuePop( ) } // ------------------------------------------------------------------------- -template< class V, class R, class VV, class VC, class B > -void fpa::Base::RegionGrow< V, R, VV, VC, B >:: +template< class V, class C, class R, class B > +void fpa::Base::RegionGrow< V, C, R, B >:: _QueueClear( ) { while( this->m_Queue.size( ) > 0 ) this->m_Queue.pop( ); } -// ------------------------------------------------------------------------- -template< class V, class R, class VV, class VC, class B > -bool fpa::Base::RegionGrow< V, R, VV, VC, B >:: -_UpdateNeigh( _TNode& nn, const _TNode& n ) -{ - return( true ); -} - #endif // __FPA__BASE__REGIONGROWING__HXX__ // eof - $RCSfile$ diff --git a/lib/fpa/Image/Algorithm.h b/lib/fpa/Image/Algorithm.h index e23a108..cd218a6 100644 --- a/lib/fpa/Image/Algorithm.h +++ b/lib/fpa/Image/Algorithm.h @@ -2,91 +2,19 @@ #define __FPA__IMAGE__ALGORITHM__H__ #include -#include namespace fpa { namespace Image { - namespace Functors - { - /** - */ - template< class VV, class C > - class CastVertexValueToCost - : public itk::FunctionBase< VV, C > - { - public: - // Type-related and pointers - typedef CastVertexValueToCost Self; - typedef itk::FunctionBase< VV, C > Superclass; - typedef itk::SmartPointer< Self > Pointer; - typedef itk::SmartPointer< const Self > ConstPointer; - - public: - itkNewMacro( Self ); - itkTypeMacro( CastVertexValueToCost, itkFunctionBase ); - - public: - virtual C Evaluate( const VV& v ) const - { return( C( v ) ); } - - protected: - CastVertexValueToCost( ) - : Superclass( ) - { } - virtual ~CastVertexValueToCost( ) - { } - - private: - // Purposely not implemented - CastVertexValueToCost( const Self& ); - void operator=( const Self& ); - }; - - /** - */ - template< class VV, class C > - class CastVertexValueToConstantCost - : public itk::FunctionBase< VV, C > - { - public: - // Type-related and pointers - typedef CastVertexValueToConstantCost Self; - typedef itk::FunctionBase< VV, C > Superclass; - typedef itk::SmartPointer< Self > Pointer; - typedef itk::SmartPointer< const Self > ConstPointer; - - public: - itkNewMacro( Self ); - itkTypeMacro( CastVertexValueToConstantCost, itkFunctionBase ); - - public: - virtual C Evaluate( const VV& v ) const - { return( C( 1 ) ); } - - protected: - CastVertexValueToConstantCost( ) - : Superclass( ) - { } - virtual ~CastVertexValueToConstantCost( ) - { } - - private: - // Purposely not implemented - CastVertexValueToConstantCost( const Self& ); - void operator=( const Self& ); - }; - - } // ecapseman - /** * A generic front propagation algorithm were vertices are image pixels. * - * @param I Input image type - * @param A Base algorithm (RegionGrow, Dijkstra or FastMarching) + * @param I Input image type + * @param O Output image type + * @param A Base algorithm (RegionGrow, Dijkstra or FastMarching) */ - template< class I, class A, class CC > + template< class I, class O, class A > class Algorithm : public A { @@ -98,72 +26,65 @@ namespace fpa typedef itk::SmartPointer< const Self > ConstPointer; /// Template input values - typedef I TInputImage; - typedef A TBaseAlgorithm; - typedef CC TCostConversionFunction; - - typedef typename A::TTraits TTraits; - typedef typename TTraits::TCost TCost; - typedef typename TTraits::TResult TResult; - typedef typename TTraits::TVertex TVertex; - typedef typename TTraits::TVertexValue TVertexValue; + typedef I TInputImage; + typedef O TOutputImage; - typedef itk::Image< TResult, I::ImageDimension > TOutputImage; + typedef typename Superclass::TVertex TVertex; + typedef typename Superclass::TValue TValue; + typedef typename Superclass::TResult TResult; protected: - typedef typename TTraits::TFrontId _TFrontId; - typedef typename TTraits::TNode _TNode; - typedef typename TTraits::TNodes _TNodes; + typedef typename Superclass::_TVertices _TVertices; + typedef typename Superclass::_TCollision _TCollision; + typedef typename Superclass::_TCollisionsRow _TCollisionsRow; + typedef typename Superclass::_TCollisions _TCollisions; + typedef typename Superclass::_TNode _TNode; + typedef typename Superclass::_TNodes _TNodes; - private: - typedef itk::Image< bool, I::ImageDimension > _TMarks; - typedef itk::Image< _TFrontId, I::ImageDimension > _TFrontsIds; - typedef itk::Image< TVertex, I::ImageDimension > _TParents; + typedef itk::Image< _TNode, I::ImageDimension > _TMarks; public: itkTypeMacro( Algorithm, TAlgorithm ); /// Set/Get itkGetConstMacro( NeighborhoodOrder, unsigned int ); - itkGetConstObjectMacro( CostConversion, TCostConversionFunction ); - itkGetObjectMacro( CostConversion, TCostConversionFunction ); - itkSetMacro( NeighborhoodOrder, unsigned int ); - itkSetObjectMacro( CostConversion, TCostConversionFunction ); protected: Algorithm( ); virtual ~Algorithm( ); - /// Base interface - virtual bool _UpdateResult( _TNode& n ); - - /// Pure virtual interface: vertices - virtual unsigned long _NumberOfVertices ( ) const; - virtual TVertexValue _Value ( const TVertex& v ) const; - virtual TResult _Result ( const TVertex& v ) const; - - /// Pure virtual interface: edges - virtual double _Norm ( const TVertex& a, const TVertex& b ) const; - virtual bool _Edge ( const TVertex& a, const TVertex& b ) const; - virtual TCost _Cost ( const TVertex& a, const TVertex& b ) const; - - /// Pure virtual interface: neighborhood - virtual void _Neighs ( const _TNode& n, _TNodes& N ) const; - virtual void _NeighsInDim ( const _TNode& n, - const unsigned int& d, - _TNodes& N ); - - /// Pure virtual interface: results - virtual void _InitializeResults ( ); + virtual void _BeforeGenerateData( ); + + // Graph-related abstract methods + virtual unsigned long _NumberOfVertices( ) const; + virtual const TValue& _VertexValue( const TVertex& v ) const; + virtual double _Distance( + const TVertex& a, const TVertex& b + ) const; + virtual bool _HasEdge( const TVertex& a, const TVertex& b ) const; + virtual void _Neighborhood( + _TVertices& neighborhood, const TVertex& v + ) const; + + // Results-related abstract methods + virtual void _InitResults( ); + virtual const TResult& _Result( const TVertex& v ) const; + virtual void _SetResult( const TVertex& v, const TResult& r ); + + // Marks-related abstract methods + virtual const _TNode& _Node( const TVertex& v ) const; + virtual void _InitMarks( ); + virtual void _Mark( const _TNode& node ); private: - Algorithm( const Self& ); // Not impl. - void operator=( const Self& ); // Not impl. + // Purposely not implemented + Algorithm( const Self& other ); + Self& operator=( const Self& other ); protected: - unsigned int m_NeighborhoodOrder; - typename TCostConversionFunction::Pointer m_CostConversion; + unsigned int m_NeighborhoodOrder; + typename _TMarks::Pointer m_Marks; }; } // ecapseman diff --git a/lib/fpa/Image/Algorithm.hxx b/lib/fpa/Image/Algorithm.hxx index 4a57bdd..0d83b03 100644 --- a/lib/fpa/Image/Algorithm.hxx +++ b/lib/fpa/Image/Algorithm.hxx @@ -2,68 +2,54 @@ #define __FPA__IMAGE__ALGORITHM__HXX__ #include -#include #include // ------------------------------------------------------------------------- -template< class I, class A, class CC > -fpa::Image::Algorithm< I, A, CC >:: +template< class I, class O, class A > +fpa::Image::Algorithm< I, O, A >:: Algorithm( ) : Superclass( ), m_NeighborhoodOrder( 1 ) { - this->m_CostConversion = TCostConversionFunction::New( ); } // ------------------------------------------------------------------------- -template< class I, class A, class CC > -fpa::Image::Algorithm< I, A, CC >:: +template< class I, class O, class A > +fpa::Image::Algorithm< I, O, A >:: ~Algorithm( ) { } // ------------------------------------------------------------------------- -template< class I, class A, class CC > -bool fpa::Image::Algorithm< I, A, CC >:: -_UpdateResult( _TNode& n ) +template< class I, class O, class A > +void fpa::Image::Algorithm< I, O, A >:: +_BeforeGenerateData( ) { - bool ret = this->Superclass::_UpdateResult( n ); - this->GetOutput( )->SetPixel( n.Vertex, n.Result ); - return( ret ); + this->Superclass::_BeforeGenerateData( ); + this->AllocateOutputs( ); } // ------------------------------------------------------------------------- -template< class I, class A, class CC > -unsigned long fpa::Image::Algorithm< I, A, CC >:: +template< class I, class O, class A > +unsigned long fpa::Image::Algorithm< I, O, A >:: _NumberOfVertices( ) const { - return( - this->GetInput( )->GetLargestPossibleRegion( ).GetNumberOfPixels( ) - ); + return( this->GetInput( )->GetRequestedRegion( ).GetNumberOfPixels( ) ); } // ------------------------------------------------------------------------- -template< class I, class A, class CC > -typename fpa::Image::Algorithm< I, A, CC >:: -TVertexValue fpa::Image::Algorithm< I, A, CC >:: -_Value( const TVertex& v ) const +template< class I, class O, class A > +const typename fpa::Image::Algorithm< I, O, A >:: +TValue& fpa::Image::Algorithm< I, O, A >:: +_VertexValue( const TVertex& v ) const { return( this->GetInput( )->GetPixel( v ) ); } // ------------------------------------------------------------------------- -template< class I, class A, class CC > -typename fpa::Image::Algorithm< I, A, CC >:: -TResult fpa::Image::Algorithm< I, A, CC >:: -_Result( const TVertex& v ) const -{ - return( this->GetOutput( )->GetPixel( v ) ); -} - -// ------------------------------------------------------------------------- -template< class I, class A, class CC > -double fpa::Image::Algorithm< I, A, CC >:: -_Norm( const TVertex& a, const TVertex& b ) const +template< class I, class O, class A > +double fpa::Image::Algorithm< I, O, A >:: +_Distance( const TVertex& a, const TVertex& b ) const { typename I::PointType pa, pb; this->GetInput( )->TransformIndexToPhysicalPoint( a, pa ); @@ -72,9 +58,9 @@ _Norm( const TVertex& a, const TVertex& b ) const } // ------------------------------------------------------------------------- -template< class I, class A, class CC > -bool fpa::Image::Algorithm< I, A, CC >:: -_Edge( const TVertex& a, const TVertex& b ) const +template< class I, class O, class A > +bool fpa::Image::Algorithm< I, O, A >:: +_HasEdge( const TVertex& a, const TVertex& b ) const { unsigned long dist = 0; for( unsigned int d = 0; d < I::ImageDimension; d++ ) @@ -86,42 +72,23 @@ _Edge( const TVertex& a, const TVertex& b ) const } // ------------------------------------------------------------------------- -template< class I, class A, class CC > -typename fpa::Image::Algorithm< I, A, CC >:: -TCost fpa::Image::Algorithm< I, A, CC >:: -_Cost( const TVertex& a, const TVertex& b ) const -{ - static const TCost INF_COST = std::numeric_limits< TCost >::max( ); - if( this->_Edge( a, b ) ) - { - return( - this->m_CostConversion->Evaluate( this->GetInput( )->GetPixel( b ) ) - ); - } - else - return( INF_COST ); -} - -// ------------------------------------------------------------------------- -template< class I, class A, class CC > -void fpa::Image::Algorithm< I, A, CC >:: -_Neighs( const _TNode& n, _TNodes& N ) const +template< class I, class O, class A > +void fpa::Image::Algorithm< I, O, A >:: +_Neighborhood( _TVertices& neighborhood, const TVertex& v ) const { typename I::RegionType reg = this->GetInput( )->GetRequestedRegion( ); - N.clear( ); + neighborhood.clear( ); if( this->m_NeighborhoodOrder == 1 ) { for( unsigned int d = 0; d < I::ImageDimension; d++ ) { for( int i = -1; i <= 1; i += 2 ) { - TVertex v = n.Vertex; - v[ d ] += i; - if( reg.IsInside( v ) ) - N.push_back( _TNode( v, n.FrontId ) ); - else - N.push_back( n ); + TVertex n = v; + n[ d ] += i; + if( reg.IsInside( n ) ) + neighborhood.push_back( n ); } // rof @@ -134,15 +101,14 @@ _Neighs( const _TNode& n, _TNodes& N ) const nSize.Fill( 1 ); TNeighIt nIt( nSize, this->GetInput( ), reg ); - nIt.SetLocation( n.Vertex ); + nIt.SetLocation( v ); for( unsigned int i = 0; i < nIt.Size( ); i++ ) { - TVertex idxN = nIt.GetIndex( i ); - if( idxN == n.Vertex ) - continue; - if( !reg.IsInside( idxN ) ) + TVertex n = nIt.GetIndex( i ); + if( n == v ) continue; - N.push_back( _TNode( idxN, n.FrontId ) ); + if( reg.IsInside( n ) ) + neighborhood.push_back( n ); } // rof @@ -150,28 +116,65 @@ _Neighs( const _TNode& n, _TNodes& N ) const } // ------------------------------------------------------------------------- -template< class I, class A, class CC > -void fpa::Image::Algorithm< I, A, CC >:: -_NeighsInDim( const _TNode& n, const unsigned int& d, _TNodes& N ) +template< class I, class O, class A > +void fpa::Image::Algorithm< I, O, A >:: +_InitResults( ) { - typename I::RegionType reg = this->GetInput( )->GetRequestedRegion( ); +} - N.clear( ); - for( int i = -1; i <= 1; i += 2 ) - { - TVertex v = n.Vertex; - v[ d ] += i; - if( reg.IsInside( v ) ) - N.push_back( _TNode( v, n.FrontId ) ); +// ------------------------------------------------------------------------- +template< class I, class O, class A > +const typename fpa::Image::Algorithm< I, O, A >:: +TResult& fpa::Image::Algorithm< I, O, A >:: +_Result( const TVertex& v ) const +{ + return( this->GetOutput( )->GetPixel( v ) ); +} + +// ------------------------------------------------------------------------- +template< class I, class O, class A > +void fpa::Image::Algorithm< I, O, A >:: +_SetResult( const TVertex& v, const TResult& r ) +{ + this->GetOutput( )->SetPixel( v, r ); +} + +// ------------------------------------------------------------------------- +template< class I, class O, class A > +const typename fpa::Image::Algorithm< I, O, A >:: +_TNode& fpa::Image::Algorithm< I, O, A >:: +_Node( const TVertex& v ) const +{ + return( this->m_Marks->GetPixel( v ) ); +} - } // rof +// ------------------------------------------------------------------------- +template< class I, class O, class A > +void fpa::Image::Algorithm< I, O, A >:: +_InitMarks( ) +{ + const I* in = this->GetInput( ); + + this->m_Marks = _TMarks::New( ); + this->m_Marks->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) ); + this->m_Marks->SetRequestedRegion( in->GetRequestedRegion( ) ); + this->m_Marks->SetBufferedRegion( in->GetBufferedRegion( ) ); + this->m_Marks->SetOrigin( in->GetOrigin( ) ); + this->m_Marks->SetSpacing( in->GetSpacing( ) ); + this->m_Marks->SetDirection( in->GetDirection( ) ); + this->m_Marks->Allocate( ); + + _TNode far_node; + far_node.Label = Self::FarLabel; + this->m_Marks->FillBuffer( far_node ); } // ------------------------------------------------------------------------- -template< class I, class A, class CC > -void fpa::Image::Algorithm< I, A, CC >:: -_InitializeResults( ) +template< class I, class O, class A > +void fpa::Image::Algorithm< I, O, A >:: +_Mark( const _TNode& node ) { + this->m_Marks->SetPixel( node.Vertex, node ); } #endif // __FPA__IMAGE__ALGORITHM__HXX__ diff --git a/lib/fpa/Image/Dijkstra.h b/lib/fpa/Image/Dijkstra.h index 1464d3c..4e5105c 100644 --- a/lib/fpa/Image/Dijkstra.h +++ b/lib/fpa/Image/Dijkstra.h @@ -1,12 +1,11 @@ #ifndef __FPA__IMAGE__DIJKSTRA__H__ #define __FPA__IMAGE__DIJKSTRA__H__ -#include -#include +#include #include -#include #include #include +#include namespace fpa { @@ -14,45 +13,75 @@ namespace fpa { /** * @param I Input image type + * @param O Output image type */ - template< class I, class C > + template< class I, class O > class Dijkstra - : public Algorithm< I, fpa::Base::Dijkstra< typename I::IndexType, C, typename I::PixelType, itk::Functor::IndexLexicographicCompare< I::ImageDimension >, itk::ImageToImageFilter< I, itk::Image< C, I::ImageDimension > > > > + : public Algorithm< I, O, fpa::Base::Dijkstra< typename I::IndexType, typename I::PixelType, typename O::PixelType, itk::ImageToImageFilter< I, O > > > { public: - // Standard class typdedefs - typedef typename I::IndexType TVertex; - typedef typename I::PixelType TVertexValue; - typedef itk::Image< C, I::ImageDimension > TCostImage; - typedef itk::ImageToImageFilter< I, TCostImage > TBaseFilter; - typedef fpa::Base::Dijkstra< TVertex, C, TVertexValue, itk::Functor::IndexLexicographicCompare< I::ImageDimension >, TBaseFilter > TBaseAlgorithm; - - typedef Dijkstra Self; - typedef Algorithm< I, TBaseAlgorithm > Superclass; - typedef itk::SmartPointer< Self > Pointer; - typedef itk::SmartPointer< const Self > ConstPointer; + typedef fpa::Base::Dijkstra< typename I::IndexType, typename I::PixelType, typename O::PixelType, itk::ImageToImageFilter< I, O > > TBaseAlgorithm; + + typedef Dijkstra Self; + typedef Algorithm< I, O, TBaseAlgorithm > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TInputImage TInputImage; + typedef typename Superclass::TOutputImage TOutputImage; + typedef typename Superclass::TVertex TVertex; + typedef typename Superclass::TValue TValue; + typedef typename Superclass::TResult TResult; + + typedef fpa::Image::Functors::ImageCostFunction< TInputImage, TResult > TCostFunction; + typedef itk::FunctionBase< TResult, TResult > TConversionFunction; + + protected: + typedef typename Superclass::_TVertices _TVertices; + typedef typename Superclass::_TCollision _TCollision; + typedef typename Superclass::_TCollisionsRow _TCollisionsRow; + typedef typename Superclass::_TCollisions _TCollisions; + typedef typename Superclass::_TNode _TNode; + typedef typename Superclass::_TNodes _TNodes; public: itkNewMacro( Self ); - itkTypeMacro( Dijkstra, fpaBaseDijkstra ); + itkTypeMacro( Dijkstra, Algorithm ); + + itkGetObjectMacro( CostFunction, TCostFunction ); + itkGetObjectMacro( ConversionFunction, TConversionFunction ); + + itkGetConstObjectMacro( CostFunction, TCostFunction ); + itkGetConstObjectMacro( ConversionFunction, TConversionFunction ); + + itkSetObjectMacro( CostFunction, TCostFunction ); + itkSetObjectMacro( ConversionFunction, TConversionFunction ); protected: - Dijkstra( ) - : Superclass( ) - { } - virtual ~Dijkstra( ) - { } + Dijkstra( ); + virtual ~Dijkstra( ); + + virtual TResult _Cost( const TVertex& v, const TVertex& p ) const; + + virtual void _BeforeGenerateData( ); + virtual void _InitResults( ); private: // Purposely not implemented - Dijkstra( const Self& ); - void operator=( const Self& ); + Dijkstra( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TCostFunction::Pointer m_CostFunction; + typename TConversionFunction::Pointer m_ConversionFunction; }; } // ecapseman } // ecapseman +#include + #endif // __FPA__IMAGE__DIJKSTRA__H__ // eof - $RCSfile$ diff --git a/lib/fpa/Image/Dijkstra.hxx b/lib/fpa/Image/Dijkstra.hxx new file mode 100644 index 0000000..eca6ce3 --- /dev/null +++ b/lib/fpa/Image/Dijkstra.hxx @@ -0,0 +1,59 @@ +#ifndef __FPA__IMAGE__DIJKSTRA__HXX__ +#define __FPA__IMAGE__DIJKSTRA__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class I, class O > +fpa::Image::Dijkstra< I, O >:: +Dijkstra( ) + : Superclass( ) +{ + this->m_CostFunction = TCostFunction::New( ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +fpa::Image::Dijkstra< I, O >:: +~Dijkstra( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class O > +typename fpa::Image::Dijkstra< I, O >:: +TResult fpa::Image::Dijkstra< I, O >:: +_Cost( const TVertex& v, const TVertex& p ) const +{ + if( this->_HasEdge( v, p ) ) + { + TResult c = this->m_CostFunction->Evaluate( v, p ); + if( this->m_ConversionFunction.IsNotNull( ) ) + c = this->m_ConversionFunction->Evaluate( c ); + return( c ); + } + else + return( std::numeric_limits< TResult >::max( ) ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +void fpa::Image::Dijkstra< I, O >:: +_BeforeGenerateData( ) +{ + this->Superclass::_BeforeGenerateData( ); + this->m_CostFunction->SetInputImage( this->GetInput( ) ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +void fpa::Image::Dijkstra< I, O >:: +_InitResults( ) +{ + this->Superclass::_InitResults( ); + this->GetOutput( )->FillBuffer( std::numeric_limits< TResult >::max( ) ); +} + +#endif // __FPA__IMAGE__DIJKSTRA__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Functors/ImageCostFunction.h b/lib/fpa/Image/Functors/ImageCostFunction.h new file mode 100644 index 0000000..533b64b --- /dev/null +++ b/lib/fpa/Image/Functors/ImageCostFunction.h @@ -0,0 +1,90 @@ +#ifndef __FPA__IMAGE__FUNCTORS__IMAGECOSTFUNCTION__H__ +#define __FPA__IMAGE__FUNCTORS__IMAGECOSTFUNCTION__H__ + +#include +#include +#include + +namespace fpa +{ + namespace Image + { + namespace Functors + { + /** + */ + template< class I, class R > + class ImageCostFunction + : public itk::Object + { + public: + /// Type-related and pointers + typedef ImageCostFunction Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef I TInputImage; + typedef R TResult; + typedef typename I::IndexType TIndex; + + public: + itkNewMacro( Self ); + itkTypeMacro( ImageCostFunction, itkObject ); + + itkGetConstObjectMacro( InputImage, I ); + itkSetConstObjectMacro( InputImage, I ); + + public: + virtual R Evaluate( const TIndex& v, const TIndex& p ) const + { + typedef typename I::PixelType _TPixel; + typedef typename itk::NumericTraits< _TPixel > _TTraits; + typedef typename _TTraits::MeasurementVectorType _TVector; + typedef typename _TTraits::ValueType _TValue; + + if( this->m_InputImage.IsNotNull( ) ) + { + _TPixel pix = this->m_InputImage->GetPixel( v ); + if( typeid( _TPixel ) != typeid( _TValue ) ) + { + _TVector* array = reinterpret_cast< _TVector* >( &pix ); + unsigned int n = + this->m_InputImage->GetNumberOfComponentsPerPixel( ); + R sum = R( 0 ); + for( unsigned int i = 0; i < n; ++i ) + sum += R( ( *array )[ i ] ); + return( sum / R( n ) ); + } + else + return( R( *( reinterpret_cast< _TValue* >( &pix ) ) ) ); + } + else + return( std::numeric_limits< R >::max( ) ); + } + + protected: + ImageCostFunction( ) + : Superclass( ) + { } + virtual ~ImageCostFunction( ) + { } + + private: + // Purposely not implemented + ImageCostFunction( const Self& ); + void operator=( const Self& ); + + protected: + typename I::ConstPointer m_InputImage; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __FPA__IMAGE__FUNCTORS__IMAGECOSTFUNCTION__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Functors/ImageFunction.h b/lib/fpa/Image/Functors/ImageFunction.h deleted file mode 100644 index a1cc9ec..0000000 --- a/lib/fpa/Image/Functors/ImageFunction.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef __FPA__IMAGE__FUNCTORS__IMAGEFUNCTION__H__ -#define __FPA__IMAGE__FUNCTORS__IMAGEFUNCTION__H__ - -#include - -namespace fpa -{ - namespace Image - { - namespace Functors - { - /** - */ - template< class I, class O > - class ImageFunction - : public itk::FunctionBase< typename I::IndexType, O > - { - public: - /// Type-related and pointers - typedef ImageFunction Self; - typedef itk::FunctionBase< typename I::IndexType, O > Superclass; - typedef itk::SmartPointer< Self > Pointer; - typedef itk::SmartPointer< const Self > ConstPointer; - - typedef I TInputImage; - typedef O TOutputValue; - typedef typename I::IndexType TIndex; - - public: - itkTypeMacro( ImageFunction, itkFunctionBase ); - - itkGetConstObjectMacro( InputImage, I ); - itkSetConstObjectMacro( InputImage, I ); - - public: - virtual O Evaluate( const TIndex& idx ) const = 0; - - protected: - ImageFunction( ) - : Superclass( ) - { } - virtual ~ImageFunction( ) - { } - - private: - // Purposely not implemented - ImageFunction( const Self& ); - void operator=( const Self& ); - - protected: - typename I::ConstPointer m_InputImage; - }; - - } // ecapseman - - } // ecapseman - -} // ecapseman - -#endif // __FPA__IMAGE__FUNCTORS__IMAGEFUNCTION__H__ - -// eof - $RCSfile$ diff --git a/lib/fpa/Image/RegionGrow.h b/lib/fpa/Image/RegionGrow.h index b12a869..e20f062 100644 --- a/lib/fpa/Image/RegionGrow.h +++ b/lib/fpa/Image/RegionGrow.h @@ -1,11 +1,10 @@ #ifndef __FPA__IMAGE__REGIONGROW__H__ #define __FPA__IMAGE__REGIONGROW__H__ +#include #include -#include #include #include -#include namespace fpa { @@ -13,64 +12,55 @@ namespace fpa { /** * @param I Input image type + * @param O Output image type */ - template< class I, class O = I, class CC = fpa::Image::Functors::CastVertexValueToCost< typename I::PixelType, typename O::PixelType > > + template< class I, class O > class RegionGrow - : public Algorithm< I, fpa::Base::RegionGrow< typename I::IndexType, typename O::PixelType, typename I::PixelType, itk::Functor::IndexLexicographicCompare< I::ImageDimension >, itk::ImageToImageFilter< I, O > >, CC > + : public Algorithm< I, O, fpa::Base::RegionGrow< typename I::IndexType, typename I::PixelType, typename O::PixelType, itk::ImageToImageFilter< I, O > > > { public: - // Standard class typdedefs - typedef typename I::IndexType TVertex; - typedef typename O::PixelType TResult; - typedef typename I::PixelType TVertexValue; - typedef itk::ImageToImageFilter< I, O > TBaseFilter; - typedef fpa::Base::RegionGrow< TVertex, TResult, TVertexValue, itk::Functor::IndexLexicographicCompare< I::ImageDimension >, TBaseFilter > TBaseAlgorithm; - - typedef RegionGrow Self; - typedef Algorithm< I, TBaseAlgorithm, CC > Superclass; - typedef itk::SmartPointer< Self > Pointer; - typedef itk::SmartPointer< const Self > ConstPointer; - - typedef - fpa::Image::Functors::ImageFunction< I, bool > - TMembershipFunction; + typedef fpa::Base::RegionGrow< typename I::IndexType, typename I::PixelType, typename O::PixelType, itk::ImageToImageFilter< I, O > > TBaseAlgorithm; + + typedef RegionGrow Self; + typedef Algorithm< I, O, TBaseAlgorithm > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TInputImage TInputImage; + typedef typename Superclass::TOutputImage TOutputImage; + typedef typename Superclass::TVertex TVertex; + typedef typename Superclass::TValue TValue; + typedef typename Superclass::TResult TResult; + + typedef itk::FunctionBase< TValue, bool > TMembershipFunction; + + protected: + typedef typename Superclass::_TVertices _TVertices; + typedef typename Superclass::_TCollision _TCollision; + typedef typename Superclass::_TCollisionsRow _TCollisionsRow; + typedef typename Superclass::_TCollisions _TCollisions; + typedef typename Superclass::_TNode _TNode; + typedef typename Superclass::_TNodes _TNodes; public: itkNewMacro( Self ); - itkTypeMacro( RegionGrow, fpaBaseRegionGrow ); + itkTypeMacro( RegionGrow, Algorithm ); itkGetObjectMacro( MembershipFunction, TMembershipFunction ); + itkGetConstObjectMacro( MembershipFunction, TMembershipFunction ); itkSetObjectMacro( MembershipFunction, TMembershipFunction ); protected: - RegionGrow( ) - : Superclass( ), - m_MembershipFunction( NULL ) - { } - virtual ~RegionGrow( ) - { } - - virtual bool _CheckMembership( - const typename Superclass::_TNode& n - ) const - { - if( this->m_MembershipFunction.IsNotNull( ) ) - { - if( - this->m_MembershipFunction->GetInputImage( ) != - this->GetInput( ) - ) - this->m_MembershipFunction->SetInputImage( this->GetInput( ) ); - return( this->m_MembershipFunction->Evaluate( n.Vertex ) ); - } - else - return( false ); - } + RegionGrow( ); + virtual ~RegionGrow( ); + + virtual bool _CheckMembership( const TVertex& v ) const; + virtual void _InitResults( ); private: // Purposely not implemented - RegionGrow( const Self& ); - void operator=( const Self& ); + RegionGrow( const Self& other ); + Self& operator=( const Self& other ); protected: typename TMembershipFunction::Pointer m_MembershipFunction; @@ -80,6 +70,8 @@ namespace fpa } // ecapseman +#include + #endif // __FPA__IMAGE__REGIONGROW__H__ // eof - $RCSfile$ diff --git a/lib/fpa/Image/RegionGrow.hxx b/lib/fpa/Image/RegionGrow.hxx new file mode 100644 index 0000000..e8e92c8 --- /dev/null +++ b/lib/fpa/Image/RegionGrow.hxx @@ -0,0 +1,41 @@ +#ifndef __FPA__IMAGE__REGIONGROW__HXX__ +#define __FPA__IMAGE__REGIONGROW__HXX__ + +// ------------------------------------------------------------------------- +template< class I, class O > +fpa::Image::RegionGrow< I, O >:: +RegionGrow( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class O > +fpa::Image::RegionGrow< I, O >:: +~RegionGrow( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class O > +bool fpa::Image::RegionGrow< I, O >:: +_CheckMembership( const TVertex& v ) const +{ + if( this->m_MembershipFunction.IsNotNull( ) ) + return( this->m_MembershipFunction->Evaluate( this->_VertexValue( v ) ) ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +void fpa::Image::RegionGrow< I, O >:: +_InitResults( ) +{ + this->Superclass::_InitResults( ); + this->GetOutput( )->FillBuffer( this->m_OutsideValue ); +} + +#endif // __FPA__IMAGE__REGIONGROW__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image2DObserver.h b/lib/fpa/VTK/Image2DObserver.h index 68dcae0..c61af4d 100644 --- a/lib/fpa/VTK/Image2DObserver.h +++ b/lib/fpa/VTK/Image2DObserver.h @@ -36,8 +36,11 @@ namespace fpa itkNewMacro( Self ); itkTypeMacro( Image2DObserver, itkCommand ); + itkGetConstMacro( RenderPercentage, double ); + itkSetMacro( RenderPercentage, double ); + public: - void SetImage( const TImage* img, R* rw ); + void SetRenderWindow( R* rw ); void SetPixel( typename TImage::IndexType idx, unsigned char red, @@ -51,33 +54,21 @@ namespace fpa void Execute( const itk::Object* c, const itk::EventObject& e ); protected: - Image2DObserver( ) - : Superclass( ), - m_RenderWindow( NULL ), - m_Number( 0 ), - m_Percentage( 0 ) - { - this->m_Stencil = TImageData::New( ); - this->m_StencilActor = TImageActor::New( ); - } - virtual ~Image2DObserver( ) - { } + Image2DObserver( ); + virtual ~Image2DObserver( ); private: Image2DObserver( const Self& ); // Not impl. void operator=( const Self& ); // Not impl. protected: - typedef vtkSmartPointer< vtkImageActor > TImageActor; - typedef vtkSmartPointer< vtkImageData > TImageData; - - typename TImage::ConstPointer m_Image; + vtkSmartPointer< vtkImageData > m_Stencil; + vtkSmartPointer< vtkImageActor > m_StencilActor; R* m_RenderWindow; - TImageData m_Stencil; - TImageActor m_StencilActor; - unsigned long m_Number; - unsigned long m_Percentage; + unsigned long m_Count; + unsigned long m_RenderCount; + double m_RenderPercentage; }; } // ecapseman diff --git a/lib/fpa/VTK/Image2DObserver.hxx b/lib/fpa/VTK/Image2DObserver.hxx index 7ebe526..74e5f4c 100644 --- a/lib/fpa/VTK/Image2DObserver.hxx +++ b/lib/fpa/VTK/Image2DObserver.hxx @@ -12,58 +12,60 @@ // ------------------------------------------------------------------------- template< class F, class R > void fpa::VTK::Image2DObserver< F, R >:: -SetImage( const TImage* img, R* rw ) +SetRenderWindow( R* rw ) { - this->m_Image = img; this->m_RenderWindow = rw; - unsigned int minD = TImage::ImageDimension; - minD = ( minD < 3 )? minD: 3; - - int e[ 6 ] = { 0 }; - typename TImage::RegionType reg = this->m_Image->GetRequestedRegion( ); - for( unsigned int i = 0; i < minD; i++ ) - { - e[ ( i << 1 ) + 0 ] = reg.GetIndex( )[ i ]; - e[ ( i << 1 ) + 1 ] = reg.GetIndex( )[ i ] + reg.GetSize( )[ i ] - 1; - - } // rof - - typename TImage::SpacingType spac = this->m_Image->GetSpacing( ); - double s[ 3 ] = { 1, 1, 1 }; - for( unsigned int i = 0; i < minD; i++ ) - s[ i ] = double( spac[ i ] ); - - typename TImage::PointType orig = this->m_Image->GetOrigin( ); - double o[ 3 ] = { 0 }; - for( unsigned int i = 0; i < minD; i++ ) - o[ i ] = double( orig[ i ] ); - - this->m_Stencil->SetExtent( e ); - this->m_Stencil->SetSpacing( s ); - this->m_Stencil->SetOrigin( o ); - this->m_Stencil->AllocateScalars( VTK_UNSIGNED_CHAR, 4 ); - for( unsigned int i = 0; i < 3; i++ ) - this->m_Stencil->GetPointData( )-> - GetScalars( )->FillComponent( i, 255 ); - this->m_Stencil->GetPointData( )->GetScalars( )->FillComponent( 3, 0 ); - - this->m_StencilActor->SetInputData( this->m_Stencil ); - this->m_StencilActor->InterpolateOff( ); - - double nPix = - double( this->m_Image->GetRequestedRegion( ).GetNumberOfPixels( ) ); - this->m_Percentage = ( unsigned long )( nPix * 0.01 ); - this->m_Number = 0; - - if( this->m_RenderWindow != NULL ) - { - vtkRenderer* ren = - this->m_RenderWindow->GetRenderers( )->GetFirstRenderer( ); - ren->AddActor( this->m_StencilActor ); - this->Render( ); - - } // fi + /* TODO + this->m_Image = img; + unsigned int minD = TImage::ImageDimension; + minD = ( minD < 3 )? minD: 3; + + int e[ 6 ] = { 0 }; + typename TImage::RegionType reg = this->m_Image->GetRequestedRegion( ); + for( unsigned int i = 0; i < minD; i++ ) + { + e[ ( i << 1 ) + 0 ] = reg.GetIndex( )[ i ]; + e[ ( i << 1 ) + 1 ] = reg.GetIndex( )[ i ] + reg.GetSize( )[ i ] - 1; + + } // rof + + typename TImage::SpacingType spac = this->m_Image->GetSpacing( ); + double s[ 3 ] = { 1, 1, 1 }; + for( unsigned int i = 0; i < minD; i++ ) + s[ i ] = double( spac[ i ] ); + + typename TImage::PointType orig = this->m_Image->GetOrigin( ); + double o[ 3 ] = { 0 }; + for( unsigned int i = 0; i < minD; i++ ) + o[ i ] = double( orig[ i ] ); + + this->m_Stencil->SetExtent( e ); + this->m_Stencil->SetSpacing( s ); + this->m_Stencil->SetOrigin( o ); + this->m_Stencil->AllocateScalars( VTK_UNSIGNED_CHAR, 4 ); + for( unsigned int i = 0; i < 3; i++ ) + this->m_Stencil->GetPointData( )-> + GetScalars( )->FillComponent( i, 255 ); + this->m_Stencil->GetPointData( )->GetScalars( )->FillComponent( 3, 0 ); + + this->m_StencilActor->SetInputData( this->m_Stencil ); + this->m_StencilActor->InterpolateOff( ); + + double nPix = + double( this->m_Image->GetRequestedRegion( ).GetNumberOfPixels( ) ); + this->m_Percentage = ( unsigned long )( nPix * 0.01 ); + this->m_Number = 0; + + if( this->m_RenderWindow != NULL ) + { + vtkRenderer* ren = + this->m_RenderWindow->GetRenderers( )->GetFirstRenderer( ); + ren->AddActor( this->m_StencilActor ); + this->Render( ); + + } // fi + */ } // ------------------------------------------------------------------------- @@ -103,13 +105,13 @@ template< class F, class R > void fpa::VTK::Image2DObserver< F, R >:: Execute( const itk::Object* c, const itk::EventObject& e ) { - typedef typename TImage::IndexType TIndex; - typedef typename TImage::PointType TPoint; - typedef typename TFilter::TEvent TEvent; - typedef typename TFilter::TFrontEvent TFrontEvent; - typedef typename TFilter::TMarkEvent TMarkEvent; - typedef typename TFilter::TCollisionEvent TCollisionEvent; - typedef typename TFilter::TEndEvent TEndEvent; + typedef typename F::TStartEvent TStartEvent; + typedef typename F::TStartLoopEvent TStartLoopEvent; + typedef typename F::TEndEvent TEndEvent; + typedef typename F::TEndLoopEvent TEndLoopEvent; + typedef typename F::TAliveEvent TAliveEvent; + typedef typename F::TFrontEvent TFrontEvent; + typedef typename F::TFreezeEvent TFreezeEvent; static unsigned char Colors[][4] = { @@ -131,58 +133,116 @@ Execute( const itk::Object* c, const itk::EventObject& e ) { 63, 63, 127, 127 } }; - if( this->m_RenderWindow == NULL ) + const F* filter = dynamic_cast< const F* >( c ); + if( this->m_RenderWindow == NULL || filter == NULL ) + return; + + const TStartEvent* startEvt = dynamic_cast< const TStartEvent* >( &e ); + if( startEvt != NULL ) + { + const typename F::TInputImage* img = filter->GetInput( ); + unsigned int minD = F::TInputImage::ImageDimension; + minD = ( minD < 3 )? minD: 3; + + int e[ 6 ] = { 0 }; + typename F::TInputImage::RegionType reg = img->GetRequestedRegion( ); + for( unsigned int i = 0; i < minD; i++ ) + { + e[ ( i << 1 ) + 0 ] = reg.GetIndex( )[ i ]; + e[ ( i << 1 ) + 1 ] = reg.GetIndex( )[ i ] + reg.GetSize( )[ i ] - 1; + + } // rof + + typename F::TInputImage::SpacingType spac = img->GetSpacing( ); + double s[ 3 ] = { 1, 1, 1 }; + for( unsigned int i = 0; i < minD; i++ ) + s[ i ] = double( spac[ i ] ); + + typename F::TInputImage::PointType orig = img->GetOrigin( ); + double o[ 3 ] = { 0 }; + for( unsigned int i = 0; i < minD; i++ ) + o[ i ] = double( orig[ i ] ); + + this->m_Stencil->SetExtent( e ); + this->m_Stencil->SetSpacing( s ); + this->m_Stencil->SetOrigin( o ); + this->m_Stencil->AllocateScalars( VTK_UNSIGNED_CHAR, 4 ); + for( unsigned int i = 0; i < 3; i++ ) + this->m_Stencil->GetPointData( )-> + GetScalars( )->FillComponent( i, 255 ); + this->m_Stencil->GetPointData( )->GetScalars( )->FillComponent( 3, 0 ); + + this->m_StencilActor->SetInputData( this->m_Stencil ); + this->m_StencilActor->InterpolateOff( ); + + this->m_Count = 0; + this->m_RenderCount = reg.GetNumberOfPixels( ); + + vtkRenderer* ren = + this->m_RenderWindow->GetRenderers( )->GetFirstRenderer( ); + ren->AddActor( this->m_StencilActor ); return; - const TEvent* evt = dynamic_cast< const TEvent* >( &e ); - TFrontEvent fevt; - TMarkEvent mevt; - TCollisionEvent cevt; - TEndEvent eevt; - if( evt != NULL ) + } // fi + + const TAliveEvent* aliveEvt = dynamic_cast< const TAliveEvent* >( &e ); + const TFrontEvent* frontEvt = dynamic_cast< const TFrontEvent* >( &e ); + if( aliveEvt != NULL || frontEvt != NULL ) { - if( mevt.CheckEvent( evt ) ) + if( aliveEvt != NULL ) this->SetPixel( - evt->Node.Vertex, - Colors[ evt->Node.FrontId ][ 0 ], - Colors[ evt->Node.FrontId ][ 1 ], - Colors[ evt->Node.FrontId ][ 2 ], - Colors[ evt->Node.FrontId ][ 3 ] + aliveEvt->Vertex, + Colors[ aliveEvt->FrontId ][ 0 ], + Colors[ aliveEvt->FrontId ][ 1 ], + Colors[ aliveEvt->FrontId ][ 2 ], + Colors[ aliveEvt->FrontId ][ 3 ] ); - else if( fevt.CheckEvent( evt ) ) - this->SetPixel( evt->Node.Vertex, 255, 0, 0, 255 ); - if( cevt.CheckEvent( evt ) ) - this->SetPixel( evt->Node.Vertex, 100, 50, 25, 255 ); + else if( frontEvt != NULL ) + this->SetPixel( frontEvt->Vertex, 255, 0, 0, 255 ); + this->m_Count++; - // Update visualization - if( this->m_Number == 0 || this->m_Percentage < 0 ) + // Render visual debug + double per = double( this->m_RenderCount ) * this->m_RenderPercentage; + if( double( this->m_Count ) >= per ) this->Render( ); - this->m_Number++; - this->m_Number %= this->m_Percentage; + if( double( this->m_Count ) >= per ) + this->m_Count = 0; - if( eevt.CheckEvent( evt ) ) - { - if( this->m_RenderWindow != NULL ) - { - /* TODO - vtkRenderer* ren = - this->m_RenderWindow->GetRenderers( )->GetFirstRenderer( ); - ren->RemoveActor( this->m_StencilActor ); - */ - this->Render( ); - - } // fi - - } // fi - } - else + return; + + } // fi + + const TEndEvent* endEvt = dynamic_cast< const TEndEvent* >( &e ); + if( endEvt != NULL ) { - // TODO: Remove all! + vtkRenderer* ren = + this->m_RenderWindow->GetRenderers( )->GetFirstRenderer( ); + ren->RemoveActor( this->m_StencilActor ); this->Render( ); + return; } // fi } +// ------------------------------------------------------------------------- +template< class F, class R > +fpa::VTK::Image2DObserver< F, R >:: +Image2DObserver( ) + : Superclass( ), + m_RenderWindow( NULL ), + m_RenderPercentage( double( 0.01 ) ) +{ + this->m_Stencil = vtkSmartPointer< vtkImageData >::New( ); + this->m_StencilActor = vtkSmartPointer< vtkImageActor >::New( ); +} + +// ------------------------------------------------------------------------- +template< class F, class R > +fpa::VTK::Image2DObserver< F, R >:: +~Image2DObserver( ) +{ +} + #endif // __FPA__VTK__IMAGE2DOBSERVER__HXX__ // eof - $RCSfile$ -- 2.47.1