From 490e6f877a3537463de4281b0366337ab73ced99 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leonardo=20Fl=C3=B3rez-Valencia?= Date: Tue, 8 Nov 2016 18:45:50 -0500 Subject: [PATCH] Skeletonization improved. --- lib/fpa/Image/SkeletonFilter.h | 117 ++++++------ lib/fpa/Image/SkeletonFilter.hxx | 278 ++++++++++++++--------------- plugins/Plugins/SkeletonFilter.cxx | 104 ++++------- plugins/Plugins/SkeletonFilter.h | 7 +- plugins/Plugins/fpaPlugins.i | 2 +- 5 files changed, 226 insertions(+), 282 deletions(-) diff --git a/lib/fpa/Image/SkeletonFilter.h b/lib/fpa/Image/SkeletonFilter.h index 85618d7..0ed3789 100644 --- a/lib/fpa/Image/SkeletonFilter.h +++ b/lib/fpa/Image/SkeletonFilter.h @@ -1,104 +1,105 @@ #ifndef __fpa__Image__SkeletonFilter__h__ #define __fpa__Image__SkeletonFilter__h__ -#include -#include -#include +#include #include +#include +#include +#include #include +/* TODO + #include + #include +*/ + namespace fpa { namespace Image { /** */ - template< class _TDistanceMap, class _TCostMap > + template< class _TImage > class SkeletonFilter - : public itk::ProcessObject + : public Dijkstra< _TImage, _TImage > { public: typedef SkeletonFilter Self; - typedef itk::ProcessObject Superclass; + typedef Dijkstra< _TImage, _TImage > Superclass; typedef itk::SmartPointer< Self > Pointer; typedef itk::SmartPointer< const Self > ConstPointer; -#ifdef ITK_USE_CONCEPT_CHECKING - itkConceptMacro( - SameDimension, - ( itk::Concept::SameDimension< _TDistanceMap::ImageDimension, _TCostMap::ImageDimension > ) + typedef _TImage TImage; + itkStaticConstMacro( + Dimension, unsigned int, TImage::ImageDimension ); -#endif - typedef _TDistanceMap TDistanceMap; - typedef _TCostMap TCostMap; - typedef typename TCostMap::IndexType TIndex; - typedef MinimumSpanningTree< TCostMap::ImageDimension > TMST; + + typedef typename Superclass::TMST TMST; + typedef typename TImage::IndexType TIndex; + typedef - cpExtensions::DataStructures::Skeleton< TCostMap::ImageDimension > - TSkeleton; - typedef itk::Image< unsigned char, _TCostMap::ImageDimension > TMarks; + itk::Functor::IndexLexicographicCompare< Self::Dimension > TIndexCmp; + typedef std::set< TIndex, TIndexCmp > TIndicesData; + typedef itk::SimpleDataObjectDecorator< TIndicesData > TIndices; + typedef itk::Image< unsigned char, Self::Dimension > TMarks; + typedef + cpExtensions::DataStructures::Skeleton< Self::Dimension > TSkeleton; + protected: + typedef typename Superclass::_TQueueNode _TQueueNode; typedef - itk::Functor::IndexLexicographicCompare< _TCostMap::ImageDimension > - TIndexCompare; - typedef std::set< TIndex, TIndexCompare > TIndicesData; - typedef itk::SimpleDataObjectDecorator< TIndicesData > TIndices; + std::multimap< double, TIndex, std::greater< double > > + _TSkeletonQueue; public: itkNewMacro( Self ); itkTypeMacro( fpa::Image::SkeletonFilter, itk::Object ); public: - _TDistanceMap* GetDistanceMap( ); - const _TDistanceMap* GetDistanceMap( ) const; - void SetDistanceMap( _TDistanceMap* dmap ); - - _TCostMap* GetCostMap( ); - const _TCostMap* GetCostMap( ) const; - void SetCostMap( _TCostMap* cmap ); - - TMST* GetMinimumSpanningTree( ); - const TMST* GetMinimumSpanningTree( ) const; - void SetMinimumSpanningTree( TMST* mst ); - TIndices* GetEndPoints( ); - const TIndices* GetEndPoints( ) const; - TIndices* GetBifurcations( ); - const TIndices* GetBifurcations( ) const; - TSkeleton* GetSkeleton( ); - const TSkeleton* GetSkeleton( ) const; - TMarks* GetMarks( ); - const TMarks* GetMarks( ) const; protected: SkeletonFilter( ); virtual ~SkeletonFilter( ); - virtual void GenerateData( ) fpa_OVERRIDE; - - void _EndPoints( - const TDistanceMap* dmap, - const TCostMap* cmap, - const TMST* mst, - TIndicesData& end_points - ); - - void _Skeleton( - const TDistanceMap* dmap, - const TCostMap* cmap, - const TMST* mst, - const TIndicesData& end_points, - TIndicesData& bifurcations, - TSkeleton* skeleton - ); + virtual void _BeforeGenerateData( ) fpa_OVERRIDE; + virtual void _UpdateResult( const _TQueueNode& n ) fpa_OVERRIDE; + virtual void _AfterGenerateData( ) fpa_OVERRIDE; + + void _EndPoints( ); + void _Skeleton( ); + + /* TODO + virtual void GenerateData( ) fpa_OVERRIDE; + const TDistanceMap* dmap, + const TCostMap* cmap, + const TMST* mst, + TIndicesData& end_points + ); + const TDistanceMap* dmap, + const TCostMap* cmap, + const TMST* mst, + const TIndicesData& end_points, + TIndicesData& bifurcations, + TSkeleton* skeleton + ); + */ private: // Purposely not defined SkeletonFilter( const Self& other ); Self& operator=( const Self& other ); + + protected: + _TSkeletonQueue m_SkeletonQueue; + + unsigned long m_EndPointsIdx; + unsigned long m_BifurcationsIdx; + unsigned long m_SkeletonIdx; + unsigned long m_MarksIdx; }; } // ecapseman diff --git a/lib/fpa/Image/SkeletonFilter.hxx b/lib/fpa/Image/SkeletonFilter.hxx index 2e98935..f0adeac 100644 --- a/lib/fpa/Image/SkeletonFilter.hxx +++ b/lib/fpa/Image/SkeletonFilter.hxx @@ -1,174 +1,152 @@ #ifndef __fpa__Image__SkeletonFilter__hxx__ #define __fpa__Image__SkeletonFilter__hxx__ -#include -#include +/* TODO + #include + #include +*/ +#include +#include #include // ------------------------------------------------------------------------- -#define fpa_Image_SkeletonFilter_InputMacro( i_n, i_t, i_i ) \ - template< class _TDistanceMap, class _TCostMap > \ - typename fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \ - i_t* fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \ - Get##i_n( ) \ - { \ - return( \ - dynamic_cast< i_t* >( this->Superclass::GetInput( i_i ) ) \ - ); \ - } \ - template< class _TDistanceMap, class _TCostMap > \ - const \ - typename fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \ - i_t* fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \ - Get##i_n( ) const \ - { \ - return( \ - dynamic_cast< const i_t* >( this->Superclass::GetInput( i_i ) ) \ - ); \ - } \ - template< class _TDistanceMap, class _TCostMap > \ - void fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \ - Set##i_n( i_t* input ) \ - { \ - this->Superclass::SetNthInput( i_i, input ); \ - } - -fpa_Image_SkeletonFilter_InputMacro( DistanceMap, TDistanceMap, 0 ); -fpa_Image_SkeletonFilter_InputMacro( CostMap, TCostMap, 1 ); -fpa_Image_SkeletonFilter_InputMacro( MinimumSpanningTree, TMST, 2 ); - -// ------------------------------------------------------------------------- -#define fpa_Image_SkeletonFilter_OutputMacro( o_n, o_t, o_i ) \ - template< class _TDistanceMap, class _TCostMap > \ - typename fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \ - o_t* fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \ +#define fpa_Image_SkeletonFilter_OutputMacro( o_n, o_t ) \ + template< class _TImage > \ + typename fpa::Image::SkeletonFilter< _TImage >:: \ + o_t* fpa::Image::SkeletonFilter< _TImage >:: \ Get##o_n( ) \ { \ return( \ - dynamic_cast< o_t* >( this->Superclass::GetOutput( o_i ) ) \ - ); \ - } \ - template< class _TDistanceMap, class _TCostMap > \ - const typename \ - fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \ - o_t* fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: \ - Get##o_n( ) const \ - { \ - return( \ - dynamic_cast< const o_t* >( this->Superclass::GetOutput( o_i ) ) \ + dynamic_cast< o_t* >( \ + this->itk::ProcessObject::GetOutput( this->m_##o_n##Idx ) \ + ) \ ); \ } -fpa_Image_SkeletonFilter_OutputMacro( Skeleton, TSkeleton, 0 ); -fpa_Image_SkeletonFilter_OutputMacro( EndPoints, TIndices, 1 ); -fpa_Image_SkeletonFilter_OutputMacro( Bifurcations, TIndices, 2 ); -fpa_Image_SkeletonFilter_OutputMacro( Marks, TMarks, 3 ); +fpa_Image_SkeletonFilter_OutputMacro( Skeleton, TSkeleton ); +fpa_Image_SkeletonFilter_OutputMacro( EndPoints, TIndices ); +fpa_Image_SkeletonFilter_OutputMacro( Bifurcations, TIndices ); +fpa_Image_SkeletonFilter_OutputMacro( Marks, TMarks ); // ------------------------------------------------------------------------- -template< class _TDistanceMap, class _TCostMap > -fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: +template< class _TImage > +fpa::Image::SkeletonFilter< _TImage >:: SkeletonFilter( ) : Superclass( ) { - this->SetNumberOfRequiredInputs( 3 ); - this->SetNumberOfRequiredOutputs( 3 ); + typedef typename _TImage::PixelType _TPixel; + typedef typename _TImage::Superclass _TImageBase; + typedef fpa::Image::Functors::SimpleNeighborhood< _TImageBase > _TNeighFunc; + typedef fpa::Base::Functors::Inverse< _TPixel, _TPixel > _TInvFunc; + + unsigned int nOutputs = this->GetNumberOfRequiredOutputs( ); + this->SetNumberOfRequiredOutputs( nOutputs + 4 ); + this->m_EndPointsIdx = nOutputs; + this->m_BifurcationsIdx = nOutputs + 1; + this->m_SkeletonIdx = nOutputs + 2; + this->m_MarksIdx = nOutputs + 3; typename TIndices::Pointer end_points = TIndices::New( ); typename TIndices::Pointer bifurcations = TIndices::New( ); typename TSkeleton::Pointer skeleton = TSkeleton::New( ); typename TMarks::Pointer marks = TMarks::New( ); - this->SetNthOutput( 0, skeleton.GetPointer( ) ); - this->SetNthOutput( 1, end_points.GetPointer( ) ); - this->SetNthOutput( 2, bifurcations.GetPointer( ) ); - this->SetNthOutput( 3, marks.GetPointer( ) ); + this->SetNthOutput( this->m_EndPointsIdx, end_points.GetPointer( ) ); + this->SetNthOutput( this->m_BifurcationsIdx, bifurcations.GetPointer( ) ); + this->SetNthOutput( this->m_SkeletonIdx, skeleton.GetPointer( ) ); + this->SetNthOutput( this->m_MarksIdx, marks.GetPointer( ) ); + + typename _TNeighFunc::Pointer nfunc = _TNeighFunc::New( ); + nfunc->SetOrder( 2 ); + this->SetNeighborhoodFunction( nfunc ); + + typename _TInvFunc::Pointer ifunc = _TInvFunc::New( ); + this->SetCostConversionFunction( ifunc ); } // ------------------------------------------------------------------------- -template< class _TDistanceMap, class _TCostMap > -fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: +template< class _TImage > +fpa::Image::SkeletonFilter< _TImage >:: ~SkeletonFilter( ) { } // ------------------------------------------------------------------------- -template< class _TDistanceMap, class _TCostMap > -void fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: -GenerateData( ) +template< class _TImage > +void fpa::Image::SkeletonFilter< _TImage >:: +_BeforeGenerateData( ) { - // 0. I/O objects - const TDistanceMap* dmap = this->GetDistanceMap( ); - const TCostMap* cmap = this->GetCostMap( ); - const TMST* mst = this->GetMinimumSpanningTree( ); - TIndices* ep = this->GetEndPoints( ); - TIndices* bi = this->GetBifurcations( ); - TSkeleton* sk = this->GetSkeleton( ); - - // 1. Check input correspondance - // TODO - - // 2. Detect end-points - this->_EndPoints( dmap, cmap, mst, ep->Get( ) ); - - // 3. Build skeleton and keep track of bifurcations - this->_Skeleton( dmap, cmap, mst, ep->Get( ), bi->Get( ), sk ); + this->Superclass::_BeforeGenerateData( ); + this->m_SkeletonQueue.clear( ); } // ------------------------------------------------------------------------- -template< class _TDistanceMap, class _TCostMap > -void fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: -_EndPoints( - const TDistanceMap* dmap, - const TCostMap* cmap, - const TMST* mst, - TIndicesData& end_points - ) +template< class _TImage > +void fpa::Image::SkeletonFilter< _TImage >:: +_UpdateResult( const _TQueueNode& n ) +{ + typedef typename _TSkeletonQueue::value_type _TSkeletonQueueValue; + + this->Superclass::_UpdateResult( n ); + + // Update skeleton candidates + double d = double( this->GetInput( )->GetPixel( n.Vertex ) ); + if( d >= double( 0 ) ) + { + d += double( 1e-5 ); + double v = double( n.Result ) / ( d * d ); + this->m_SkeletonQueue.insert( _TSkeletonQueueValue( v, n.Vertex ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void fpa::Image::SkeletonFilter< _TImage >:: +_AfterGenerateData( ) +{ + this->Superclass::_AfterGenerateData( ); + this->_EndPoints( ); + this->_Skeleton( ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void fpa::Image::SkeletonFilter< _TImage >:: +_EndPoints( ) { - typedef itk::ImageRegionConstIteratorWithIndex< _TDistanceMap > _TDistMapIt; - typedef itk::ImageRegionConstIteratorWithIndex< _TCostMap > _TCostMapIt; - typedef std::multimap< double, TIndex, std::greater< double > > _TQueue; - typedef typename _TQueue::value_type _TQueueValue; typedef itk::ImageRegionIteratorWithIndex< TMarks > _TMarksIt; - static const double _eps = std::sqrt( double( TMarks::ImageDimension + 1 ) ); + /* TODO + typedef itk::ImageRegionConstIteratorWithIndex< _TImage > _TDistMapIt; + typedef itk::ImageRegionConstIteratorWithIndex< _TOutput > _TOutputIt; + typedef std::multimap< double, TIndex, std::greater< double > > _TQueue; + typedef typename _TQueue::value_type _TQueueValue; + */ - // Some values + static const double _eps = std::sqrt( double( Self::Dimension + 1 ) ); + auto input = this->GetInput( ); + auto mst = this->GetMinimumSpanningTree( ); auto marks = this->GetMarks( ); - marks->SetLargestPossibleRegion( dmap->GetLargestPossibleRegion( ) ); - marks->SetRequestedRegion( dmap->GetRequestedRegion( ) ); - marks->SetBufferedRegion( dmap->GetBufferedRegion( ) ); - marks->SetSpacing( dmap->GetSpacing( ) ); - marks->SetOrigin( dmap->GetOrigin( ) ); - marks->SetDirection( dmap->GetDirection( ) ); + auto& end_points = this->GetEndPoints( )->Get( ); + + // Some values + marks->SetLargestPossibleRegion( input->GetLargestPossibleRegion( ) ); + marks->SetRequestedRegion( input->GetRequestedRegion( ) ); + marks->SetBufferedRegion( input->GetBufferedRegion( ) ); + marks->SetSpacing( input->GetSpacing( ) ); + marks->SetOrigin( input->GetOrigin( ) ); + marks->SetDirection( input->GetDirection( ) ); marks->Allocate( ); marks->FillBuffer( 0 ); - // Create queue - _TQueue queue; - _TDistMapIt dIt( dmap, dmap->GetRequestedRegion( ) ); - _TCostMapIt cIt( cmap, cmap->GetRequestedRegion( ) ); - dIt.GoToBegin( ); - cIt.GoToBegin( ); - for( ; !dIt.IsAtEnd( ) && !cIt.IsAtEnd( ); ++dIt, ++cIt ) - { - double d = double( dIt.Get( ) ); - if( d >= double( 0 ) ) - { - d += double( 1e-5 ); - double v = double( cIt.Get( ) ) / ( d * d ); - queue.insert( _TQueueValue( v, dIt.GetIndex( ) ) ); - - } // fi - - } // rof - // BFS from maximum queue - auto region = dmap->GetRequestedRegion( ); - while( queue.size( ) > 0 ) + auto region = input->GetRequestedRegion( ); + while( this->m_SkeletonQueue.size( ) > 0 ) { // Get node - auto nIt = queue.begin( ); + auto nIt = this->m_SkeletonQueue.begin( ); auto n = *nIt; - queue.erase( nIt ); + this->m_SkeletonQueue.erase( nIt ); // Mark it and update end-points unsigned char m = marks->GetPixel( n.second ); @@ -184,12 +162,12 @@ _EndPoints( for( unsigned long i = 0; i < path->GetSize( ); ++i ) { TIndex idx = path->GetVertex( i ); - typename _TCostMap::PointType cnt; - cmap->TransformIndexToPhysicalPoint( idx, cnt ); - double r = double( dmap->GetPixel( idx ) ) * _eps; + typename _TImage::PointType cnt; + input->TransformIndexToPhysicalPoint( idx, cnt ); + double r = double( input->GetPixel( idx ) ) * _eps; TIndex i0, i1; - for( unsigned int d = 0; d < TMarks::ImageDimension; ++d ) + for( unsigned int d = 0; d < Self::Dimension; ++d ) { long off = long( std::ceil( r / double( spac[ d ] ) ) ); if( off < 3 ) @@ -205,11 +183,11 @@ _EndPoints( } // rof - typename TMarks::SizeType size; - for( unsigned int d = 0; d < TMarks::ImageDimension; ++d ) + typename _TImage::SizeType size; + for( unsigned int d = 0; d < Self::Dimension; ++d ) size[ d ] = i1[ d ] - i0[ d ] + 1; - typename TMarks::RegionType neighRegion; + typename _TImage::RegionType neighRegion; neighRegion.SetIndex( i0 ); neighRegion.SetSize( size ); @@ -217,7 +195,7 @@ _EndPoints( for( mIt.GoToBegin( ); !mIt.IsAtEnd( ); ++mIt ) { TIndex w = mIt.GetIndex( ); - typename _TCostMap::PointType p; + typename _TImage::PointType p; marks->TransformIndexToPhysicalPoint( w, p ); mIt.Set( 1 ); @@ -229,19 +207,15 @@ _EndPoints( } // ------------------------------------------------------------------------- -template< class _TDistanceMap, class _TCostMap > -void fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap >:: -_Skeleton( - const TDistanceMap* dmap, - const TCostMap* cmap, - const TMST* mst, - const TIndicesData& end_points, - TIndicesData& bifurcations, - TSkeleton* skeleton - ) +template< class _TImage > +void fpa::Image::SkeletonFilter< _TImage >:: +_Skeleton( ) { - typedef typename TMST::TPath _TPath; + auto mst = this->GetMinimumSpanningTree( ); + auto skeleton = this->GetSkeleton( ); + auto& end_points = this->GetEndPoints( )->Get( ); + typedef typename TMST::TPath _TPath; for( auto eIt = end_points.begin( ); eIt != end_points.end( ); ++eIt ) { typename _TPath::Pointer path; @@ -251,6 +225,22 @@ _Skeleton( } // rof } +// ------------------------------------------------------------------------- +/* TODO + template< class _TImage > + void fpa::Image::SkeletonFilter< _TImage >:: + _Skeleton( + const TDistanceMap* dmap, + const TCostMap* cmap, + const TMST* mst, + const TIndicesData& end_points, + TIndicesData& bifurcations, + TSkeleton* skeleton + ) + { + } +*/ + #endif // __fpa__Image__SkeletonFilter__hxx__ // eof - $RCSfile$ diff --git a/plugins/Plugins/SkeletonFilter.cxx b/plugins/Plugins/SkeletonFilter.cxx index d68db4f..31f0f5c 100644 --- a/plugins/Plugins/SkeletonFilter.cxx +++ b/plugins/Plugins/SkeletonFilter.cxx @@ -5,11 +5,7 @@ #include #include - -/* TODO - #include - #include -*/ +#include // ------------------------------------------------------------------------- fpaPlugins::SkeletonFilter:: @@ -18,16 +14,12 @@ SkeletonFilter( ) { typedef cpPlugins::DataObjects::Image _TImage; typedef cpPlugins::DataObjects::Skeleton _TSkeleton; + typedef cpPlugins::BaseObjects::DataObject _TData; - this->_ConfigureInput< _TImage >( "DistanceMap", true, false ); - this->_ConfigureInput< _TImage >( "CostMap", true, false ); - this->_ConfigureInput< _TImage >( "MST", true, false ); + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureInput< _TData >( "Seeds", true, false ); this->_ConfigureOutput< _TSkeleton >( "Skeleton" ); this->_ConfigureOutput< _TImage >( "Marks" ); - /* TODO - this->_ConfigureOutput< _TMesh >( "EndPoints" ); - this->_ConfigureOutput< _TMesh >( "Bifurcations" ); - */ } // ------------------------------------------------------------------------- @@ -40,82 +32,46 @@ fpaPlugins::SkeletonFilter:: void fpaPlugins::SkeletonFilter:: _GenerateData( ) { - auto o = this->GetInputData( "DistanceMap" ); + auto o = this->GetInputData( "Input" ); cpPlugins_Demangle_Image_RealPixels_AllDims_1( o, _GD0 ) this->_Error( "Invalid input image." ); } // ------------------------------------------------------------------------- -template< class _TDistanceMap > +template< class _TImage > void fpaPlugins::SkeletonFilter:: -_GD0( _TDistanceMap* dmap ) +_GD0( _TImage* image ) { - auto o = this->GetInputData( "CostMap" ); - cpPlugins_Demangle_Image_RealPixels_2( o, _GD1, _TDistanceMap::ImageDimension, dmap ) - this->_Error( "Invalid input image." ); -} - -// ------------------------------------------------------------------------- -template< class _TCostMap, class _TDistanceMap > -void fpaPlugins::SkeletonFilter:: -_GD1( _TCostMap* cmap, _TDistanceMap* dmap ) -{ - typedef fpa::Image::SkeletonFilter< _TDistanceMap, _TCostMap > _TFilter; - typedef typename _TFilter::TMST _TMST; - - auto mst = this->GetInputData< _TMST >( "MST" ); - if( mst == NULL ) - this->_Error( "Invalid MST." ); - + typedef fpa::Image::SkeletonFilter< _TImage > _TFilter; auto filter = this->_CreateITK< _TFilter >( ); - filter->SetDistanceMap( dmap ); - filter->SetCostMap( cmap ); - filter->SetMinimumSpanningTree( mst ); - filter->Update( ); - this->GetOutput( "Skeleton" )->SetITK( filter->GetSkeleton( ) ); - this->GetOutput( "Marks" )->SetITK( filter->GetMarks( ) ); - - /* TODO - auto ep = filter->GetEndPoints( ); - auto bi = filter->GetBifurcations( ); + filter->SetInput( image ); - auto ep_pd = this->GetOutputData< vtkPolyData >( "EndPoints" ); - if( ep_pd == NULL ) - { - auto points = vtkSmartPointer< vtkPoints >::New( ); - auto verts = vtkSmartPointer< vtkCellArray >::New( ); - auto lines = vtkSmartPointer< vtkCellArray >::New( ); - auto polys = vtkSmartPointer< vtkCellArray >::New( ); - auto strips = vtkSmartPointer< vtkCellArray >::New( ); - auto pd = vtkSmartPointer< vtkPolyData >::New( ); - pd->SetPoints( points ); - pd->SetVerts( verts ); - pd->SetLines( lines ); - pd->SetPolys( polys ); - pd->SetStrips( strips ); + auto seeds = this->GetInputData< vtkPolyData >( "Seeds" ); + if( seeds != NULL ) + { + typename _TImage::PointType pnt; + typename _TImage::IndexType idx; + unsigned int dim = + ( _TImage::ImageDimension < 3 )? _TImage::ImageDimension: 3; - this->GetOutput( "EndPoints" )->SetVTK( pd ); - ep_pd = this->GetOutputData< vtkPolyData >( "EndPoints" ); + for( int i = 0; i < seeds->GetNumberOfPoints( ); ++i ) + { + double buf[ 3 ]; + seeds->GetPoint( i, buf ); + pnt.Fill( 0 ); + for( unsigned int d = 0; d < dim; ++d ) + pnt[ d ] = buf[ d ]; - } // fi + if( image->TransformPhysicalPointToIndex( pnt, idx ) ) + filter->AddSeed( idx, 0 ); - for( auto iIt = ep.begin( ); iIt != ep.end( ); ++iIt ) - { - typename _TCostMap::PointType p; - cmap->TransformIndexToPhysicalPoint( *iIt, p ); + } // rof - if( _TCostMap::ImageDimension == 1 ) - ep_pd->GetPoints( )->InsertNextPoint( p[ 0 ], 0, 0 ); - else if( _TCostMap::ImageDimension == 2 ) - ep_pd->GetPoints( )->InsertNextPoint( p[ 0 ], p[ 1 ], 0 ); - else if( _TCostMap::ImageDimension > 2 ) - ep_pd->GetPoints( )->InsertNextPoint( p[ 0 ], p[ 1 ], p[ 2 ] ); + } // fi - ep_pd->GetVerts( )->InsertNextCell( 1 ); - ep_pd->GetVerts( )->InsertCellPoint( ep_pd->GetNumberOfPoints( ) - 1 ); - - } // rof - */ + filter->Update( ); + this->GetOutput( "Skeleton" )->SetITK( filter->GetSkeleton( ) ); + this->GetOutput( "Marks" )->SetITK( filter->GetMarks( ) ); } // eof - $RCSfile$ diff --git a/plugins/Plugins/SkeletonFilter.h b/plugins/Plugins/SkeletonFilter.h index 1337ca2..ee940c7 100644 --- a/plugins/Plugins/SkeletonFilter.h +++ b/plugins/Plugins/SkeletonFilter.h @@ -18,11 +18,8 @@ namespace fpaPlugins ); protected: - template< class _TDistanceMap > - inline void _GD0( _TDistanceMap* dmap ); - - template< class _TCostMap, class _TDistanceMap > - inline void _GD1( _TCostMap* cmap, _TDistanceMap* dmap ); + template< class _TImage > + inline void _GD0( _TImage* image ); }; } // ecapseman diff --git a/plugins/Plugins/fpaPlugins.i b/plugins/Plugins/fpaPlugins.i index 57709d3..b01b712 100644 --- a/plugins/Plugins/fpaPlugins.i +++ b/plugins/Plugins/fpaPlugins.i @@ -21,6 +21,6 @@ instances fpa::Base::Functors::Inverse< #i_real#, #o_real# > instances fpa::Base::Functors::GaussianModel< #i_real#, #o_real# > instances fpa::Image::Dijkstra< itk::Image< #scalar_pixels#, #process_dims# >, itk::Image< #real_types#, #process_dims# > > -instances fpa::Image::SkeletonFilter< itk::Image< #i_real#, #process_dims# >, itk::Image< #o_real#, #process_dims# > > +instances fpa::Image::SkeletonFilter< itk::Image< #real_types#, #process_dims# > > ** eof - $RCSfile$ -- 2.47.1