9 #include <itkImageFileReader.h>
10 #include <itkMinimumMaximumImageCalculator.h>
11 #include <itkShiftScaleImageFilter.h>
13 #include <itkSignedMaurerDistanceMapImageFilter.h>
15 #include <itkImageFileWriter.h>
17 #include <fpa/Image/DijkstraWithEndPointDetection.h>
18 #include <fpa/Base/Functors/InvertCostFunction.h>
20 #include <fpa/IO/MinimumSpanningTreeWriter.h>
21 #include <fpa/IO/UniqueValuesContainerWriter.h>
22 #include <fpa/IO/MatrixValuesContainerWriter.h>
24 // -------------------------------------------------------------------------
25 const unsigned int Dim = 3;
26 typedef unsigned char TPixel;
27 typedef float TScalar;
29 typedef itk::Image< TPixel, Dim > TImage;
30 typedef itk::Image< TScalar, Dim > TScalarImage;
32 // -------------------------------------------------------------------------
34 void ReadImage( typename I::Pointer& image, const std::string& filename );
37 void SaveImage( const I* image, const std::string& filename );
39 template< class I, class O >
41 const typename I::Pointer& input, typename O::Pointer& output
44 // -------------------------------------------------------------------------
45 int main( int argc, char* argv[] )
50 << "Usage: " << argv[ 0 ] << std::endl
51 << " input_image" << std::endl
52 << " seed_x seed_y seed_z" << std::endl
53 << " output_distancemap" << std::endl
54 << " output_costmap" << std::endl
55 << " output_labels" << std::endl
56 << " output_minimum_spanning_tree" << std::endl
57 << " output_endpoints" << std::endl
58 << " output_bifurcations" << std::endl
59 << " output_branches" << std::endl
64 std::string input_image_fn = argv[ 1 ];
65 double seed_x = std::atof( argv[ 2 ] );
66 double seed_y = std::atof( argv[ 3 ] );
67 double seed_z = std::atof( argv[ 4 ] );
68 std::string distancemap_fn = argv[ 5 ];
69 std::string output_costmap_fn = argv[ 6 ];
70 std::string output_labels_fn = argv[ 7 ];
71 std::string mst_output_fn = argv[ 8 ];
72 std::string endpoints_output_fn = argv[ 9 ];
73 std::string bifurcations_output_fn = argv[ 10 ];
74 std::string branches_output_fn = argv[ 11 ];
77 TImage::Pointer input_image;
80 ReadImage< TImage >( input_image, input_image_fn );
82 catch( itk::ExceptionObject& err )
85 << "Error caught while reading \""
86 << input_image_fn << "\": " << err
94 TImage::PointType pnt;
95 TImage::IndexType seed;
99 input_image->TransformPhysicalPointToIndex( pnt, seed );
101 // Compute squared distance map
102 TScalarImage::Pointer dmap;
103 DistanceMap< TImage, TScalarImage >( input_image, dmap );
105 // Prepare cost conversion function
106 typedef fpa::Base::Functors::InvertCostFunction< TScalar > TFunction;
107 TFunction::Pointer function = TFunction::New( );
109 // Prepare Dijkstra filter
110 typedef fpa::Image::DijkstraWithEndPointDetection< TScalarImage, TScalarImage > TFilter;
111 TFilter::Pointer filter = TFilter::New( );
112 filter->SetInput( dmap );
113 filter->SetConversionFunction( function );
114 filter->SetNeighborhoodOrder( 2 );
115 filter->StopAtOneFrontOff( );
116 filter->AddSeed( seed, TScalar( 0 ) );
119 std::time_t start, end;
124 << "Extraction time = "
125 << std::difftime( end, start )
126 << " s." << std::endl;
129 const TFilter::TOutputImage* accumulated_costs = filter->GetOutput( );
130 const TFilter::TLabelImage* labeled_image = filter->GetLabelImage( );
131 const TFilter::TMinimumSpanningTree* mst = filter->GetMinimumSpanningTree( );
132 const TFilter::TUniqueVertices* endpoints = filter->GetEndPoints( );
133 const TFilter::TUniqueVertices* bifurcations = filter->GetBifurcations( );
134 const TFilter::TBranches* branches = filter->GetBranches( );
135 unsigned long nBranches = filter->GetNumberOfBranches( );
138 SaveImage( dmap.GetPointer( ), distancemap_fn );
139 SaveImage( accumulated_costs, output_costmap_fn );
140 SaveImage( labeled_image, output_labels_fn );
142 fpa::IO::MinimumSpanningTreeWriter< TFilter::TMinimumSpanningTree >::Pointer
144 fpa::IO::MinimumSpanningTreeWriter< TFilter::TMinimumSpanningTree >::New( );
145 mst_writer->SetInput( mst );
146 mst_writer->SetFileName( mst_output_fn );
147 mst_writer->Update( );
149 fpa::IO::UniqueValuesContainerWriter< TFilter::TUniqueVertices >::Pointer
151 fpa::IO::UniqueValuesContainerWriter< TFilter::TUniqueVertices >::New( );
152 endpoints_writer->SetInput( endpoints );
153 endpoints_writer->SetFileName( endpoints_output_fn );
154 endpoints_writer->Update( );
156 fpa::IO::UniqueValuesContainerWriter< TFilter::TUniqueVertices >::Pointer
157 bifurcations_writer =
158 fpa::IO::UniqueValuesContainerWriter< TFilter::TUniqueVertices >::New( );
159 bifurcations_writer->SetInput( bifurcations );
160 bifurcations_writer->SetFileName( bifurcations_output_fn );
161 bifurcations_writer->Update( );
163 fpa::IO::MatrixValuesContainerWriter< TFilter::TBranches >::Pointer
165 fpa::IO::MatrixValuesContainerWriter< TFilter::TBranches >::New( );
166 branches_writer->SetInput( branches );
167 branches_writer->SetFileName( branches_output_fn );
168 branches_writer->Update( );
173 // -------------------------------------------------------------------------
175 void ReadImage( typename I::Pointer& image, const std::string& filename )
177 typename itk::ImageFileReader< I >::Pointer reader =
178 itk::ImageFileReader< I >::New( );
179 reader->SetFileName( filename );
182 typename itk::MinimumMaximumImageCalculator< I >::Pointer minmax =
183 itk::MinimumMaximumImageCalculator< I >::New( );
184 minmax->SetImage( reader->GetOutput( ) );
186 double vmin = double( minmax->GetMinimum( ) );
187 double vmax = double( minmax->GetMaximum( ) );
189 typename itk::ShiftScaleImageFilter< I, I >::Pointer shift =
190 itk::ShiftScaleImageFilter< I, I >::New( );
191 shift->SetInput( reader->GetOutput( ) );
192 shift->SetScale( vmax - vmin );
193 shift->SetShift( vmin / ( vmax - vmin ) );
196 image = shift->GetOutput( );
197 image->DisconnectPipeline( );
200 // -------------------------------------------------------------------------
202 void SaveImage( const I* image, const std::string& filename )
204 typename itk::ImageFileWriter< I >::Pointer writer =
205 itk::ImageFileWriter< I >::New( );
206 writer->SetInput( image );
207 writer->SetFileName( filename );
212 catch( itk::ExceptionObject& err )
215 << "Error saving \"" << filename << "\": " << err
221 // -------------------------------------------------------------------------
222 template< class I, class O >
224 const typename I::Pointer& input, typename O::Pointer& output
227 typename itk::SignedMaurerDistanceMapImageFilter< I, O >::Pointer dmap =
228 itk::SignedMaurerDistanceMapImageFilter< I, O >::New( );
229 dmap->SetInput( input );
230 dmap->SetBackgroundValue( ( typename I::PixelType )( 0 ) );
231 dmap->InsideIsPositiveOn( );
232 dmap->SquaredDistanceOn( );
233 dmap->UseImageSpacingOn( );
235 std::time_t start, end;
240 << "Distance map time = "
241 << std::difftime( end, start )
242 << " s." << std::endl;
244 output = dmap->GetOutput( );
245 output->DisconnectPipeline( );