1 #ifndef __FPA__IMAGE__DIJKSTRAWITHSPHEREBACKTRACKING__HXX__
2 #define __FPA__IMAGE__DIJKSTRAWITHSPHEREBACKTRACKING__HXX__
5 #include <itkImageRegionConstIteratorWithIndex.h>
6 #include <itkImageRegionIteratorWithIndex.h>
8 // -------------------------------------------------------------------------
9 template< class I, class C >
10 typename fpa::Image::DijkstraWithSphereBacktracking< I, C >::
11 TMarkImage* fpa::Image::DijkstraWithSphereBacktracking< I, C >::
15 dynamic_cast< TMarkImage* >(
16 this->itk::ProcessObject::GetOutput( 1 )
21 // -------------------------------------------------------------------------
22 template< class I, class C >
23 const typename fpa::Image::DijkstraWithSphereBacktracking< I, C >::
24 TMarkImage* fpa::Image::DijkstraWithSphereBacktracking< I, C >::
25 GetOutputMarkImage( ) const
28 dynamic_cast< const TMarkImage* >(
29 this->itk::ProcessObject::GetOutput( 1 )
34 // -------------------------------------------------------------------------
35 template< class I, class C >
36 fpa::Image::DijkstraWithSphereBacktracking< I, C >::
37 DijkstraWithSphereBacktracking( )
39 m_NumberOfBranches( 0 )
41 this->SetNumberOfRequiredOutputs( 2 );
42 this->SetNthOutput( 0, I::New( ) );
43 this->SetNthOutput( 1, TMarkImage::New( ) );
46 // -------------------------------------------------------------------------
47 template< class I, class C >
48 fpa::Image::DijkstraWithSphereBacktracking< I, C >::
49 ~DijkstraWithSphereBacktracking( )
53 // -------------------------------------------------------------------------
54 template< class I, class C >
55 void fpa::Image::DijkstraWithSphereBacktracking< I, C >::
58 const I* img = this->GetInput( );
59 typename I::SpacingType spac = img->GetSpacing( );
60 double max_spac = spac[ 0 ];
61 for( unsigned int d = 1; d < I::ImageDimension; ++d )
63 ( max_spac < double( spac[ d ] ) )? double( spac[ d ] ): max_spac;
64 max_spac *= double( 30 );
67 for( unsigned int s = 0; s < this->m_Seeds.size( ); ++s )
69 _TNode seed = this->m_Seeds[ s ];
70 _TRegion region = this->_Region( seed.Vertex, max_spac );
71 itk::ImageRegionConstIteratorWithIndex< I > iIt( img, region );
74 _TPixel max_value = iIt.Get( );
75 for( ++iIt; !iIt.IsAtEnd( ); ++iIt )
77 if( iIt.Get( ) > max_value )
79 seed.Vertex = iIt.GetIndex( );
80 seed.Parent = seed.Vertex;
81 max_value = iIt.Get( );
86 this->m_Seeds[ s ] = seed;
91 this->Superclass::_BeforeMainLoop( );
92 this->m_Candidates.clear( );
95 // -------------------------------------------------------------------------
96 template< class I, class C >
97 void fpa::Image::DijkstraWithSphereBacktracking< I, C >::
100 // Finish base algorithm
101 this->Superclass::_AfterMainLoop( );
102 this->m_FullTree.clear( );
103 this->m_ReducedTree.clear( );
104 this->m_EndPoints.clear( );
105 this->m_BifurcationPoints.clear( );
106 if( this->m_Candidates.size( ) == 0 )
108 this->InvokeEvent( TEndEvent( ) );
110 // Get some input values
111 const I* input = this->GetInput( );
112 typename I::SpacingType spac = input->GetSpacing( );
113 double max_spac = spac[ 0 ];
114 for( unsigned int d = 1; d < I::ImageDimension; ++d )
116 ( max_spac < double( spac[ d ] ) )? double( spac[ d ] ): max_spac;
117 max_spac *= double( 3 );
119 // Prepare an object to hold marks
120 typename TMarkImage::Pointer marks = this->GetOutputMarkImage( );
121 marks->FillBuffer( 0 );
123 // Iterate over the candidates, starting from the candidates that
124 // are near thin branches
125 typename _TCandidates::const_reverse_iterator cIt =
126 this->m_Candidates.rbegin( );
127 this->m_NumberOfBranches = 1;
128 for( ; cIt != this->m_Candidates.rend( ); ++cIt )
130 // If pixel hasn't been visited, continue
131 TVertex v = cIt->second;
132 if( marks->GetPixel( v ) != 0 )
135 // Compute nearest start candidate
136 _TRegion region = this->_Region( v, max_spac );
137 itk::ImageRegionConstIteratorWithIndex< I > iIt( input, region );
139 TVertex max_vertex = iIt.GetIndex( );
140 _TPixel max_value = iIt.Get( );
141 for( ++iIt; !iIt.IsAtEnd( ); ++iIt )
143 _TPixel value = iIt.Get( );
144 if( value > max_value )
147 max_vertex = iIt.GetIndex( );
154 if( marks->GetPixel( max_vertex ) != 0 )
156 this->m_EndPoints.push_back( max_vertex );
158 // Construct path (at least the part that hasn't been iterated)
165 if( this->m_FullTree.find( max_vertex ) == this->m_FullTree.end( ) )
167 // Mark a sphere around current point as visited
168 double dist = std::sqrt( double( input->GetPixel( max_vertex ) ) );
169 region = this->_Region( max_vertex, dist * double( 1.5 ) );
170 itk::ImageRegionIteratorWithIndex< TMarkImage >
171 mIt( marks, region );
172 for( mIt.GoToBegin( ); !mIt.IsAtEnd( ); ++mIt )
173 mIt.Set( this->m_NumberOfBranches );
175 // Next vertex in current path
176 this->InvokeEvent( TBacktrackingEvent( max_vertex, this->m_NumberOfBranches ) );
177 this->m_FullTree[ max_vertex ] =
178 TTreeNode( this->_Parent( max_vertex ), this->m_NumberOfBranches );
179 // std::cout << "New: " << this->m_NumberOfBranches << std::endl;
183 // A bifurcation point has been reached!
184 this->m_BifurcationPoints.push_back( max_vertex );
185 this->m_NumberOfBranches++;
187 this->m_FullTree[ max_vertex ] =
188 TTreeNode( this->_Parent( max_vertex ), this->m_NumberOfBranches );
189 // std::cout << "Bifurcation: " << this->m_NumberOfBranches << std::endl;
199 this->m_BifurcationPoints.begin( ),
200 this->m_BifurcationPoints.end( ),
202 ) == this->m_BifurcationPoints.end( )
205 // Mark a sphere around current point as visited
206 double dist = std::sqrt( double( input->GetPixel( max_vertex ) ) );
207 region = this->_Region( max_vertex, dist * double( 1.5 ) );
208 itk::ImageRegionIteratorWithIndex< TMarkImage >
209 mIt( marks, region );
210 for( mIt.GoToBegin( ); !mIt.IsAtEnd( ); ++mIt )
211 mIt.Set( this->m_NumberOfBranches );
213 // Next vertex in current path
214 this->InvokeEvent( TBacktrackingEvent( max_vertex, this->m_NumberOfBranches ) );
215 this->m_FullTree[ max_vertex ] =
216 TTreeNode( this->_Parent( max_vertex ), this->m_NumberOfBranches );
218 // std::cout << "Change: " << this->m_NumberOfBranches << std::endl;
222 // A bifurcation point has been reached!
223 // TODO: this->m_BifurcationPoints.push_back( max_vertex );
224 this->m_NumberOfBranches++;
225 this->m_FullTree[ max_vertex ] =
226 TTreeNode( this->_Parent( max_vertex ), this->m_NumberOfBranches );
227 // std::cout << "Change bifurcation: " << this->m_NumberOfBranches << std::endl;
232 max_vertex = this->_Parent( max_vertex );
234 } while( max_vertex != this->_Parent( max_vertex ) );
235 if( start || change )
236 this->m_NumberOfBranches++;
237 this->m_FullTree[ max_vertex ] = TTreeNode( max_vertex, this->m_NumberOfBranches );
239 this->InvokeEvent( TEndBacktrackingEvent( ) );
243 std::map< TMark, unsigned long > histo;
245 typename TTree::iterator treeIt = this->m_FullTree.begin( );
246 treeIt != this->m_FullTree.end( );
249 histo[ treeIt->second.second ]++;
251 std::map< TMark, TMark > changes;
252 TMark last_change = 1;
253 for( TMark i = 1; i <= this->m_NumberOfBranches; ++i )
255 if( histo[ i ] != 0 )
256 changes[ i ] = last_change++;
259 this->m_NumberOfBranches = changes.size( );
262 typename TTree::iterator treeIt = this->m_FullTree.begin( );
263 treeIt != this->m_FullTree.end( );
267 TMark old = treeIt->second.second;
268 treeIt->second.second = changes[ old ];
272 // Construct reduced tree
274 typename TVertices::const_iterator eIt = this->m_EndPoints.begin( );
275 eIt != this->m_EndPoints.end( );
279 typename TTree::const_iterator tIt = this->m_FullTree.find( *eIt );
280 if( tIt != this->m_FullTree.end( ) )
282 TMark id = tIt->second.second;
285 tIt = this->m_FullTree.find( tIt->second.first );
286 if( tIt == this->m_FullTree.end( ) )
289 } while( tIt->second.second == id );
290 this->m_ReducedTree[ *eIt ] = TTreeNode( tIt->first, id );
297 typename TVertices::const_iterator bIt = this->m_BifurcationPoints.begin( );
298 bIt != this->m_BifurcationPoints.end( );
302 typename TTree::const_iterator tIt = this->m_FullTree.find( *bIt );
303 if( tIt != this->m_FullTree.end( ) )
305 TMark id = tIt->second.second;
308 tIt = this->m_FullTree.find( tIt->second.first );
309 if( tIt == this->m_FullTree.end( ) )
312 } while( tIt->second.second == id );
313 this->m_ReducedTree[ *bIt ] = TTreeNode( tIt->first, id );
320 // -------------------------------------------------------------------------
321 template< class I, class C >
322 bool fpa::Image::DijkstraWithSphereBacktracking< I, C >::
323 _UpdateNeigh( _TNode& nn, const _TNode& n )
325 C nc = this->_Cost( nn.Vertex, n.Vertex );
326 if( TCost( 0 ) < nc )
328 typename I::PointType pnn, pn;
329 this->GetInput( )->TransformIndexToPhysicalPoint( nn.Vertex, pnn );
330 this->GetInput( )->TransformIndexToPhysicalPoint( n.Vertex, pn );
334 nn.Cost = n.Cost + ( TCost( pnn.EuclideanDistanceTo( pn ) ) / std::pow( nc, 4 ) );
342 // -------------------------------------------------------------------------
343 template< class I, class C >
344 bool fpa::Image::DijkstraWithSphereBacktracking< I, C >::
345 _UpdateResult( _TNode& n )
347 bool ret = this->Superclass::_UpdateResult( n );
350 TCost nc = this->_Cost( n.Vertex, n.Parent );
351 if( TCost( 0 ) < nc )
353 TCost cc = n.Cost / nc;
354 this->m_Candidates.insert( _TCandidate( cc, n.Vertex ) );
356 this->GetOutput( )->SetPixel( n.Vertex, cc );
364 // -------------------------------------------------------------------------
365 template< class I, class C >
366 typename fpa::Image::DijkstraWithSphereBacktracking< I, C >::
367 _TRegion fpa::Image::DijkstraWithSphereBacktracking< I, C >::
368 _Region( const TVertex& c, const double& r )
370 typename I::ConstPointer input = this->GetInput( );
371 typename I::SpacingType spac = input->GetSpacing( );
372 _TRegion region = input->GetLargestPossibleRegion( );
373 typename I::IndexType idx0 = region.GetIndex( );
374 typename I::IndexType idx1 = idx0 + region.GetSize( );
376 // Compute region size and index
377 typename I::IndexType i0, i1;
379 for( unsigned int d = 0; d < I::ImageDimension; ++d )
381 long s = long( std::ceil( r / double( spac[ d ] ) ) );
382 i0[ d ] = c[ d ] - s;
383 i1[ d ] = c[ d ] + s;
385 if( i0[ d ] < idx0[ d ] ) i0[ d ] = idx0[ d ];
386 if( i1[ d ] < idx0[ d ] ) i1[ d ] = idx0[ d ];
387 if( i0[ d ] > idx1[ d ] ) i0[ d ] = idx1[ d ];
388 if( i1[ d ] > idx1[ d ] ) i1[ d ] = idx1[ d ];
389 size[ d ] = i1[ d ] - i0[ d ];
393 // Prepare region and return it
394 region.SetIndex( i0 );
395 region.SetSize( size );
399 #endif // __FPA__IMAGE__DIJKSTRAWITHSPHEREBACKTRACKING__HXX__