1 #ifndef __fpa__Image__SkeletonFilter__hxx__
2 #define __fpa__Image__SkeletonFilter__hxx__
5 #include <itkImageRegionConstIteratorWithIndex.h>
7 // -------------------------------------------------------------------------
8 #define fpa_Image_SkeletonFilter_InputMacro( i_n, i_t, i_i ) \
9 template< class _TDistanceMap, class _TCostMap > \
10 typename fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \
11 i_t* fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \
15 dynamic_cast< i_t* >( this->Superclass::GetInput( i_i ) ) \
18 template< class _TDistanceMap, class _TCostMap > \
20 typename fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \
21 i_t* fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \
25 dynamic_cast< const i_t* >( this->Superclass::GetInput( i_i ) ) \
28 template< class _TDistanceMap, class _TCostMap > \
29 void fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \
30 Set##i_n( i_t* input ) \
32 this->Superclass::SetNthInput( i_i, input ); \
35 fpa_Image_SkeletonFilter_InputMacro( DistanceMap, TDistanceMap, 0 );
36 fpa_Image_SkeletonFilter_InputMacro( CostMap, TCostMap, 1 );
37 fpa_Image_SkeletonFilter_InputMacro( MinimumSpanningTree, TMST, 2 );
39 // -------------------------------------------------------------------------
40 #define fpa_Image_SkeletonFilter_OutputMacro( o_n, o_t, o_i ) \
41 template< class _TDistanceMap, class _TCostMap > \
42 typename fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \
43 o_t* fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \
47 dynamic_cast< o_t* >( this->Superclass::GetOutput( o_i ) ) \
50 template< class _TDistanceMap, class _TCostMap > \
52 fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \
53 o_t* fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \
57 dynamic_cast< const o_t* >( this->Superclass::GetOutput( o_i ) ) \
61 fpa_Image_SkeletonFilter_OutputMacro( Skeleton, TSkeleton, 0 );
62 fpa_Image_SkeletonFilter_OutputMacro( EndPoints, TIndices, 1 );
63 fpa_Image_SkeletonFilter_OutputMacro( Bifurcations, TIndices, 2 );
64 fpa_Image_SkeletonFilter_OutputMacro( Marks, TMarks, 3 );
66 // -------------------------------------------------------------------------
67 template< class _TDistanceMap, class _TCostMap >
68 fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >::
72 this->SetNumberOfRequiredInputs( 3 );
73 this->SetNumberOfRequiredOutputs( 3 );
75 typename TIndices::Pointer end_points = TIndices::New( );
76 typename TIndices::Pointer bifurcations = TIndices::New( );
77 typename TSkeleton::Pointer skeleton = TSkeleton::New( );
78 typename TMarks::Pointer marks = TMarks::New( );
79 this->SetNthOutput( 0, skeleton.GetPointer( ) );
80 this->SetNthOutput( 1, end_points.GetPointer( ) );
81 this->SetNthOutput( 2, bifurcations.GetPointer( ) );
82 this->SetNthOutput( 3, marks.GetPointer( ) );
85 // -------------------------------------------------------------------------
86 template< class _TDistanceMap, class _TCostMap >
87 fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >::
92 // -------------------------------------------------------------------------
93 template< class _TDistanceMap, class _TCostMap >
94 void fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >::
98 const TDistanceMap* dmap = this->GetDistanceMap( );
99 const TCostMap* cmap = this->GetCostMap( );
100 const TMST* mst = this->GetMinimumSpanningTree( );
101 TIndices* ep = this->GetEndPoints( );
102 TIndices* bi = this->GetBifurcations( );
103 TSkeleton* sk = this->GetSkeleton( );
105 // 1. Check input correspondance
108 // 2. Detect end-points
109 this->_EndPoints( dmap, cmap, mst, ep->Get( ) );
111 // 3. Build skeleton and keep track of bifurcations
112 this->_Skeleton( dmap, cmap, mst, ep->Get( ), bi->Get( ), sk );
115 // -------------------------------------------------------------------------
116 template< class _TDistanceMap, class _TCostMap >
117 void fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >::
119 const TDistanceMap* dmap,
120 const TCostMap* cmap,
122 TIndicesData& end_points
125 typedef itk::ImageRegionConstIteratorWithIndex< _TDistanceMap > _TDistMapIt;
126 typedef itk::ImageRegionConstIteratorWithIndex< _TCostMap > _TCostMapIt;
127 typedef std::multimap< double, TIndex, std::greater< double > > _TQueue;
128 typedef typename _TQueue::value_type _TQueueValue;
129 typedef itk::Image< unsigned char, _TCostMap::ImageDimension > _TMarks;
132 // typename _TMarks::Pointer marks = _TMarks::New( );
133 auto marks = this->GetMarks( );
134 marks->SetLargestPossibleRegion( dmap->GetLargestPossibleRegion( ) );
135 marks->SetRequestedRegion( dmap->GetRequestedRegion( ) );
136 marks->SetBufferedRegion( dmap->GetBufferedRegion( ) );
137 marks->SetSpacing( dmap->GetSpacing( ) );
138 marks->SetOrigin( dmap->GetOrigin( ) );
139 marks->SetDirection( dmap->GetDirection( ) );
141 marks->FillBuffer( 0 );
145 _TDistMapIt dIt( dmap, dmap->GetRequestedRegion( ) );
146 _TCostMapIt cIt( cmap, cmap->GetRequestedRegion( ) );
149 for( ; !dIt.IsAtEnd( ) && !cIt.IsAtEnd( ); ++dIt, ++cIt )
151 double d = double( dIt.Get( ) );
154 double v = double( cIt.Get( ) ) / ( d * d );
155 queue.insert( _TQueueValue( v, dIt.GetIndex( ) ) );
161 // BFS from maximum queue
162 auto region = dmap->GetRequestedRegion( );
163 double init_v = queue.begin( )->first;
164 while( queue.size( ) > 0 )
167 auto nIt = queue.begin( );
171 unsigned char m = marks->GetPixel( n.second );
172 // if( ( m & 0x01 ) == 0x01 )
173 if( m != 0 || ( n.first / init_v ) < double( 1e-1 ) )
176 // Mark it and update end-points
178 marks->SetPixel( n.second, m );
179 end_points.insert( n.second );
182 typename TMST::TPath::Pointer path;
183 mst->GetPath( path, n.second );
184 for( unsigned long i = 0; i < path->GetSize( ); ++i )
186 TIndex idx = path->GetVertex( i );
187 typename _TCostMap::PointType cnt;
188 cmap->TransformIndexToPhysicalPoint( idx, cnt );
189 double d = double( 2 ) * double( dmap->GetPixel( idx ) );
192 std::queue< TIndex > q;
194 while( q.size( ) > 0 )
196 TIndex v = q.front( );
198 unsigned char m = marks->GetPixel( v );
199 if( ( m & 0x02 ) == 0x02 )
202 marks->SetPixel( v, m );
204 for( unsigned int x = 0; x < _TCostMap::ImageDimension; ++x )
206 for( int y = -1; y <= 1; y += 2 )
210 if( region.IsInside( w ) )
212 typename _TCostMap::PointType p;
213 cmap->TransformIndexToPhysicalPoint( w, p );
214 if( cnt.EuclideanDistanceTo( p ) <= d )
230 // -------------------------------------------------------------------------
231 template< class _TDistanceMap, class _TCostMap >
232 void fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >::
234 const TDistanceMap* dmap,
235 const TCostMap* cmap,
237 const TIndicesData& end_points,
238 TIndicesData& bifurcations,
242 typedef typename TMST::TPath _TPath;
244 for( auto eIt = end_points.begin( ); eIt != end_points.end( ); ++eIt )
246 typename _TPath::Pointer path;
247 mst->GetPath( path, *eIt );
248 skeleton->AddBranch( path );
253 #endif // __fpa__Image__SkeletonFilter__hxx__