From c1c86dd3facb6e070b78f9bacb2c54b5a0f6bc59 Mon Sep 17 00:00:00 2001 From: Leonardo Florez-Valencia Date: Wed, 13 Apr 2016 15:46:16 -0500 Subject: [PATCH] ... --- ...tsAndBifurcationsFromMinimumSpanningTree.h | 6 +- ...AndBifurcationsFromMinimumSpanningTree.hxx | 30 +-- lib/fpa/Base/ImageSkeleton.h | 70 +++++++ lib/fpa/Base/ImageSkeleton.hxx | 73 ++++++++ ...tsAndBifurcationsFromMinimumSpanningTree.h | 3 + ...AndBifurcationsFromMinimumSpanningTree.hxx | 32 +++- lib/fpa/VTK/Image/ImageSkeletonToPolyData.h | 67 +++++++ lib/fpa/VTK/Image/ImageSkeletonToPolyData.hxx | 176 ++++++++++++++++++ lib/fpa_Instances/Instances.i | 10 + plugins/fpa/CMakeLists.txt | 2 + ...AndBifurcationsFromMinimumSpanningTree.cxx | 3 + plugins/fpa/ImageSkeleton.cxx | 75 ++++++++ plugins/fpa/ImageSkeleton.h | 52 ++++++ plugins/fpa/MinimumSpanningTree.h | 2 +- 14 files changed, 573 insertions(+), 28 deletions(-) create mode 100644 lib/fpa/Base/ImageSkeleton.h create mode 100644 lib/fpa/Base/ImageSkeleton.hxx create mode 100644 lib/fpa/VTK/Image/ImageSkeletonToPolyData.h create mode 100644 lib/fpa/VTK/Image/ImageSkeletonToPolyData.hxx create mode 100644 plugins/fpa/ImageSkeleton.cxx create mode 100644 plugins/fpa/ImageSkeleton.h diff --git a/lib/fpa/Base/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.h b/lib/fpa/Base/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.h index 598e15d..9a12904 100644 --- a/lib/fpa/Base/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.h +++ b/lib/fpa/Base/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.h @@ -26,7 +26,7 @@ namespace fpa typedef _TMST TMinimumSpanningTree; typedef typename _TMST::TVertex TVertex; typedef std::pair< TVertex, TVertex > TBranch; - typedef itk::SimpleDataObjectDecorator< std::vector< TBranch > > TBranches; + typedef std::vector< TBranch > TBranches; typedef cpExtensions::DataStructures::ImageIndexesContainer< TVertex::Dimension > @@ -45,7 +45,6 @@ namespace fpa TVertices* GetEndPoints( ); TVertices* GetBifurcations( ); TVertices* GetCollisions( ); - TBranches* GetBranches( ); virtual void Update( ) ITK_OVERRIDE { @@ -76,6 +75,9 @@ namespace fpa // Purposely not implemented ExtractEndPointsAndBifurcationsFromMinimumSpanningTree( const Self& other ); Self& operator=( const Self& other ); + + protected: + TBranches m_Branches; }; } // ecapseman diff --git a/lib/fpa/Base/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.hxx b/lib/fpa/Base/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.hxx index 3e8b6e5..afb5252 100644 --- a/lib/fpa/Base/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.hxx +++ b/lib/fpa/Base/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.hxx @@ -65,19 +65,6 @@ GetCollisions( ) ); } -// ------------------------------------------------------------------------- -template< class _TMST > -typename -fpa::Base::ExtractEndPointsAndBifurcationsFromMinimumSpanningTree< _TMST >:: -TBranches* -fpa::Base::ExtractEndPointsAndBifurcationsFromMinimumSpanningTree< _TMST >:: -GetBranches( ) -{ - return( - dynamic_cast< TBranches* >( this->itk::ProcessObject::GetOutput( 3 ) ) - ); -} - // ------------------------------------------------------------------------- template< class _TMST > fpa::Base::ExtractEndPointsAndBifurcationsFromMinimumSpanningTree< _TMST >:: @@ -89,11 +76,9 @@ ExtractEndPointsAndBifurcationsFromMinimumSpanningTree( ) typename TVertices::Pointer ep = TVertices::New( ); typename TVertices::Pointer bf = TVertices::New( ); typename TVertices::Pointer co = TVertices::New( ); - typename TBranches::Pointer br = TBranches::New( ); this->itk::ProcessObject::SetNthOutput( 0, ep.GetPointer( ) ); this->itk::ProcessObject::SetNthOutput( 1, bf.GetPointer( ) ); this->itk::ProcessObject::SetNthOutput( 2, co.GetPointer( ) ); - this->itk::ProcessObject::SetNthOutput( 3, br.GetPointer( ) ); } // ------------------------------------------------------------------------- @@ -119,11 +104,10 @@ GenerateData( ) auto endpoints = this->GetEndPoints( ); auto bifurcations = this->GetBifurcations( ); auto collisions = this->GetCollisions( ); - auto branches = this->GetBranches( ); endpoints->Get( ).clear( ); bifurcations->Get( ).clear( ); collisions->Get( ).clear( ); - branches->Get( ).clear( ); + this->m_Branches.clear( ); // 1. Get priority queue auto& q = mst->GetNodeQueue( ); @@ -144,7 +128,7 @@ GenerateData( ) // 2.3. Prepare new branch data and prepare new end-point label++; - branches->Get( ).push_back( _TBranch( vertex, vertex ) ); + this->m_Branches.push_back( _TBranch( vertex, vertex ) ); endpoints->Get( ).push_back( vertex ); // 2.4. Backtracking @@ -160,10 +144,10 @@ GenerateData( ) bifurcations->Get( ).push_back( *pIt ); // Reorder labels - auto coll_branch = branches->Get( )[ mark ]; - branches->Get( )[ mark ] = _TBranch( coll_branch.first, *pIt ); - branches->Get( )[ label - 1 ] = _TBranch( qIt->second, *pIt ); - branches->Get( ).push_back( _TBranch( *pIt, coll_branch.second ) ); + auto coll_branch = this->m_Branches[ mark ]; + this->m_Branches[ mark ] = _TBranch( coll_branch.first, *pIt ); + this->m_Branches[ label - 1 ] = _TBranch( qIt->second, *pIt ); + this->m_Branches.push_back( _TBranch( *pIt, coll_branch.second ) ); // Mark skeleton (b,coll_branch_second) with the new label label++; @@ -195,7 +179,7 @@ GenerateData( ) double r = this->_Radius( *pIt ); this->_MarkSkeleton( *pIt, label ); this->_MarkSphere( *pIt, r, label ); - branches->Get( )[ label - 1 ].second = *pIt; + this->m_Branches[ label - 1 ].second = *pIt; // 2.4.4. Is this a seed? -> add it to endpoints auto sIt = pIt; diff --git a/lib/fpa/Base/ImageSkeleton.h b/lib/fpa/Base/ImageSkeleton.h new file mode 100644 index 0000000..d7ca832 --- /dev/null +++ b/lib/fpa/Base/ImageSkeleton.h @@ -0,0 +1,70 @@ +#ifndef __FPA__BASE__IMAGESKELETON__H__ +#define __FPA__BASE__IMAGESKELETON__H__ + +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TMST > + class ImageSkeleton + : public itk::SimpleDataObjectDecorator< std::map< typename _TMST::TVertex, std::map< typename _TMST::TVertex, typename cpExtensions::DataStructures::PolyLineParametricPath< _TMST::TVertex::Dimension >::Pointer, typename _TMST::TVertex::LexicographicCompare >, typename _TMST::TVertex::LexicographicCompare > > + { + public: + // Base types + typedef _TMST TMinimumSpanningTree; + typedef typename _TMST::TVertex TVertex; + typedef typename TVertex::LexicographicCompare TVertexCmp; + typedef + cpExtensions::DataStructures::PolyLineParametricPath< TVertex::Dimension > + TPath; + typedef + std::map< TVertex, typename TPath::Pointer, TVertexCmp > + TSkeletonRow; + typedef std::map< TVertex, TSkeletonRow, TVertexCmp > TSkeleton; + + // ITK-related types + typedef ImageSkeleton Self; + typedef itk::SimpleDataObjectDecorator< TSkeleton > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( ImageSkeleton, itk::SimpleDataObjectDecorator ); + + itkGetConstObjectMacro( MinimumSpanningTree, _TMST ); + itkSetConstObjectMacro( MinimumSpanningTree, _TMST ); + + public: + void AddBranch( const TVertex& a, const TVertex& b ); + const TPath* GetBranch( const TVertex& a, const TVertex& b ) const; + + protected: + ImageSkeleton( ); + virtual ~ImageSkeleton( ); + + private: + // Purposely not implemented + ImageSkeleton( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename _TMST::ConstPointer m_MinimumSpanningTree; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __FPA__BASE__IMAGESKELETON__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/ImageSkeleton.hxx b/lib/fpa/Base/ImageSkeleton.hxx new file mode 100644 index 0000000..cd2daec --- /dev/null +++ b/lib/fpa/Base/ImageSkeleton.hxx @@ -0,0 +1,73 @@ +#ifndef __FPA__BASE__IMAGESKELETON__HXX__ +#define __FPA__BASE__IMAGESKELETON__HXX__ + +// ------------------------------------------------------------------------- +template< class _TMST > +void fpa::Base::ImageSkeleton< _TMST >:: +AddBranch( const TVertex& a, const TVertex& b ) +{ + if( this->m_MinimumSpanningTree.IsNull( ) ) + return; + + // Check if the branch already exists + bool found = false; + auto arIt = this->Get( ).find( a ); + if( arIt != this->Get( ).end( ) ) + found = ( arIt->second.find( b ) != arIt->second.end( ) ); + if( found ) + return; + + // Create path + auto vertices = this->m_MinimumSpanningTree->GetPath( a, b ); + typename TPath::Pointer path = TPath::New( ); + for( auto vIt = vertices.begin( ); vIt != vertices.end( ); ++vIt ) + path->AddVertex( *vIt ); + + // Assign path vertices + path->SetReferenceImage( this->m_MinimumSpanningTree ); + this->Get( )[ a ][ b ] = path; + + // Create symmetric path + this->AddBranch( b, a ); +} + +// ------------------------------------------------------------------------- +template< class _TMST > +const typename fpa::Base::ImageSkeleton< _TMST >:: +TPath* fpa::Base::ImageSkeleton< _TMST >:: +GetBranch( const TVertex& a, const TVertex& b ) const +{ + if( this->m_MinimumSpanningTree.IsNull( ) ) + return( NULL ); + + auto aIt = this->Get( ).find( a ); + if( aIt != this->Get( ).end( ) ) + { + auto bIt = aIt->second.find( b ); + if( bIt != aIt->second.end( ) ) + return( bIt->second.GetPointer( ) ); + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TMST > +fpa::Base::ImageSkeleton< _TMST >:: +ImageSkeleton( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TMST > +fpa::Base::ImageSkeleton< _TMST >:: +~ImageSkeleton( ) +{ +} + +#endif // __FPA__BASE__IMAGESKELETON__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.h b/lib/fpa/Image/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.h index 312da36..002afb4 100644 --- a/lib/fpa/Image/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.h +++ b/lib/fpa/Image/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.h @@ -2,6 +2,7 @@ #define __FPA__IMAGE__EXTRACTENDPOINTSANDBIFURCATIONSFROMMINIMUMSPANNINGTREE__H__ #include +#include namespace fpa { @@ -26,6 +27,7 @@ namespace fpa typedef typename Superclass::TVertex TVertex; typedef itk::Image< unsigned short, TImage::ImageDimension > TMarkImage; + typedef fpa::Base::ImageSkeleton< _TMST > TSkeleton; public: itkNewMacro( Self ); @@ -41,6 +43,7 @@ namespace fpa public: const TImage* GetCostsImage( ); const TImage* GetDistanceMap( ); + TSkeleton* GetSkeleton( ); void SetCostsImage( TImage* image ); void SetDistanceMap( TImage* image ); diff --git a/lib/fpa/Image/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.hxx b/lib/fpa/Image/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.hxx index 16d03e8..3e7a32b 100644 --- a/lib/fpa/Image/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.hxx +++ b/lib/fpa/Image/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.hxx @@ -30,6 +30,23 @@ GetDistanceMap( ) ); } +// ------------------------------------------------------------------------- +template< class _TImage, class _TMST > +typename +fpa::Image::ExtractEndPointsAndBifurcationsFromMinimumSpanningTree< _TImage, _TMST >:: +TSkeleton* +fpa::Image::ExtractEndPointsAndBifurcationsFromMinimumSpanningTree< _TImage, _TMST >:: +GetSkeleton( ) +{ + return( + dynamic_cast< TSkeleton* >( + this->itk::ProcessObject::GetOutput( + this->GetNumberOfRequiredOutputs( ) - 1 + ) + ) + ); +} + // ------------------------------------------------------------------------- template< class _TImage, class _TMST > void @@ -56,6 +73,10 @@ ExtractEndPointsAndBifurcationsFromMinimumSpanningTree( ) m_SquaredDistanceMap( false ) { this->SetNumberOfRequiredInputs( 3 ); + unsigned int nOuts = this->GetNumberOfRequiredOutputs( ); + this->SetNumberOfRequiredOutputs( nOuts + 1 ); + typename TSkeleton::Pointer sk = TSkeleton::New( ); + this->itk::ProcessObject::SetNthOutput( nOuts, sk.GetPointer( ) ); } // ------------------------------------------------------------------------- @@ -71,8 +92,8 @@ void fpa::Image::ExtractEndPointsAndBifurcationsFromMinimumSpanningTree< _TImage, _TMST >:: GenerateData( ) { + // Create auxiliary objects auto image = this->GetCostsImage( ); - this->m_MarkImage = TMarkImage::New( ); this->m_MarkImage->SetLargestPossibleRegion( image->GetLargestPossibleRegion( ) ); this->m_MarkImage->SetRequestedRegion( image->GetRequestedRegion( ) ); @@ -82,7 +103,6 @@ GenerateData( ) this->m_MarkImage->SetSpacing( image->GetSpacing( ) ); this->m_MarkImage->Allocate( ); this->m_MarkImage->FillBuffer( 0 ); - this->m_SkeletonImage = TMarkImage::New( ); this->m_SkeletonImage->SetLargestPossibleRegion( image->GetLargestPossibleRegion( ) ); this->m_SkeletonImage->SetRequestedRegion( image->GetRequestedRegion( ) ); @@ -93,7 +113,15 @@ GenerateData( ) this->m_SkeletonImage->Allocate( ); this->m_SkeletonImage->FillBuffer( 0 ); + // Real execution this->Superclass::GenerateData( ); + + // Build skeleton + auto sk = this->GetSkeleton( ); + sk->SetMinimumSpanningTree( this->GetMinimumSpanningTree( ) ); + auto bIt = this->m_Branches.begin( ); + for( ; bIt != this->m_Branches.end( ); ++bIt ) + sk->AddBranch( bIt->first, bIt->second ); } // ------------------------------------------------------------------------- diff --git a/lib/fpa/VTK/Image/ImageSkeletonToPolyData.h b/lib/fpa/VTK/Image/ImageSkeletonToPolyData.h new file mode 100644 index 0000000..3c19b7b --- /dev/null +++ b/lib/fpa/VTK/Image/ImageSkeletonToPolyData.h @@ -0,0 +1,67 @@ +#ifndef __FPA__VTK__IMAGESKELETONTOPOLYDATA__H__ +#define __FPA__VTK__IMAGESKELETONTOPOLYDATA__H__ + +#include + +namespace fpa +{ + namespace VTK + { + namespace Image + { + /** + */ + template< class _TSkeleton > + class ImageSkeletonToPolyData + : public vtkPolyDataAlgorithm + { + public: + typedef ImageSkeletonToPolyData Self; + typedef _TSkeleton TSkeleton; + + public: + vtkTypeMacro( ImageSkeletonToPolyData, vtkPolyDataAlgorithm ); + + public: + static Self* New( ); + + const TSkeleton* GetInput( ) const; + void SetInput( const TSkeleton* sk ); + + protected: + ImageSkeletonToPolyData( ); + virtual ~ImageSkeletonToPolyData( ); + + int RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + int RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + + private: + // Purposely not implemented + ImageSkeletonToPolyData( const Self& ); + void operator=( const Self& ); + + protected: + const TSkeleton* m_Skeleton; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __FPA__VTK__IMAGESKELETONTOPOLYDATA__H__ + +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image/ImageSkeletonToPolyData.hxx b/lib/fpa/VTK/Image/ImageSkeletonToPolyData.hxx new file mode 100644 index 0000000..5e41358 --- /dev/null +++ b/lib/fpa/VTK/Image/ImageSkeletonToPolyData.hxx @@ -0,0 +1,176 @@ +#ifndef __FPA__VTK__IMAGESKELETONTOPOLYDATA__HXX__ +#define __FPA__VTK__IMAGESKELETONTOPOLYDATA__HXX__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +typename fpa::VTK::Image::ImageSkeletonToPolyData< _TSkeleton >:: +Self* fpa::VTK::Image::ImageSkeletonToPolyData< _TSkeleton >:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +const _TSkeleton* fpa::VTK::Image::ImageSkeletonToPolyData< _TSkeleton >:: +GetInput( ) const +{ + return( this->m_Skeleton ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void fpa::VTK::Image::ImageSkeletonToPolyData< _TSkeleton >:: +SetInput( const _TSkeleton* sk ) +{ + if( this->m_Skeleton != sk ) + { + this->m_Skeleton = sk; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +fpa::VTK::Image::ImageSkeletonToPolyData< _TSkeleton >:: +ImageSkeletonToPolyData( ) + : vtkPolyDataAlgorithm( ), + m_Skeleton( NULL ) +{ + this->SetNumberOfInputPorts( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +fpa::VTK::Image::ImageSkeletonToPolyData< _TSkeleton >:: +~ImageSkeletonToPolyData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +int fpa::VTK::Image::ImageSkeletonToPolyData< _TSkeleton >:: +RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + typedef typename _TSkeleton::TVertex _TVertex; + typedef typename _TSkeleton::TVertexCmp _TCmp; + typedef itk::Point< double, _TVertex::Dimension > _TPoint; + typedef + std::map< _TVertex, std::map< _TVertex, bool, _TCmp >, _TCmp > + _TMarks; + static const unsigned int dim = _TVertex::Dimension; + + if( this->m_Skeleton == NULL ) + return( 0 ); + + // Get output + vtkInformation* info = output->GetInformationObject( 0 ); + vtkPolyData* out = vtkPolyData::SafeDownCast( + info->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + + // Prepare points and cells + vtkSmartPointer< vtkPoints > points = + vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkCellArray > lines = + vtkSmartPointer< vtkCellArray >::New( ); + + // Iterator over input data + auto& sk = this->m_Skeleton->Get( ); + auto mst = this->m_Skeleton->GetMinimumSpanningTree( ); + _TMarks marks; + for( auto i = sk.begin( ); i != sk.end( ); ++i ) + { + for( auto j = i->second.begin( ); j != i->second.end( ); ++j ) + { + if( !marks[ i->first ][ j->first ] ) + { + auto path = j->second.GetPointer( ); + if( path != NULL ) + { + auto vertices = path->GetVertexList( ); + for( unsigned int v = 0; v < vertices->Size( ); ++v ) + { + auto idx = vertices->GetElement( v ); + _TPoint pnt; + mst->TransformContinuousIndexToPhysicalPoint( idx, pnt ); + if( dim == 1 ) + points->InsertNextPoint( pnt[ 0 ], 0, 0 ); + else if( dim == 2 ) + points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], 0 ); + else + points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] ); + if( v > 0 ) + { + lines->InsertNextCell( 2 ); + lines->InsertCellPoint( points->GetNumberOfPoints( ) - 2 ); + lines->InsertCellPoint( points->GetNumberOfPoints( ) - 1 ); + + } // fi + + } // rof + + } // fi + + // Mark path and its symmetric as visited + marks[ i->first ][ j->first ] = true; + marks[ j->first ][ i->first ] = true; + + } // fi + + } // rof + + } // rof + out->SetPoints( points ); + out->SetLines( lines ); + return( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +int fpa::VTK::Image::ImageSkeletonToPolyData< _TSkeleton >:: +RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + vtkInformation* info = output->GetInformationObject( 0 ); + /* TODO + info->Set( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES( ), -1 + ); + */ + + if( this->m_Skeleton != NULL ) + { + /* TODO + typename C::TScalar len = this->m_RGC->GetTotalLength( ); + typename C::TScalar s0 = this->m_RGC->Gets0( ); + typename C::TPoint p0 = this->m_RGC->Axis( s0 ); + typename C::TPoint p1 = this->m_RGC->Axis( s0 + len ); + + info->Set( + vtkStreamingDemandDrivenPipeline::WHOLE_BOUNDING_BOX( ), + double( p0[ 0 ] ), double( p1[ 0 ] ), + double( p0[ 1 ] ), double( p1[ 1 ] ), + double( p0[ 2 ] ), double( p1[ 2 ] ) + ); + */ + + } // fi + return( 1 ); +} + +#endif // __FPA__VTK__IMAGESKELETONTOPOLYDATA__HXX__ + +// eof - $RCSfile$ diff --git a/lib/fpa_Instances/Instances.i b/lib/fpa_Instances/Instances.i index 5263046..9c8d6d7 100644 --- a/lib/fpa_Instances/Instances.i +++ b/lib/fpa_Instances/Instances.i @@ -4,11 +4,14 @@ t fpa/Base/MinimumSpanningTree.h t fpa/Image/MinimumSpanningTree.h t fpa/IO/MinimumSpanningTreeReader.h t fpa/IO/MinimumSpanningTreeWriter.h +t fpa/Base/ImageSkeleton.h +t fpa/VTK/Image/ImageSkeletonToPolyData.h t itkImage.h t itkImportImageContainer.h t itkImageRegionConstIteratorWithIndex.h t itkImageConstIteratorWithIndex.h +t itkSimpleDataObjectDecorator.h d #dims=2;3 d #int=char;short;int;long @@ -33,9 +36,16 @@ c itk::ImportImageContainer< unsigned long, #i::{#mst}Data< #dims > > c itk::Image< #i::{#mst}Data< #dims >, #dims > c #b::#mst< itk::Image< #i::{#mst}Data< #dims >, #dims >, itk::Index< #dims > > c #i::#mst@{Data;{}}< #dims > +c #b::ImageSkeleton< #i::#mst< #dims > > c itk::ImageConstIteratorWithIndex< #i::#mst< #dims > > c itk::ImageRegionConstIteratorWithIndex< #i::#mst< #dims > > c fpa::IO::MinimumSpanningTree@{Reader;Writer}< #i::#mst< #dims > > +* ======================== +* == Conversion filters == +* ======================== + +c fpa::VTK::Image::ImageSkeletonToPolyData< #b::ImageSkeleton< #i::#mst< #dims > > > + * eof - $RCSfile$ diff --git a/plugins/fpa/CMakeLists.txt b/plugins/fpa/CMakeLists.txt index cc21d76..84f58c3 100644 --- a/plugins/fpa/CMakeLists.txt +++ b/plugins/fpa/CMakeLists.txt @@ -30,6 +30,8 @@ SET( ${CMAKE_CURRENT_SOURCE_DIR}/BaseImageFilter.cxx ${CMAKE_CURRENT_SOURCE_DIR}/MinimumSpanningTree.h ${CMAKE_CURRENT_SOURCE_DIR}/MinimumSpanningTree.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/ImageSkeleton.h + ${CMAKE_CURRENT_SOURCE_DIR}/ImageSkeleton.cxx ) SET(lib_QT4_HEADERS "") diff --git a/plugins/fpa/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.cxx b/plugins/fpa/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.cxx index 793493b..8078a67 100644 --- a/plugins/fpa/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.cxx +++ b/plugins/fpa/ExtractEndPointsAndBifurcationsFromMinimumSpanningTree.cxx @@ -3,6 +3,7 @@ #include #include #include +#include // ------------------------------------------------------------------------- fpaPlugins::ExtractEndPointsAndBifurcationsFromMinimumSpanningTree:: @@ -15,6 +16,7 @@ ExtractEndPointsAndBifurcationsFromMinimumSpanningTree( ) this->_AddOutput< cpPlugins::ImageIndexesContainer >( "EndPoints" ); this->_AddOutput< cpPlugins::ImageIndexesContainer >( "Bifurcations" ); this->_AddOutput< cpPlugins::ImageIndexesContainer >( "Collisions" ); + this->_AddOutput< fpaPlugins::ImageSkeleton >( "Skeleton" ); this->m_Parameters.ConfigureAsBool( "SquaredDistanceMap" ); this->m_Parameters.SetBool( "SquaredDistanceMap", false ); @@ -75,6 +77,7 @@ _GD0( _TImage* image ) this->GetOutputData( "EndPoints" )->SetITK( filter->GetEndPoints( ) ); this->GetOutputData( "Bifurcations" )->SetITK( filter->GetBifurcations( ) ); this->GetOutputData( "Collisions" )->SetITK( filter->GetCollisions( ) ); + this->GetOutputData( "Skeleton" )->SetITK( filter->GetSkeleton( ) ); return( "" ); } diff --git a/plugins/fpa/ImageSkeleton.cxx b/plugins/fpa/ImageSkeleton.cxx new file mode 100644 index 0000000..f121d66 --- /dev/null +++ b/plugins/fpa/ImageSkeleton.cxx @@ -0,0 +1,75 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +void fpaPlugins::ImageSkeleton:: +SetITK( itk::LightObject* o ) +{ + typedef + fpa::Base::ImageSkeleton< fpa::Image::MinimumSpanningTree< 2 > > _I2; + typedef + fpa::Base::ImageSkeleton< fpa::Image::MinimumSpanningTree< 3 > > _I3; + + bool r = this->_SetITK< _I2 >( o ); + if( !r ) r = this->_SetITK< _I3 >( o ); + if( !r ) + this->Superclass::SetITK( NULL ); +} + +// ------------------------------------------------------------------------- +void fpaPlugins::ImageSkeleton:: +SetVTK( vtkObjectBase* o ) +{ + // Do nothing: this only has sense in ITK +} + +// ------------------------------------------------------------------------- +fpaPlugins::ImageSkeleton:: +ImageSkeleton( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +fpaPlugins::ImageSkeleton:: +~ImageSkeleton( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TMST > +bool fpaPlugins::ImageSkeleton:: +_SetITK( itk::LightObject* o ) +{ + typedef fpa::VTK::Image::ImageSkeletonToPolyData< _TMST > _TFilter; + + _TMST* mst = dynamic_cast< _TMST* >( o ); + if( mst != NULL ) + { + _TFilter* f = dynamic_cast< _TFilter* >( this->m_ITKvVTK.GetPointer( ) ); + if( f == NULL ) + { + vtkSmartPointer< _TFilter > nf = _TFilter::New( ); + this->m_ITKvVTK = nf.GetPointer( ); + f = nf.GetPointer( ); + + } // fi + f->SetInput( mst ); + f->Update( ); + + // Keep object track + this->m_ITKObject = o; + this->m_VTKObject = f->GetOutput( ); + return( true ); + } + else + { + this->Superclass::SetITK( NULL ); + this->Superclass::SetVTK( NULL ); + return( false ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/plugins/fpa/ImageSkeleton.h b/plugins/fpa/ImageSkeleton.h new file mode 100644 index 0000000..e8a1345 --- /dev/null +++ b/plugins/fpa/ImageSkeleton.h @@ -0,0 +1,52 @@ +#ifndef __FPAPLUGINS__IMAGESKELETON__H__ +#define __FPAPLUGINS__IMAGESKELETON__H__ + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +namespace fpaPlugins +{ + /** + */ + class fpaPlugins_EXPORT ImageSkeleton + : public cpPlugins::DataObject + { + public: + typedef ImageSkeleton Self; + typedef cpPlugins::DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( ImageSkeleton, cpPlugins::DataObject ); + cpPlugins_Id_Macro( ImageSkeleton, ImageSkeleton ); + + public: + virtual void SetITK( itk::LightObject* o ) override; + virtual void SetVTK( vtkObjectBase* o ) override; + + protected: + ImageSkeleton( ); + virtual ~ImageSkeleton( ); + + template< class _TMST > + inline bool _SetITK( itk::LightObject* o ); + + private: + // Purposely not implemented + ImageSkeleton( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< vtkPolyDataAlgorithm > m_ITKvVTK; + }; + +} // ecapseman + +#endif // __FPAPLUGINS__IMAGESKELETON__H__ + +// eof - $RCSfile$ diff --git a/plugins/fpa/MinimumSpanningTree.h b/plugins/fpa/MinimumSpanningTree.h index 2904600..e391ae6 100644 --- a/plugins/fpa/MinimumSpanningTree.h +++ b/plugins/fpa/MinimumSpanningTree.h @@ -32,7 +32,7 @@ namespace fpaPlugins virtual ~MinimumSpanningTree( ); template< class _TMST > - bool _SetITK( itk::LightObject* o ); + inline bool _SetITK( itk::LightObject* o ); private: // Purposely not implemented -- 2.47.1