]> Creatis software - FrontAlgorithms.git/blob - lib/fpa/Image/DijkstraWithEndPointDetection.hxx
cb417f027092de357d1353ff18b4cd367f860729
[FrontAlgorithms.git] / lib / fpa / Image / DijkstraWithEndPointDetection.hxx
1 #ifndef __FPA__IMAGE__DIJKSTRAWITHENDPOINTDETECTION__HXX__
2 #define __FPA__IMAGE__DIJKSTRAWITHENDPOINTDETECTION__HXX__
3
4 #include <vector>
5 #include <set>
6 #include <itkImageRegionConstIteratorWithIndex.h>
7 #include <itkImageRegionIteratorWithIndex.h>
8
9 // -------------------------------------------------------------------------
10 template< class I, class O >
11 typename fpa::Image::DijkstraWithEndPointDetection< I, O >::
12 TLabelImage* fpa::Image::DijkstraWithEndPointDetection< I, O >::
13 GetLabelImage( )
14 {
15   return(
16     dynamic_cast< TLabelImage* >(
17       this->itk::ProcessObject::GetOutput( this->m_LabelImageIndex )
18       )
19     );
20 }
21
22 // -------------------------------------------------------------------------
23 template< class I, class O >
24 const typename fpa::Image::DijkstraWithEndPointDetection< I, O >::
25 TLabelImage* fpa::Image::DijkstraWithEndPointDetection< I, O >::
26 GetLabelImage( ) const
27 {
28   return(
29     dynamic_cast< const TLabelImage* >(
30       this->itk::ProcessObject::GetOutput( this->m_LabelImageIndex )
31       )
32     );
33 }
34
35 // -------------------------------------------------------------------------
36 template< class I, class O >
37 void fpa::Image::DijkstraWithEndPointDetection< I, O >::
38 GraftLabelImage( itk::DataObject* obj )
39 {
40   TLabelImage* lbl =
41     dynamic_cast< TLabelImage* >(
42       this->itk::ProcessObject::GetOutput( this->m_LabelImageIndex )
43       );
44   if( lbl != NULL )
45     this->GraftNthOutput( this->m_LabelImageIndex, lbl );
46 }
47
48
49
50
51 // -------------------------------------------------------------------------
52 template< class I, class O >
53 typename fpa::Image::DijkstraWithEndPointDetection< I, O >::
54 TUniqueVertices* fpa::Image::DijkstraWithEndPointDetection< I, O >::
55 GetEndPoints( )
56 {
57   return(
58     dynamic_cast< TUniqueVertices* >(
59       this->itk::ProcessObject::GetOutput( this->m_EndPointsIndex )
60       )
61     );
62 }
63
64 // -------------------------------------------------------------------------
65 template< class I, class O >
66 const typename fpa::Image::DijkstraWithEndPointDetection< I, O >::
67 TUniqueVertices* fpa::Image::DijkstraWithEndPointDetection< I, O >::
68 GetEndPoints( ) const
69 {
70   return(
71     dynamic_cast< const TUniqueVertices* >(
72       this->itk::ProcessObject::GetOutput( this->m_EndPointsIndex )
73       )
74     );
75 }
76
77 // -------------------------------------------------------------------------
78 template< class I, class O >
79 void fpa::Image::DijkstraWithEndPointDetection< I, O >::
80 GraftEndPoints( itk::DataObject* obj )
81 {
82   TUniqueVertices* lbl =
83     dynamic_cast< TUniqueVertices* >(
84       this->itk::ProcessObject::GetOutput( this->m_EndPointsIndex )
85       );
86   if( lbl != NULL )
87     this->GraftNthOutput( this->m_EndPointsIndex, lbl );
88 }
89
90 // -------------------------------------------------------------------------
91 template< class I, class O >
92 typename fpa::Image::DijkstraWithEndPointDetection< I, O >::
93 TUniqueVertices* fpa::Image::DijkstraWithEndPointDetection< I, O >::
94 GetBifurcations( )
95 {
96   return(
97     dynamic_cast< TUniqueVertices* >(
98       this->itk::ProcessObject::GetOutput( this->m_BifurcationsIndex )
99       )
100     );
101 }
102
103 // -------------------------------------------------------------------------
104 template< class I, class O >
105 const typename fpa::Image::DijkstraWithEndPointDetection< I, O >::
106 TUniqueVertices* fpa::Image::DijkstraWithEndPointDetection< I, O >::
107 GetBifurcations( ) const
108 {
109   return(
110     dynamic_cast< const TUniqueVertices* >(
111       this->itk::ProcessObject::GetOutput( this->m_BifurcationsIndex )
112       )
113     );
114 }
115
116 // -------------------------------------------------------------------------
117 template< class I, class O >
118 void fpa::Image::DijkstraWithEndPointDetection< I, O >::
119 GraftBifurcations( itk::DataObject* obj )
120 {
121   TUniqueVertices* lbl =
122     dynamic_cast< TUniqueVertices* >(
123       this->itk::ProcessObject::GetOutput( this->m_BifurcationsIndex )
124       );
125   if( lbl != NULL )
126     this->GraftNthOutput( this->m_BifurcationsIndex, lbl );
127 }
128
129
130 // -------------------------------------------------------------------------
131 template< class I, class O >
132 typename fpa::Image::DijkstraWithEndPointDetection< I, O >::
133 TBranches* fpa::Image::DijkstraWithEndPointDetection< I, O >::
134 GetBranches( )
135 {
136   return(
137     dynamic_cast< TBranches* >(
138       this->itk::ProcessObject::GetOutput( this->m_BranchesIndex )
139       )
140     );
141 }
142
143 // -------------------------------------------------------------------------
144 template< class I, class O >
145 const typename fpa::Image::DijkstraWithEndPointDetection< I, O >::
146 TBranches* fpa::Image::DijkstraWithEndPointDetection< I, O >::
147 GetBranches( ) const
148 {
149   return(
150     dynamic_cast< const TBranches* >(
151       this->itk::ProcessObject::GetOutput( this->m_BranchesIndex )
152       )
153     );
154 }
155
156 // -------------------------------------------------------------------------
157 template< class I, class O >
158 void fpa::Image::DijkstraWithEndPointDetection< I, O >::
159 GraftBranches( itk::DataObject* obj )
160 {
161   TBranches* lbl =
162     dynamic_cast< TBranches* >(
163       this->itk::ProcessObject::GetOutput( this->m_BranchesIndex )
164       );
165   if( lbl != NULL )
166     this->GraftNthOutput( this->m_BranchesIndex, lbl );
167 }
168
169 // -------------------------------------------------------------------------
170 template< class I, class O >
171 fpa::Image::DijkstraWithEndPointDetection< I, O >::
172 DijkstraWithEndPointDetection( )
173   : Superclass( ),
174     m_CorrectSeeds( true ),
175     m_CorrectEndPoints( true ),
176     m_SafetyNeighborhoodSize( 3 )
177 {
178   this->m_LabelImageIndex = this->GetNumberOfRequiredOutputs( );
179   this->m_EndPointsIndex = this->m_LabelImageIndex + 1;
180   this->m_BifurcationsIndex = this->m_LabelImageIndex + 2;
181   this->m_BranchesIndex = this->m_LabelImageIndex + 3;
182   this->SetNumberOfRequiredOutputs( this->m_LabelImageIndex + 4 );
183   this->itk::ProcessObject::SetNthOutput(
184     this->m_LabelImageIndex, TLabelImage::New( )
185     );
186   this->itk::ProcessObject::SetNthOutput(
187     this->m_EndPointsIndex, TUniqueVertices::New( )
188     );
189   this->itk::ProcessObject::SetNthOutput(
190     this->m_BifurcationsIndex, TUniqueVertices::New( )
191     );
192   this->itk::ProcessObject::SetNthOutput(
193     this->m_BranchesIndex, TBranches::New( )
194     );
195 }
196
197 // -------------------------------------------------------------------------
198 template< class I, class O >
199 fpa::Image::DijkstraWithEndPointDetection< I, O >::
200 ~DijkstraWithEndPointDetection( )
201 {
202 }
203
204 // -------------------------------------------------------------------------
205 template< class I, class O >
206 void fpa::Image::DijkstraWithEndPointDetection< I, O >::
207 _BeforeGenerateData( )
208 {
209   if( this->m_CorrectSeeds )
210   {
211     const I* input = this->GetInput( );
212     typename I::SpacingType spac = input->GetSpacing( );
213     double max_spac = double( spac[ 0 ] );
214     for( unsigned int d = 1; d < I::ImageDimension; ++d )
215       max_spac =
216         ( double( spac[ d ] ) > max_spac )? double( spac[ d ] ): max_spac;
217     max_spac *= double( 3 );
218
219     // Correct seeds
220     for( unsigned int s = 0; s < this->m_SeedVertices.size( ); ++s )
221     {
222       TVertex seed = this->m_SeedVertices[ s ];
223       _TNode n = this->m_Seeds[ seed ];
224       _TRegion region = this->_Region( seed, max_spac );
225       itk::ImageRegionConstIteratorWithIndex< I > iIt( input, region );
226
227       iIt.GoToBegin( );
228       _TPixel max_value = iIt.Get( );
229       for( ++iIt; !iIt.IsAtEnd( ); ++iIt )
230       {
231         if( iIt.Get( ) > max_value )
232         {
233           this->m_SeedVertices[ s ] = iIt.GetIndex( );
234           max_value = iIt.Get( );
235
236         } // fi
237
238       } // rof
239       this->m_Seeds.erase( seed );
240       n.Parent = this->m_SeedVertices[ s ];
241       this->m_Seeds[ this->m_SeedVertices[ s ] ] = n;
242
243     } // rof
244
245   } // fi
246
247   // End initialization
248   this->Superclass::_BeforeGenerateData( );
249   this->m_Candidates.clear( );
250 }
251
252 // -------------------------------------------------------------------------
253 template< class I, class O >
254 void fpa::Image::DijkstraWithEndPointDetection< I, O >::
255 _AfterGenerateData( )
256 {
257   // Finish base algorithm
258   this->Superclass::_AfterGenerateData( );
259
260   // Check if backtracking has any sense
261   if( this->m_Candidates.size( ) == 0 )
262     return;
263   this->InvokeEvent( TEndEvent( ) );
264   this->InvokeEvent( TStartBacktrackingEvent( ) );
265
266   // Detect endpoints and bifurcations
267   this->_EndPointsAndBifurcations( );
268
269   // Find branches
270   this->_FindBranches( );
271
272   // Label pixels and branches
273   this->_LabelAll( );
274 }
275
276 // -------------------------------------------------------------------------
277 template< class I, class O >
278 void fpa::Image::DijkstraWithEndPointDetection< I, O >::
279 _SetResult( const TVertex& v, const _TNode& n )
280 {
281   this->Superclass::_SetResult( v, n );
282   this->m_Candidates.insert( _TCandidate( n.Result, v ) );
283 }
284
285 // -------------------------------------------------------------------------
286 template< class I, class O >
287 void fpa::Image::DijkstraWithEndPointDetection< I, O >::
288 _EndPointsAndBifurcations( )
289 {
290   // Prepare backtracking objects
291   TUniqueVertices* endpoints = this->GetEndPoints( );
292   TUniqueVertices* bifurcations = this->GetBifurcations( );
293   endpoints->Clear( );
294   bifurcations->Clear( );
295
296   // Get some input values
297   TVertex seed = this->GetSeed( 0 );
298   const I* input = this->GetInput( );
299   const TMinimumSpanningTree* mst = this->GetMinimumSpanningTree( );
300
301   // Prepare a pixel marks structure
302   typedef std::map< TVertex, bool, TVertexCompare > _TPixelMarks;
303   _TPixelMarks pixel_marks;
304
305   // Object to hold tree-nodes marks
306   typedef std::set< TVertex, TVertexCompare > _TTreeMarks;
307   _TTreeMarks tree_marks;
308
309   // Iterate over the candidates, starting from the candidates that
310   // are near thin branches (high accumulated cost)
311   typename _TCandidates::const_reverse_iterator cIt =
312     this->m_Candidates.rbegin( );
313   for( ; cIt != this->m_Candidates.rend( ); ++cIt )
314   {
315     // If pixel has already been visited, pass
316     TVertex v = cIt->second;
317     if( pixel_marks[ v ] )
318       continue;
319
320     // Correct it to nearest start candidate (high distance value)
321     double vr = std::sqrt( double( input->GetPixel( v ) ) );
322     if( this->m_CorrectEndPoints )
323       v = this->_MaxInRegion( input, v, vr * double( 1.5 ) );
324
325     // Now, check for real marking conditions
326     //   1. Has it been visited by dijkstra?
327     if( this->_Node( v ).Label == Self::FarLabel )
328       continue;
329     //   2. Is it already marked?
330     if( pixel_marks[ v ] )
331       continue;
332     //   3. Is it already an endpoint?
333     if( endpoints->Find( v ) )
334       continue;
335     //   4. Ok, it is completely new!
336     endpoints->Insert( v );
337
338     // Get the path all the way to global seed
339     TVertices path;
340     mst->GetPath( path, v, seed );
341
342     // Backtracking to find endpoints and bifurcations
343     bool adding_new_points = true;
344     typename TVertices::const_iterator pIt = path.begin( );
345     for( ; pIt != path.end( ) && adding_new_points; ++pIt )
346     {
347       this->InvokeEvent( TBacktrackingEvent( *pIt, 1 ) );
348       if( tree_marks.find( *pIt ) == tree_marks.end( ) )
349       {
350         // Mark current point as a tree point
351         tree_marks.insert( *pIt );
352
353         // Mark a region around current point as visited
354         vr = std::sqrt( double( input->GetPixel( *pIt ) ) );
355         _TRegion region = this->_Region( *pIt, vr );
356         if( region.GetNumberOfPixels( ) > 0 )
357         {
358           itk::ImageRegionConstIteratorWithIndex< I > iIt( input, region );
359           for( iIt.GoToBegin( ); !iIt.IsAtEnd( ); ++iIt )
360             pixel_marks[ iIt.GetIndex( ) ] = true;
361         }
362         else
363           pixel_marks[ *pIt ] = true;
364       }
365       else
366       {
367         // A bifurcation point has been reached!
368         if( *pIt != seed )
369         {
370           bifurcations->Insert( *pIt );
371           adding_new_points = false;
372
373         } // fi
374
375       } // fi
376
377     } // rof
378     this->InvokeEvent( TEndBacktrackingEvent( ) );
379
380   } // rof
381 }
382
383 // -------------------------------------------------------------------------
384 template< class I, class O >
385 void fpa::Image::DijkstraWithEndPointDetection< I, O >::
386 _FindBranches( )
387 {
388   // Configure and obtain inputs
389   TVertex seed = this->GetSeed( 0 );
390   const TMinimumSpanningTree* mst = this->GetMinimumSpanningTree( );
391   const TUniqueVertices* endpoints = this->GetEndPoints( );
392   const TUniqueVertices* bifurcations = this->GetBifurcations( );
393   TBranches* branches = this->GetBranches( );
394   branches->Clear( );
395
396   // Reconstruct pixels
397   typename TUniqueVertices::ConstIterator eIt = endpoints->Begin( );
398   for( ; eIt != endpoints->End( ); ++eIt )
399   {
400     // Get the path all the way to global seed
401     TVertices path;
402     mst->GetPath( path, *eIt, seed );
403
404     TVertex start_vertex = *eIt;
405     typename TVertices::const_iterator pIt = path.begin( );
406     for( ; pIt != path.end( ); ++pIt )
407     {
408       if( bifurcations->Find( *pIt ) )
409       {
410         branches->SetValue( start_vertex, *pIt, 1 );
411         start_vertex = *pIt;
412
413       } // fi
414
415     } // rof
416
417     // Finish with branches to global seed
418     branches->SetValue( start_vertex, seed, 1 );
419
420   } // rof
421 }
422
423 // -------------------------------------------------------------------------
424 template< class I, class O >
425 void fpa::Image::DijkstraWithEndPointDetection< I, O >::
426 _LabelAll( )
427 {
428   // Configure and obtain inputs
429   const I* input = this->GetInput( );
430   const TMinimumSpanningTree* mst = this->GetMinimumSpanningTree( );
431   const TUniqueVertices* bifurcations = this->GetBifurcations( );
432   TBranches* branches = this->GetBranches( );
433   TLabelImage* label = this->GetLabelImage( );
434   label->FillBuffer( 0 );
435
436   // Label branches
437   typename TBranches::Iterator bIt = branches->Begin( );
438   TLabel actual_label = 0;
439   for( ; bIt != branches->End( ); ++bIt )
440   {
441     typename TBranches::RowIterator brIt = branches->Begin( bIt );
442     for( ; brIt != branches->End( bIt ); ++brIt )
443     {
444       actual_label++;
445       brIt->second = actual_label;
446
447       TVertices path;
448       mst->GetPath( path, bIt->first, brIt->first );
449       typename TVertices::const_iterator pIt = path.begin( );
450       for( ; pIt != path.end( ); ++pIt )
451       {
452         double d = std::sqrt( double( input->GetPixel( *pIt ) ) );
453         _TRegion region = this->_Region( *pIt, d );
454         itk::ImageRegionConstIteratorWithIndex< I > iIt( input, region );
455         itk::ImageRegionIteratorWithIndex< TLabelImage > lIt( label, region );
456         iIt.GoToBegin( );
457         lIt.GoToBegin( );
458         for( ; !iIt.IsAtEnd( ); ++iIt, ++lIt )
459         {
460           // Mask real input image
461           if(
462             !( iIt.Get( ) < ( typename I::PixelType )( 0 ) ) &&
463             lIt.Get( ) == TLabel( 0 )
464             )
465             lIt.Set( actual_label );
466           
467         } // rof
468
469       } // rof
470
471     } // rof
472
473   } // rof
474   this->m_NumberOfBranches = actual_label;
475
476   // Label bifurcations
477   typename TUniqueVertices::ConstIterator bifIt =
478     bifurcations->Begin( );
479   for( ; bifIt != bifurcations->End( ); ++bifIt )
480   {
481     actual_label++;
482     double d = std::sqrt( double( input->GetPixel( *bifIt ) ) );
483     _TRegion region = this->_Region( *bifIt, d * 1.5 );
484     itk::ImageRegionConstIteratorWithIndex< I > iIt( input, region );
485     itk::ImageRegionIteratorWithIndex< TLabelImage > lIt( label, region );
486     iIt.GoToBegin( );
487     lIt.GoToBegin( );
488     for( ; !iIt.IsAtEnd( ); ++iIt, ++lIt )
489     {
490       // Mask real input image
491       if( !( iIt.Get( ) < ( typename I::PixelType )( 0 ) ) )
492         lIt.Set( actual_label );
493
494     } // rof
495
496   } // rof
497 }
498
499 // -------------------------------------------------------------------------
500 template< class I, class O >
501 typename fpa::Image::DijkstraWithEndPointDetection< I, O >::
502 _TRegion fpa::Image::DijkstraWithEndPointDetection< I, O >::
503 _Region( const TVertex& c, const double& r )
504 {
505   typename I::ConstPointer input = this->GetInput( );
506   typename I::SpacingType spac = input->GetSpacing( );
507   _TRegion region = input->GetLargestPossibleRegion( );
508   typename I::IndexType idx0 = region.GetIndex( );
509   typename I::IndexType idx1 = idx0 + region.GetSize( );
510
511   // Compute region size and index
512   typename I::IndexType i0, i1;
513   _TSize size;
514   for( unsigned int d = 0; d < I::ImageDimension; ++d )
515   {
516     // NOTE: 3 is a minimum neighborhood size
517     long s =
518       long( std::ceil( r / double( spac[ d ] ) ) ) +
519       long( this->m_SafetyNeighborhoodSize );
520     i0[ d ] = c[ d ] - s;
521     i1[ d ] = c[ d ] + s;
522
523     if( i0[ d ] < idx0[ d ] ) i0[ d ] = idx0[ d ];
524     if( i1[ d ] < idx0[ d ] ) i1[ d ] = idx0[ d ];
525     if( i0[ d ] > idx1[ d ] ) i0[ d ] = idx1[ d ];
526     if( i1[ d ] > idx1[ d ] ) i1[ d ] = idx1[ d ];
527     size[ d ] = i1[ d ] - i0[ d ];
528
529   }  // rof
530
531   // Prepare region and return it
532   region.SetIndex( i0 );
533   region.SetSize( size );
534
535   return( region );
536 }
537
538 // -------------------------------------------------------------------------
539 template< class I, class O >
540 template< class _T > 
541 typename fpa::Image::DijkstraWithEndPointDetection< I, O >::
542 TVertex fpa::Image::DijkstraWithEndPointDetection< I, O >::
543 _MaxInRegion( const _T* image, const TVertex& v, const double& r )
544 {
545   typedef itk::ImageRegionConstIteratorWithIndex< _T > _TIt;
546
547   _TIt iIt( image, this->_Region( v, r ) );
548   iIt.GoToBegin( );
549   TVertex max_vertex = iIt.GetIndex( );
550   typename _T::PixelType max_value = iIt.Get( );
551   for( ++iIt; !iIt.IsAtEnd( ); ++iIt )
552   {
553     typename _T::PixelType value = iIt.Get( );
554     if( value > max_value )
555     {
556       max_value = value;
557       max_vertex = iIt.GetIndex( );
558
559     } // fi
560
561   } // rof
562   return( max_vertex );
563 }
564
565 #endif // __FPA__IMAGE__DIJKSTRAWITHENDPOINTDETECTION__HXX__
566
567 // eof - $RCSfile$