#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 #include #include #include // ------------------------------------------------------------------------- const unsigned int Dim = 3; typedef float TPixel; typedef float TScalar; typedef itk::Image< TPixel, Dim > TImage; typedef itk::ImageToVTKImageFilter< TImage > TVTKImage; typedef itk::ImageFileReader< TImage > TImageReader; typedef itk::ImageFileWriter< TImage > TImageWriter; typedef fpa::Image::DijkstraWithSphereBacktracking< TImage, TScalar > TDijkstra; typedef fpa::VTK::ImageMPR TMPR; typedef fpa::VTK::Image3DObserver< TDijkstra, vtkRenderWindow > TDijkstraObs; struct TBranch { double Length; TImage::PointType V1; TImage::PointType V2; bool operator<( const TBranch& other ) const { return( other.Length < this->Length ); } }; typedef std::set< TBranch > TBranches; // ------------------------------------------------------------------------- int main( int argc, char* argv[] ) { if( argc < 6 ) { std::cerr << "Usage: " << argv[ 0 ] << " input_image x y z output_image" << " visual_debug" << std::endl; return( 1 ); } // fi std::string input_image_fn = argv[ 1 ]; TImage::PointType seed_pnt; seed_pnt[ 0 ] = std::atof( argv[ 2 ] ); seed_pnt[ 1 ] = std::atof( argv[ 3 ] ); seed_pnt[ 2 ] = std::atof( argv[ 4 ] ); std::string output_image_fn = argv[ 5 ]; bool visual_debug = false; if( argc > 6 ) visual_debug = ( std::atoi( argv[ 6 ] ) == 1 ); // Read image TImageReader::Pointer input_image_reader = TImageReader::New( ); input_image_reader->SetFileName( input_image_fn ); try { input_image_reader->Update( ); } catch( itk::ExceptionObject& err ) { std::cerr << "Error caught: " << err << std::endl; return( 1 ); } // yrt TImage::ConstPointer input_image = input_image_reader->GetOutput( ); // Show image TVTKImage::Pointer vtk_image = TVTKImage::New( ); vtk_image->SetInput( input_image ); vtk_image->Update( ); TMPR view; view.SetBackground( 0.3, 0.2, 0.8 ); view.SetSize( 800, 800 ); view.SetImage( vtk_image->GetOutput( ) ); /* vtkSmartPointer< vtkImageMarchingCubes > mc = vtkSmartPointer< vtkImageMarchingCubes >::New( ); mc->SetInputData( vtk_image->GetOutput( ) ); mc->SetValue( 0, 1e-2 ); mc->Update( ); view.AddPolyData( mc->GetOutput( ), 1, 1, 1, 0.4 ); */ // Allow some interaction view.Render( ); view.Start( ); TImage::IndexType seed_idx; input_image->TransformPhysicalPointToIndex( seed_pnt, seed_idx ); std::cout << seed_idx << " " << seed_pnt << std::endl; seed_idx[ 0 ] = 256; seed_idx[ 1 ] = 313; seed_idx[ 2 ] = 381; // Extract paths TDijkstra::Pointer paths = TDijkstra::New( ); paths->AddSeed( seed_idx, TScalar( 0 ) ); paths->SetInput( input_image ); paths->SetNeighborhoodOrder( 2 ); if( visual_debug ) { // Configure observer TDijkstraObs::Pointer obs = TDijkstraObs::New( ); obs->SetRenderWindow( view.GetWindow( ) ); paths->AddObserver( itk::AnyEvent( ), obs ); paths->ThrowEventsOn( ); } else paths->ThrowEventsOff( ); std::clock_t start = std::clock( ); paths->Update( ); std::clock_t end = std::clock( ); double seconds = double( end - start ) / double( CLOCKS_PER_SEC ); std::cout << "Paths extraction time = " << seconds << std::endl; // Create polydata vtkSmartPointer< vtkPoints > points = vtkSmartPointer< vtkPoints >::New( ); vtkSmartPointer< vtkCellArray > cells = vtkSmartPointer< vtkCellArray >::New( ); vtkSmartPointer< vtkFloatArray > scalars = vtkSmartPointer< vtkFloatArray >::New( ); const TDijkstra::TMarkImage* marks = paths->GetOutputMarkImage( ); TDijkstra::TMark max_mark = paths->GetNumberOfBranches( ); const TDijkstra::TVertices& endpoints = paths->GetEndPoints( ); const TDijkstra::TVertices& bifurcations = paths->GetBifurcationPoints( ); const TDijkstra::TTree& tree = paths->GetFinalTree( ); TDijkstra::TVertices::const_iterator epIt = endpoints.begin( ); TDijkstra::TMarkImage::Pointer new_marks = TDijkstra::TMarkImage::New( ); new_marks->SetLargestPossibleRegion( marks->GetLargestPossibleRegion( ) ); new_marks->SetRequestedRegion( marks->GetRequestedRegion( ) ); new_marks->SetBufferedRegion( marks->GetBufferedRegion( ) ); new_marks->SetOrigin( marks->GetOrigin( ) ); new_marks->SetSpacing( marks->GetSpacing( ) ); new_marks->SetDirection( marks->GetDirection( ) ); new_marks->Allocate( ); new_marks->FillBuffer( 0 ); std::cout << max_mark << std::endl; std::cout << endpoints.size( ) << std::endl; TBranches branches; TBranch branch; for( ; epIt != endpoints.end( ); ++epIt ) { TDijkstra::TVertex idx = *epIt; TDijkstra::TTree::const_iterator tIt = tree.find( idx ); TImage::PointType pnt, prev; input_image->TransformIndexToPhysicalPoint( idx, pnt ); do { input_image->TransformIndexToPhysicalPoint( idx, pnt ); branch.V2 = pnt; points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] ); scalars->InsertNextTuple1( double( tIt->second.second ) ); new_marks->SetPixel( idx, tIt->second.second ); if( idx != *epIt ) { cells->InsertNextCell( 2 ); cells->InsertCellPoint( points->GetNumberOfPoints( ) - 2 ); cells->InsertCellPoint( points->GetNumberOfPoints( ) - 1 ); branch.Length += prev.EuclideanDistanceTo( pnt ); } // fi prev = pnt; idx = tIt->second.first; if( std::find( bifurcations.begin( ), bifurcations.end( ), idx ) != bifurcations.end( ) ) { branches.insert( branch ); prev = pnt; branch.V1 = pnt; branch.Length = double( 0 ); } tIt = tree.find( idx ); } while( idx != tIt->second.first ); } // rof /* TODO int i = 1; TImage::PointType ori = input_image->GetOrigin( ); std::cout << ori << std::endl; for( TBranches::const_iterator bIt = branches.begin( ); bIt != branches.end( ); ++bIt, ++i ) { TImage::PointType::VectorType v1 = bIt->V1 - ori; TImage::PointType::VectorType v2 = bIt->V2 - ori; std::cout << std::setiosflags( std::ios::fixed) << std::setprecision( 3 ) << i << "\t1.000\t" << bIt->Length << "\t" << v1[ 0 ] << "\t" << v1[ 1 ] << "\t" << v1[ 2 ] << "\t" << v2[ 0 ] << "\t" << v2[ 1 ] << "\t" << v2[ 2 ] << "\t" << ( v2 - v1 ).GetNorm( ) << std::endl; } // rof */ vtkSmartPointer< vtkPolyData > vtk_tree = vtkSmartPointer< vtkPolyData >::New( ); vtk_tree->SetPoints( points ); vtk_tree->SetLines( cells ); vtk_tree->GetPointData( )->SetScalars( scalars ); view.AddPolyData( vtk_tree ); view.Render( ); view.Start( ); vtkSmartPointer< vtkPolyDataWriter > writer = vtkSmartPointer< vtkPolyDataWriter >::New( ); writer->SetInputData( vtk_tree ); writer->SetFileName( output_image_fn.c_str( ) ); writer->Update( ); itk::ImageFileWriter< TDijkstra::TMarkImage >::Pointer marks_writer = itk::ImageFileWriter< TDijkstra::TMarkImage >::New( ); marks_writer->SetInput( new_marks ); marks_writer->SetFileName( "marks.mhd" ); marks_writer->Update( ); /* TODO TImageWriter::Pointer dijkstra_writer = TImageWriter::New( ); dijkstra_writer->SetInput( paths->GetOutput( ) ); dijkstra_writer->SetFileName( "dijkstra.mhd" ); dijkstra_writer->Update( ); */ return( 0 ); } // eof - $RCSfile$