5 #include <itkConstNeighborhoodIterator.h>
6 #include <itkDanielssonDistanceMapImageFilter.h>
8 #include <itkImageFileReader.h>
9 #include <itkImageFileWriter.h>
10 #include <itkImageToVTKImageFilter.h>
12 #include <vtkImageMarchingCubes.h>
14 #include <fpa/Image/RegionGrowWithMultipleThresholds.h>
15 #include <fpa/Image/DijkstraWithSphereBacktracking.h>
16 #include <fpa/VTK/ImageMPR.h>
17 #include <fpa/VTK/Image3DObserver.h>
19 // -------------------------------------------------------------------------
20 const unsigned int Dim = 3;
22 typedef double TScalar;
23 typedef itk::Image< TPixel, Dim > TImage;
24 typedef itk::Image< TScalar, Dim > TDistanceMap;
25 typedef itk::ImageToVTKImageFilter< TImage > TVTKImage;
26 typedef itk::ImageToVTKImageFilter< TDistanceMap > TVTKDistanceMap;
28 typedef itk::ImageFileReader< TImage > TImageReader;
29 typedef itk::ImageFileWriter< TImage > TImageWriter;
30 typedef itk::ImageFileWriter< TDistanceMap > TDistanceMapWriter;
31 typedef fpa::Image::RegionGrowWithMultipleThresholds< TImage > TSegmentor;
33 itk::DanielssonDistanceMapImageFilter< TImage, TDistanceMap >
36 fpa::Image::DijkstraWithSphereBacktracking< TDistanceMap, TScalar >
39 typedef fpa::VTK::ImageMPR TMPR;
40 typedef fpa::VTK::Image3DObserver< TSegmentor, vtkRenderWindow > TSegmentorObs;
41 typedef fpa::VTK::Image3DObserver< TDijkstra, vtkRenderWindow > TDijkstraObs;
43 // -------------------------------------------------------------------------
44 int main( int argc, char* argv[] )
49 << "Usage: " << argv[ 0 ]
50 << " input_image thr_0 thr_1 step"
51 << " output_segmentation output_distancemap"
57 std::string input_image_fn = argv[ 1 ];
58 TPixel thr_0 = TPixel( std::atof( argv[ 2 ] ) );
59 TPixel thr_1 = TPixel( std::atof( argv[ 3 ] ) );
60 unsigned int step = std::atoi( argv[ 4 ] );
61 std::string output_segmentation_fn = argv[ 5 ];
62 std::string output_distancemap_fn = argv[ 6 ];
63 bool visual_debug = false;
65 visual_debug = ( std::atoi( argv[ 7 ] ) == 1 );
68 TImageReader::Pointer input_image_reader = TImageReader::New( );
69 input_image_reader->SetFileName( input_image_fn );
72 input_image_reader->Update( );
74 catch( itk::ExceptionObject& err )
76 std::cerr << "Error caught: " << err << std::endl;
80 TImage::ConstPointer input_image = input_image_reader->GetOutput( );
83 TVTKImage::Pointer vtk_image = TVTKImage::New( );
84 vtk_image->SetInput( input_image );
88 view.SetBackground( 0.3, 0.2, 0.8 );
89 view.SetSize( 800, 800 );
90 view.SetImage( vtk_image->GetOutput( ) );
92 // Wait for a seed to be given
93 while( view.GetNumberOfSeeds( ) == 0 )
98 view.GetSeed( 0, seed );
99 TImage::PointType seed_pnt;
100 seed_pnt[ 0 ] = seed[ 0 ];
101 seed_pnt[ 1 ] = seed[ 1 ];
102 seed_pnt[ 2 ] = seed[ 2 ];
103 TImage::IndexType seed_idx;
104 input_image->TransformPhysicalPointToIndex( seed_pnt, seed_idx );
106 // Segment input image
107 TSegmentor::Pointer segmentor = TSegmentor::New( );
108 segmentor->AddThresholds( thr_0, thr_1, step );
109 segmentor->AddSeed( seed_idx, 0 );
110 segmentor->SetInput( input_image );
111 segmentor->SetNeighborhoodOrder( 1 );
112 segmentor->SetDifferenceThreshold( double( 3 ) );
113 segmentor->SetInsideValue( TPixel( 0 ) ); // WARNING: This is to optimize
114 segmentor->SetOutsideValue( TPixel( 1 ) ); // distance map calculation
117 // Configure observer
118 TSegmentorObs::Pointer obs = TSegmentorObs::New( );
119 obs->SetRenderWindow( view.GetWindow( ) );
120 segmentor->AddObserver( itk::AnyEvent( ), obs );
121 segmentor->ThrowEventsOn( );
124 segmentor->ThrowEventsOff( );
125 std::clock_t start = std::clock( );
126 segmentor->Update( );
127 std::clock_t end = std::clock( );
128 double seconds = double( end - start ) / double( CLOCKS_PER_SEC );
129 std::cout << "Segmentation time = " << seconds << std::endl;
131 // Extract distance map
132 TDistanceFilter::Pointer distanceMap = TDistanceFilter::New( );
133 distanceMap->SetInput( segmentor->GetOutput( ) );
134 distanceMap->InputIsBinaryOn( );
135 distanceMap->SquaredDistanceOn( );
136 start = std::clock( );
137 distanceMap->Update( );
139 seconds = double( end - start ) / double( CLOCKS_PER_SEC );
140 std::cout << "Distance map time = " << seconds << std::endl;
142 TVTKDistanceMap::Pointer vtk_distanceMap = TVTKDistanceMap::New( );
143 vtk_distanceMap->SetInput( distanceMap->GetOutput( ) );
144 vtk_distanceMap->Update( );
146 vtkSmartPointer< vtkImageMarchingCubes > mc =
147 vtkSmartPointer< vtkImageMarchingCubes >::New( );
148 mc->SetInputData( vtk_distanceMap->GetOutput( ) );
149 mc->SetValue( 0, 1e-2 );
151 view.AddPolyData( mc->GetOutput( ), 1, 1, 1, 0.4 );
155 TDijkstra::Pointer paths = TDijkstra::New( );
156 paths->AddSeed( segmentor->GetSeed( 0 ), TScalar( 0 ) );
157 paths->SetInput( distanceMap->GetOutput( ) );
158 paths->SetNeighborhoodOrder( 1 );
162 // Configure observer
163 TDijkstraObs::Pointer obs = TDijkstraObs::New( );
164 obs->SetRenderWindow( view.GetWindow( ) );
165 paths->AddObserver( itk::AnyEvent( ), obs );
166 paths->ThrowEventsOn( );
169 paths->ThrowEventsOff( );
170 start = std::clock( );
173 seconds = double( end - start ) / double( CLOCKS_PER_SEC );
174 std::cout << "Paths extraction time = " << seconds << std::endl;
176 std::cout << "Final seed: " << paths->GetSeed( 0 ) << std::endl;
179 vtkSmartPointer< vtkPoints > points =
180 vtkSmartPointer< vtkPoints >::New( );
181 vtkSmartPointer< vtkCellArray > cells =
182 vtkSmartPointer< vtkCellArray >::New( );
183 vtkSmartPointer< vtkFloatArray > scalars =
184 vtkSmartPointer< vtkFloatArray >::New( );
186 const TDijkstra::TVertices& endpoints = paths->GetEndPoints( );
187 const TDijkstra::TTree& tree = paths->GetFinalTree( );
188 TDijkstra::TVertices::const_iterator epIt = endpoints.begin( );
189 for( unsigned int epId = 0; epIt != endpoints.end( ); ++epIt, ++epId )
191 double pd = double( epId ) / double( endpoints.size( ) - 1 );
193 TDijkstra::TVertex idx = *epIt;
196 TImage::PointType pnt;
197 input_image->TransformIndexToPhysicalPoint( idx, pnt );
199 points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] );
200 scalars->InsertNextTuple1( pd );
203 cells->InsertNextCell( 2 );
204 cells->InsertCellPoint( points->GetNumberOfPoints( ) - 2 );
205 cells->InsertCellPoint( points->GetNumberOfPoints( ) - 1 );
208 idx = tree.find( idx )->second;
210 } while( idx != tree.find( idx )->second );
214 vtkSmartPointer< vtkPolyData > vtk_tree =
215 vtkSmartPointer< vtkPolyData >::New( );
216 vtk_tree->SetPoints( points );
217 vtk_tree->SetLines( cells );
218 vtk_tree->GetPointData( )->SetScalars( scalars );
220 view.AddPolyData( vtk_tree );
225 TDistanceMapWriter::Pointer distancemap_writer =
226 TDistanceMapWriter::New( );
227 distancemap_writer->SetInput( distanceMap->GetOutput( ) );
228 distancemap_writer->SetFileName( output_distancemap_fn );
229 distancemap_writer->Update( );
231 TImageWriter::Pointer segmentation_writer =
232 TImageWriter::New( );
233 segmentation_writer->SetInput( segmentor->GetOutput( ) );
234 segmentation_writer->SetFileName( output_segmentation_fn );
235 segmentation_writer->Update( );
240 TVTKImage::Pointer output_image_vtk = TVTKImage::New( );
241 output_image_vtk->SetInput( segmentor->GetOutput( ) );
242 output_image_vtk->Update( );
244 vtkSmartPointer< vtkImageMarchingCubes > mc =
245 vtkSmartPointer< vtkImageMarchingCubes >::New( );
246 mc->SetInputData( output_image_vtk->GetOutput( ) );
249 double( segmentor->GetInsideValue( ) ) * double( 0.95 )
253 // Let some interaction and close program
254 view.AddPolyData( mc->GetOutput( ), 0.1, 0.6, 0.8, 0.5 );
257 // Write resulting image
258 TImageWriter::Pointer output_image_writer = TImageWriter::New( );
259 output_image_writer->SetInput( segmentor->GetOutput( ) );
260 output_image_writer->SetFileName( output_image_fn );
263 output_image_writer->Update( );
265 catch( itk::ExceptionObject& err )
267 std::cerr << "Error caught: " << err << std::endl;