+#include <cstdlib>
+#include <iostream>
+#include <limits>
+#include <string>
+
+#include <itkImage.h>
+#include <itkImageToVTKImageFilter.h>
+
+#include <itkImageFileReader.h>
+#include <itkMinimumMaximumImageCalculator.h>
+#include <itkInvertIntensityImageFilter.h>
+#include <itkDanielssonDistanceMapImageFilter.h>
+#include <itkImageFileWriter.h>
+
+#include <vtkCamera.h>
+#include <vtkImageActor.h>
+#include <vtkInteractorStyleImage.h>
+#include <vtkPointHandleRepresentation3D.h>
+#include <vtkProperty.h>
+#include <vtkRenderer.h>
+#include <vtkRenderWindow.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkSeedRepresentation.h>
+#include <vtkSeedWidget.h>
+#include <vtkSmartPointer.h>
+
+#include <fpa/Image/Dijkstra.h>
+#include <fpa/Base/Functors/InvertCostFunction.h>
+#include <fpa/VTK/Image2DObserver.h>
+
+// -------------------------------------------------------------------------
+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$