From: Leonardo Flórez-Valencia Date: Thu, 17 Aug 2017 02:27:12 +0000 (-0500) Subject: ... X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=2047276c8f1a02432fbcc7014722d460d6c1e60f;p=FrontAlgorithms.git ... --- diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..d7d1948 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,12 @@ +## ========================================================================= +## @author Leonardo Florez Valencia +## @email florez-l@javeriana.edu.co +## ========================================================================= + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ) +subdirs(fpa) + +## eof - $RCSfile$ diff --git a/lib/fpa/CMakeLists.txt b/lib/fpa/CMakeLists.txt new file mode 100644 index 0000000..bb03ddd --- /dev/null +++ b/lib/fpa/CMakeLists.txt @@ -0,0 +1,78 @@ +## ========================================================================= +## @author Leonardo Florez Valencia +## @email florez-l@javeriana.edu.co +## ========================================================================= + +configure_file(Version.cxx.in "${CMAKE_CURRENT_BINARY_DIR}/Version.cxx" @ONLY) +configure_file(Config.h.in "${CMAKE_CURRENT_BINARY_DIR}/Config.h" @ONLY) +file(GLOB_RECURSE _common_src "${CMAKE_CURRENT_SOURCE_DIR}/Common/*.cxx") +file(GLOB_RECURSE _filters_src "${CMAKE_CURRENT_SOURCE_DIR}/Filters/*.cxx") +file(GLOB_RECURSE _functors_src "${CMAKE_CURRENT_SOURCE_DIR}/Functors/*.cxx") +file(GLOB_RECURSE _common_hdr "${CMAKE_CURRENT_SOURCE_DIR}/Common/*.h") +file(GLOB_RECURSE _filters_hdr "${CMAKE_CURRENT_SOURCE_DIR}/Filters/*.h") +file(GLOB_RECURSE _functors_hdr "${CMAKE_CURRENT_SOURCE_DIR}/Functors/*.h") +file(GLOB_RECURSE _common_hrc "${CMAKE_CURRENT_SOURCE_DIR}/Common/*.hxx") +file(GLOB_RECURSE _filters_hrc "${CMAKE_CURRENT_SOURCE_DIR}/Filters/*.hxx") +file(GLOB_RECURSE _functors_hrc "${CMAKE_CURRENT_SOURCE_DIR}/Functors/*.hxx") +if(VTK_FOUND) + file(GLOB_RECURSE _vtk_src "${CMAKE_CURRENT_SOURCE_DIR}/VTK/*.cxx") + file(GLOB_RECURSE _vtk_hdr "${CMAKE_CURRENT_SOURCE_DIR}/VTK/*.h") + file(GLOB_RECURSE _vtk_hrc "${CMAKE_CURRENT_SOURCE_DIR}/VTK/*.hxx") +endif(VTK_FOUND) + +## ===================== +## == Compile library == +## ===================== + +add_library( + fpa SHARED + "${CMAKE_CURRENT_BINARY_DIR}/Version.cxx" + "${CMAKE_CURRENT_BINARY_DIR}/Config.h" + ${_common_src} + ${_filters_src} + ${_functors_src} + ${_vtk_src} + ) +generate_export_header(fpa) +set_property(TARGET fpa PROPERTY VERSION ${prj_VERSION}) +set_property(TARGET fpa PROPERTY SOVERSION ${prj_SHORT_VERSION}) +set_property( + TARGET fpa PROPERTY INTERFACE_fpa_MAJOR_VERSION ${prj_MAJ_VERSION} + ) +set_property( + TARGET fpa APPEND PROPERTY COMPATIBLE_INTERFACE_STRING ${prj_MAJ_VERSION} + ) +target_link_libraries(fpa PUBLIC ${ITK_LIBRARIES}) + +## ======================== +## == Installation rules == +## ======================== + +install( + TARGETS fpa + EXPORT "${targets_export_name}" + LIBRARY DESTINATION "lib" + ARCHIVE DESTINATION "lib" + RUNTIME DESTINATION "bin" + INCLUDES DESTINATION "${include_install_dir}" + ) +install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + DESTINATION "${include_install_dir}" + FILES_MATCHING PATTERN "*.h" + ) +install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + DESTINATION "${include_install_dir}" + FILES_MATCHING PATTERN "*.hxx" + ) +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/fpa_export.h" + DESTINATION "${include_install_dir}/fpa" + ) +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/Config.h" + DESTINATION "${include_install_dir}/fpa" + ) + +## eof - $RCSfile$ diff --git a/lib/fpa/Common/Image/PolyLineParametricPathReader.h b/lib/fpa/Common/Image/PolyLineParametricPathReader.h new file mode 100644 index 0000000..fe3678b --- /dev/null +++ b/lib/fpa/Common/Image/PolyLineParametricPathReader.h @@ -0,0 +1,85 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Common__Image__PolyLineParametricPathReader__h__ +#define __fpa__Common__Image__PolyLineParametricPathReader__h__ + +#include + +namespace fpa +{ + namespace Common + { + namespace Image + { + /** + */ + template< class _TPath > + class PolyLineParametricPathReader + : public itk::ProcessObject + { + public: + // Basic types + typedef PolyLineParametricPathReader Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TPath TPath; + + public: + itkNewMacro( Self ); + itkTypeMacro( PolyLineParametricPathReader, itk::ProcessObject ); + + itkGetConstMacro( FileName, std::string ); + itkSetMacro( FileName, std::string ); + + public: + TPath* GetOutput( ); + TPath* GetOutput( unsigned int i ); + + virtual void GraftOutput( itk::DataObject* out ); + virtual void GraftOutput( + const typename Superclass::DataObjectIdentifierType& key, + itk::DataObject* out + ); + virtual void GraftNthOutput( unsigned int i, itk::DataObject* out ); + virtual itk::DataObject::Pointer MakeOutput( + itk::ProcessObject::DataObjectPointerArraySizeType i + ) override; + + virtual void Update( ) override + { this->GenerateData( ); } + + protected: + PolyLineParametricPathReader( ); + virtual ~PolyLineParametricPathReader( ); + + virtual void GenerateData( ) override; + + // Do nothing + virtual void GenerateOutputInformation( ) override + { } + + private: + // Purposely not implemented + PolyLineParametricPathReader( const Self& ); + void operator=( const Self& ); + + protected: + std::string m_FileName; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__Common__Image__PolyLineParametricPathReader__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Common/Image/PolyLineParametricPathReader.hxx b/lib/fpa/Common/Image/PolyLineParametricPathReader.hxx new file mode 100644 index 0000000..b931ea1 --- /dev/null +++ b/lib/fpa/Common/Image/PolyLineParametricPathReader.hxx @@ -0,0 +1,173 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Common__Image__PolyLineParametricPathReader__hxx__ +#define __fpa__Common__Image__PolyLineParametricPathReader__hxx__ + +// ------------------------------------------------------------------------- +template< class _TPath > +_TPath* fpa::Common::Image::PolyLineParametricPathReader< _TPath >:: +GetOutput( ) +{ + return( + itkDynamicCastInDebugMode< TPath* >( this->GetPrimaryOutput( ) ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +_TPath* fpa::Common::Image::PolyLineParametricPathReader< _TPath >:: +GetOutput( unsigned int i ) +{ + return( + itkDynamicCastInDebugMode< TPath* >( + this->itk::ProcessObject::GetOutput( i ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +void fpa::Common::Image::PolyLineParametricPathReader< _TPath >:: +GraftOutput( itk::DataObject* out ) +{ + this->GraftNthOutput( 0, out ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +void fpa::Common::Image::PolyLineParametricPathReader< _TPath >:: +GraftOutput( + const typename Superclass::DataObjectIdentifierType& key, + itk::DataObject* out + ) +{ + if( out == NULL ) + { + itkExceptionMacro( + << "Requested to graft output that is a NULL pointer" + ); + + } // fi + itk::DataObject* output = this->itk::ProcessObject::GetOutput( key ); + output->Graft( out ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +void fpa::Common::Image::PolyLineParametricPathReader< _TPath >:: +GraftNthOutput( unsigned int i, itk::DataObject* out ) +{ + if( i >= this->GetNumberOfIndexedOutputs( ) ) + { + itkExceptionMacro( + << "Requested to graft output " << i + << " but this filter only has " + << this->GetNumberOfIndexedOutputs( ) + << " indexed Outputs." + ); + + } // fi + this->GraftOutput( this->MakeNameFromOutputIndex( i ), out ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +itk::DataObject::Pointer +fpa::Common::Image::PolyLineParametricPathReader< _TPath >:: +MakeOutput( itk::ProcessObject::DataObjectPointerArraySizeType i ) +{ + return( TPath::New( ).GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +fpa::Common::Image::PolyLineParametricPathReader< _TPath >:: +PolyLineParametricPathReader( ) + : Superclass( ) +{ + typename TPath::Pointer out = + static_cast< TPath* >( this->MakeOutput( 0 ).GetPointer( ) ); + this->itk::ProcessObject::SetNumberOfRequiredInputs( 0 ); + this->itk::ProcessObject::SetNumberOfRequiredOutputs( 1 ); + this->itk::ProcessObject::SetNthOutput( 0, out.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +fpa::Common::Image::PolyLineParametricPathReader< _TPath >:: +~PolyLineParametricPathReader( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TPath > +void fpa::Common::Image::PolyLineParametricPathReader< _TPath >:: +GenerateData( ) +{ + std::string buffer; + std::ifstream file_stream( this->m_FileName.c_str( ) ); + if( !file_stream ) + { + itkExceptionMacro( + << "Error reading skeleton from \"" << this->m_FileName << "\"" + ); + return; + + } // fi + file_stream.seekg( 0, std::ios::end ); + buffer.reserve( ( unsigned int )( file_stream.tellg( ) ) ); + file_stream.seekg( 0, std::ios::beg ); + buffer.assign( + ( std::istreambuf_iterator< char >( file_stream ) ), + std::istreambuf_iterator< char >( ) + ); + file_stream.close( ); + + std::istringstream in( buffer ); + unsigned int dim; + in >> dim; + if( dim != TPath::Dimension ) + { + itkExceptionMacro( + << "Mismatched path dimension: " << dim + << " != " << TPath::Dimension + ); + return; + + } // fi + + // Read spatial parameters + typename TPath::TSpacing spa; + typename TPath::TDirection dir; + typename TPath::TPoint ori; + for( unsigned int d = 0; d < dim; ++d ) + in >> spa[ d ]; + for( unsigned int d = 0; d < dim; ++d ) + for( unsigned int e = 0; e < dim; ++e ) + in >> dir[ d ][ e ]; + for( unsigned int d = 0; d < dim; ++d ) + in >> ori[ d ]; + + // Read path + TPath* path = this->GetOutput( ); + path->SetSpacing( spa ); + path->SetOrigin( ori ); + path->SetDirection( dir ); + + unsigned long pathSize; + in >> pathSize; + for( unsigned long id = 0; id < pathSize; ++id ) + { + typename TPath::TIndex idx; + for( unsigned int d = 0; d < dim; ++d ) + in >> idx[ d ]; + path->AddVertex( idx ); + + } // rof +} + +#endif // __fpa__Common__Image__PolyLineParametricPathReader__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Common/Image/PolyLineParametricPathWriter.h b/lib/fpa/Common/Image/PolyLineParametricPathWriter.h new file mode 100644 index 0000000..f8ba177 --- /dev/null +++ b/lib/fpa/Common/Image/PolyLineParametricPathWriter.h @@ -0,0 +1,69 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Common__Image__PolyLineParametricPathWriter__h__ +#define __fpa__Common__Image__PolyLineParametricPathWriter__h__ + +#include + +namespace fpa +{ + namespace Common + { + namespace Image + { + /** + */ + template< class _TPath > + class PolyLineParametricPathWriter + : public itk::ProcessObject + { + public: + // Basic types + typedef PolyLineParametricPathWriter Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TPath TPath; + + public: + itkNewMacro( Self ); + itkTypeMacro( PolyLineParametricPathWriter, itk::ProcessObject ); + + itkGetConstMacro( FileName, std::string ); + itkSetMacro( FileName, std::string ); + + public: + const TPath* GetInput( ) const; + void SetInput( const TPath* path ); + virtual void Update( ) override; + + protected: + PolyLineParametricPathWriter( ); + virtual ~PolyLineParametricPathWriter( ); + + virtual void GenerateData( ) override; + + private: + // Purposely not implemented + PolyLineParametricPathWriter( const Self& ); + void operator=( const Self& ); + + protected: + std::string m_FileName; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__Common__Image__PolyLineParametricPathWriter__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Common/Image/PolyLineParametricPathWriter.hxx b/lib/fpa/Common/Image/PolyLineParametricPathWriter.hxx new file mode 100644 index 0000000..94b6a04 --- /dev/null +++ b/lib/fpa/Common/Image/PolyLineParametricPathWriter.hxx @@ -0,0 +1,111 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Common__Image__PolyLineParametricPathWriter__hxx__ +#define __fpa__Common__Image__PolyLineParametricPathWriter__hxx__ + +#include + +// ------------------------------------------------------------------------- +template< class _TPath > +const _TPath* fpa::Common::Image::PolyLineParametricPathWriter< _TPath >:: +GetInput( ) const +{ + return( + dynamic_cast< const TPath* >( + this->itk::ProcessObject::GetInput( 0 ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +void fpa::Common::Image::PolyLineParametricPathWriter< _TPath >:: +SetInput( const _TPath* path ) +{ + this->itk::ProcessObject::SetNthInput( 0, const_cast< TPath* >( path ) ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +void fpa::Common::Image::PolyLineParametricPathWriter< _TPath >:: +Update( ) +{ + TPath* input = const_cast< TPath* >( this->GetInput( ) ); + if( input != NULL ) + { + input->UpdateOutputInformation( ); + input->UpdateOutputData( ); + this->GenerateData( ); + this->ReleaseInputs( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TPath > +fpa::Common::Image::PolyLineParametricPathWriter< _TPath >:: +PolyLineParametricPathWriter( ) + : Superclass( ), + m_FileName( "" ) +{ + this->SetNumberOfRequiredInputs( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +fpa::Common::Image::PolyLineParametricPathWriter< _TPath >:: +~PolyLineParametricPathWriter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TPath > +void fpa::Common::Image::PolyLineParametricPathWriter< _TPath >:: +GenerateData( ) +{ + const TPath* path = this->GetInput( ); + + // Write base information + std::stringstream out1, out2; + out1 << TPath::Dimension << std::endl; + typename TPath::TSpacing spa = path->GetSpacing( ); + for( unsigned int d = 0; d < TPath::Dimension; ++d ) + out1 << spa[ d ] << " "; + out1 << std::endl; + typename TPath::TDirection dir = path->GetDirection( ); + for( unsigned int d = 0; d < TPath::Dimension; ++d ) + for( unsigned int e = 0; e < TPath::Dimension; ++e ) + out1 << dir[ d ][ e ] << " "; + out1 << std::endl; + typename TPath::TPoint ori = path->GetOrigin( ); + for( unsigned int d = 0; d < TPath::Dimension; ++d ) + out1 << ori[ d ] << " "; + out1 << std::endl; + + // Write path + unsigned int size = path->GetSize( ); + out2 << size << std::endl; + for( unsigned int i = 0; i < path->GetSize( ); ++i ) + { + typename TPath::TIndex v = path->GetVertex( i ); + for( unsigned int d = 0; d < TPath::Dimension; ++d ) + out2 << v[ d ] << " "; + + } // rof + + // Real write + std::ofstream file_stream( this->m_FileName.c_str( ), std::ofstream::binary ); + if( !file_stream ) + itkExceptionMacro( + << "Unable to write skeleton to \"" + << this->m_FileName + << "\"" + ); + file_stream.write( out1.str( ).c_str( ), out1.str( ).size( ) ); +} + +#endif // __fpa__Common__Image__PolyLineParametricPathWriter__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Common/Image/SkeletonReader.h b/lib/fpa/Common/Image/SkeletonReader.h new file mode 100644 index 0000000..cc64aae --- /dev/null +++ b/lib/fpa/Common/Image/SkeletonReader.h @@ -0,0 +1,85 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Common__Image__SkeletonReader__h__ +#define __fpa__Common__Image__SkeletonReader__h__ + +#include + +namespace fpa +{ + namespace Common + { + namespace Image + { + /** + */ + template< class _TSkeleton > + class SkeletonReader + : public itk::ProcessObject + { + public: + // Basic types + typedef SkeletonReader Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TSkeleton TSkeleton; + + public: + itkNewMacro( Self ); + itkTypeMacro( SkeletonReader, itk::ProcessObject ); + + itkGetConstMacro( FileName, std::string ); + itkSetMacro( FileName, std::string ); + + public: + TSkeleton* GetOutput( ); + TSkeleton* GetOutput( unsigned int i ); + + virtual void GraftOutput( itk::DataObject* out ); + virtual void GraftOutput( + const typename Superclass::DataObjectIdentifierType& key, + itk::DataObject* out + ); + virtual void GraftNthOutput( unsigned int i, itk::DataObject* out ); + virtual itk::DataObject::Pointer MakeOutput( + itk::ProcessObject::DataObjectPointerArraySizeType i + ) override; + + virtual void Update( ) override + { this->GenerateData( ); } + + protected: + SkeletonReader( ); + virtual ~SkeletonReader( ); + + virtual void GenerateData( ) override; + + // Do nothing + virtual void GenerateOutputInformation( ) override + { } + + private: + // Purposely not implemented + SkeletonReader( const Self& ); + void operator=( const Self& ); + + protected: + std::string m_FileName; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__Common__Image__SkeletonReader__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Common/Image/SkeletonReader.hxx b/lib/fpa/Common/Image/SkeletonReader.hxx new file mode 100644 index 0000000..ee886c5 --- /dev/null +++ b/lib/fpa/Common/Image/SkeletonReader.hxx @@ -0,0 +1,208 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Common__Image__SkeletonReader__hxx__ +#define __fpa__Common__Image__SkeletonReader__hxx__ + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +_TSkeleton* fpa::Common::Image::SkeletonReader< _TSkeleton >:: +GetOutput( ) +{ + return( + itkDynamicCastInDebugMode< TSkeleton* >( this->GetPrimaryOutput( ) ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +_TSkeleton* fpa::Common::Image::SkeletonReader< _TSkeleton >:: +GetOutput( unsigned int i ) +{ + return( + itkDynamicCastInDebugMode< TSkeleton* >( + this->itk::ProcessObject::GetOutput( i ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void fpa::Common::Image::SkeletonReader< _TSkeleton >:: +GraftOutput( itk::DataObject* out ) +{ + this->GraftNthOutput( 0, out ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void fpa::Common::Image::SkeletonReader< _TSkeleton >:: +GraftOutput( + const typename Superclass::DataObjectIdentifierType& key, + itk::DataObject* out + ) +{ + if( out == NULL ) + { + itkExceptionMacro( + << "Requested to graft output that is a NULL pointer" + ); + + } // fi + itk::DataObject* output = this->itk::ProcessObject::GetOutput( key ); + output->Graft( out ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void fpa::Common::Image::SkeletonReader< _TSkeleton >:: +GraftNthOutput( unsigned int i, itk::DataObject* out ) +{ + if( i >= this->GetNumberOfIndexedOutputs( ) ) + { + itkExceptionMacro( + << "Requested to graft output " << i + << " but this filter only has " + << this->GetNumberOfIndexedOutputs( ) + << " indexed Outputs." + ); + + } // fi + this->GraftOutput( this->MakeNameFromOutputIndex( i ), out ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +itk::DataObject::Pointer +fpa::Common::Image::SkeletonReader< _TSkeleton >:: +MakeOutput( itk::ProcessObject::DataObjectPointerArraySizeType i ) +{ + return( TSkeleton::New( ).GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +fpa::Common::Image::SkeletonReader< _TSkeleton >:: +SkeletonReader( ) + : Superclass( ) +{ + typename TSkeleton::Pointer out = + static_cast< TSkeleton* >( this->MakeOutput( 0 ).GetPointer( ) ); + this->itk::ProcessObject::SetNumberOfRequiredInputs( 0 ); + this->itk::ProcessObject::SetNumberOfRequiredOutputs( 1 ); + this->itk::ProcessObject::SetNthOutput( 0, out.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +fpa::Common::Image::SkeletonReader< _TSkeleton >:: +~SkeletonReader( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void fpa::Common::Image::SkeletonReader< _TSkeleton >:: +GenerateData( ) +{ + typedef typename TSkeleton::TPath _TPath; + typedef typename _TPath::TIndex _TIndex; + typedef typename _TPath::TSpacing _TSpacing; + typedef typename _TPath::TPoint _TPoint; + typedef typename _TPath::TDirection _TDirection; + + std::string buffer; + std::ifstream file_stream( this->m_FileName.c_str( ) ); + if( !file_stream ) + { + itkExceptionMacro( + << "Error reading skeleton from \"" << this->m_FileName << "\"" + ); + return; + + } // fi + file_stream.seekg( 0, std::ios::end ); + buffer.reserve( ( unsigned int )( file_stream.tellg( ) ) ); + file_stream.seekg( 0, std::ios::beg ); + buffer.assign( + ( std::istreambuf_iterator< char >( file_stream ) ), + std::istreambuf_iterator< char >( ) + ); + file_stream.close( ); + + std::istringstream in( buffer ); + unsigned int dim; + in >> dim; + if( dim != TSkeleton::Dimension ) + { + itkExceptionMacro( + << "Mismatched skeletons dimension: " << dim + << " != " << TSkeleton::Dimension + ); + return; + + } // fi + + // Read spatial parameters + _TSpacing spa; + _TDirection dir; + _TPoint ori; + for( unsigned int d = 0; d < dim; ++d ) + in >> spa[ d ]; + for( unsigned int d = 0; d < dim; ++d ) + for( unsigned int e = 0; e < dim; ++e ) + in >> dir[ d ][ e ]; + for( unsigned int d = 0; d < dim; ++d ) + in >> ori[ d ]; + + // Read end-points, just to ignore + unsigned int n; + in >> n; + for( unsigned int i = 0; i < n; ++i ) + { + _TIndex idx; + for( unsigned int d = 0; d < dim; ++d ) + in >> idx[ d ]; + + } // rof + + // Read bifurcations, just to ignore + in >> n; + for( unsigned int i = 0; i < n; ++i ) + { + _TIndex idx; + for( unsigned int d = 0; d < dim; ++d ) + in >> idx[ d ]; + + } // rof + + // Read paths + TSkeleton* out = this->GetOutput( ); + unsigned int nPaths; + in >> nPaths; + for( unsigned int p = 0; p < nPaths; ++p ) + { + typename _TPath::Pointer path = _TPath::New( ); + path->SetSpacing( spa ); + path->SetOrigin( ori ); + path->SetDirection( dir ); + + unsigned long pathSize; + in >> pathSize; + for( unsigned long id = 0; id < pathSize; ++id ) + { + _TIndex idx; + for( unsigned int d = 0; d < dim; ++d ) + in >> idx[ d ]; + path->AddVertex( idx ); + + } // rof + out->AddBranch( path ); + + } // rof +} + +#endif // __fpa__Common__Image__SkeletonReader__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Common/Image/SkeletonWriter.h b/lib/fpa/Common/Image/SkeletonWriter.h new file mode 100644 index 0000000..6348daf --- /dev/null +++ b/lib/fpa/Common/Image/SkeletonWriter.h @@ -0,0 +1,74 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Common__Image__SkeletonWriter__h__ +#define __fpa__Common__Image__SkeletonWriter__h__ + +#include + +namespace fpa +{ + namespace Common + { + namespace Image + { + /** + */ + template< class _TSkeleton > + class SkeletonWriter + : public itk::ProcessObject + { + public: + // Basic types + typedef SkeletonWriter Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TSkeleton TSkeleton; + typedef typename TSkeleton::TEdges TEdges; + typedef typename TSkeleton::TMatrix TMatrix; + typedef typename TSkeleton::TMatrixRow TMatrixRow; + typedef typename TSkeleton::TPath TPath; + typedef typename TSkeleton::TVertex TVertex; + + public: + itkNewMacro( Self ); + itkTypeMacro( SkeletonWriter, itk::ProcessObject ); + + itkGetConstMacro( FileName, std::string ); + itkSetMacro( FileName, std::string ); + + public: + const TSkeleton* GetInput( ) const; + void SetInput( const TSkeleton* skeleton ); + virtual void Update( ) override; + + protected: + SkeletonWriter( ); + virtual ~SkeletonWriter( ); + + virtual void GenerateData( ) override; + + private: + // Purposely not implemented + SkeletonWriter( const Self& ); + void operator=( const Self& ); + + protected: + std::string m_FileName; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__Common__Image__SkeletonWriter__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Common/Image/SkeletonWriter.hxx b/lib/fpa/Common/Image/SkeletonWriter.hxx new file mode 100644 index 0000000..4f392ed --- /dev/null +++ b/lib/fpa/Common/Image/SkeletonWriter.hxx @@ -0,0 +1,161 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Common__Image__SkeletonWriter__hxx__ +#define __fpa__Common__Image__SkeletonWriter__hxx__ + +#include + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +const _TSkeleton* fpa::Common::Image::SkeletonWriter< _TSkeleton >:: +GetInput( ) const +{ + return( + dynamic_cast< const TSkeleton* >( + this->itk::ProcessObject::GetInput( 0 ) + ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void fpa::Common::Image::SkeletonWriter< _TSkeleton >:: +SetInput( const _TSkeleton* skeleton ) +{ + this->itk::ProcessObject::SetNthInput( + 0, const_cast< TSkeleton* >( skeleton ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void fpa::Common::Image::SkeletonWriter< _TSkeleton >:: +Update( ) +{ + TSkeleton* input = const_cast< TSkeleton* >( this->GetInput( ) ); + if( input != NULL ) + { + input->UpdateOutputInformation( ); + input->UpdateOutputData( ); + this->GenerateData( ); + this->ReleaseInputs( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +fpa::Common::Image::SkeletonWriter< _TSkeleton >:: +SkeletonWriter( ) + : Superclass( ), + m_FileName( "" ) +{ + this->SetNumberOfRequiredInputs( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +fpa::Common::Image::SkeletonWriter< _TSkeleton >:: +~SkeletonWriter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void fpa::Common::Image::SkeletonWriter< _TSkeleton >:: +GenerateData( ) +{ + const TSkeleton* sk = this->GetInput( ); + typename TMatrix::const_iterator mIt = sk->BeginEdgesRows( ); + typename TMatrixRow::const_iterator rIt = mIt->second.begin( ); + typename TEdges::const_iterator eIt = rIt->second.begin( ); + const TPath* path = *eIt; + + // Write base information + std::stringstream out1, out2; + out1 << TSkeleton::Dimension << std::endl; + typename TPath::TSpacing spa = path->GetSpacing( ); + for( unsigned int d = 0; d < TSkeleton::Dimension; ++d ) + out1 << spa[ d ] << " "; + out1 << std::endl; + typename TPath::TDirection dir = path->GetDirection( ); + for( unsigned int d = 0; d < TSkeleton::Dimension; ++d ) + for( unsigned int e = 0; e < TSkeleton::Dimension; ++e ) + out1 << dir[ d ][ e ] << " "; + out1 << std::endl; + typename TPath::TPoint ori = path->GetOrigin( ); + for( unsigned int d = 0; d < TSkeleton::Dimension; ++d ) + out1 << ori[ d ] << " "; + out1 << std::endl; + + // End points + std::vector< TVertex > end_points = sk->GetEndPoints( ); + out1 << end_points.size( ) << std::endl; + typename std::vector< TVertex >::const_iterator epIt = end_points.begin( ); + for( ; epIt != end_points.end( ); ++epIt ) + { + for( unsigned int d = 0; d < TSkeleton::Dimension; ++d ) + out1 << ( *epIt )[ d ] << " "; + out1 << std::endl; + + } // rof + + // Bifurcations + std::vector< TVertex > bifurcations = sk->GetBifurcations( ); + out1 << bifurcations.size( ) << std::endl; + typename std::vector< TVertex >::const_iterator bIt = bifurcations.begin( ); + for( ; bIt != bifurcations.end( ); ++bIt ) + { + for( unsigned int d = 0; d < TSkeleton::Dimension; ++d ) + out1 << ( *bIt )[ d ] << " "; + out1 << std::endl; + + } // rof + + // Write paths + unsigned long pathCount = 0; + mIt = sk->BeginEdgesRows( ); + for( ; mIt != sk->EndEdgesRows( ); ++mIt ) + { + typename TMatrixRow::const_iterator rIt = mIt->second.begin( ); + for( ; rIt != mIt->second.end( ); ++rIt ) + { + typename TEdges::const_iterator eIt = rIt->second.begin( ); + for( ; eIt != rIt->second.end( ); ++eIt ) + { + TPath* path = *eIt; + pathCount++; + unsigned int size = path->GetSize( ); + out2 << size << std::endl; + for( unsigned int i = 0; i < path->GetSize( ); ++i ) + { + TVertex v = path->GetVertex( i ); + for( unsigned int d = 0; d < TSkeleton::Dimension; ++d ) + out2 << v[ d ] << " "; + + } // rof + out2 << std::endl; + + } // rof + + } // rof + + } // rof + out1 << pathCount << std::endl << out2.str( ); + + // Real write + std::ofstream file_stream( this->m_FileName.c_str( ), std::ofstream::binary ); + if( !file_stream ) + itkExceptionMacro( + << "Unable to write skeleton to \"" + << this->m_FileName + << "\"" + ); + file_stream.write( out1.str( ).c_str( ), out1.str( ).size( ) ); +} + +#endif // __fpa__Common__Image__SkeletonWriter__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Common/IncrementalMeanAndVariance.cxx b/lib/fpa/Common/IncrementalMeanAndVariance.cxx new file mode 100644 index 0000000..ea88f03 --- /dev/null +++ b/lib/fpa/Common/IncrementalMeanAndVariance.cxx @@ -0,0 +1,74 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#include +#include + +// ------------------------------------------------------------------------- +fpa::Common::IncrementalMeanAndVariance:: +IncrementalMeanAndVariance( ) +{ + this->Clear( ); +} + +// ------------------------------------------------------------------------- +fpa::Common::IncrementalMeanAndVariance:: +~IncrementalMeanAndVariance( ) +{ +} + +// ------------------------------------------------------------------------- +double fpa::Common::IncrementalMeanAndVariance:: +GetMean( ) const +{ + return( this->m_M ); +} + +// ------------------------------------------------------------------------- +double fpa::Common::IncrementalMeanAndVariance:: +GetVariance( ) const +{ + return( this->m_V ); +} + +// ------------------------------------------------------------------------- +double fpa::Common::IncrementalMeanAndVariance:: +GetDeviation( ) const +{ + return( std::sqrt( this->m_V ) ); +} + +// ------------------------------------------------------------------------- +unsigned long fpa::Common::IncrementalMeanAndVariance:: +GetNumberOfSamples( ) const +{ + return( ( unsigned long )( this->m_N ) ); +} + +// ------------------------------------------------------------------------- +void fpa::Common::IncrementalMeanAndVariance:: +Clear( ) +{ + this->m_M = double( 0 ); + this->m_V = double( 0 ); + this->m_N = double( 0 ); +} + +// ------------------------------------------------------------------------- +void fpa::Common::IncrementalMeanAndVariance:: +AddValue( double v ) +{ + this->m_N += double( 1 ); + double d = v - this->m_M; + if( this->m_N > double( 1 ) ) + { + double o = ( this->m_N - double( 2 ) ) / ( this->m_N - double( 1 ) ); + this->m_V = ( o * this->m_V ) + ( ( d * d ) / this->m_N ); + } + else + this->m_V = double( 0 ); + this->m_M += d / this->m_N; +} + +// eof - $RCSfile$ diff --git a/lib/fpa/Common/IncrementalMeanAndVariance.h b/lib/fpa/Common/IncrementalMeanAndVariance.h new file mode 100644 index 0000000..83383c3 --- /dev/null +++ b/lib/fpa/Common/IncrementalMeanAndVariance.h @@ -0,0 +1,44 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Common__IncrementalMeanAndVariance__h__ +#define __fpa__Common__IncrementalMeanAndVariance__h__ + +#include + +namespace fpa +{ + namespace Common + { + /** + */ + class FPA_EXPORT IncrementalMeanAndVariance + { + public: + typedef IncrementalMeanAndVariance Self; + + public: + IncrementalMeanAndVariance( ); + virtual ~IncrementalMeanAndVariance( ); + + double GetMean( ) const; + double GetVariance( ) const; + double GetDeviation( ) const; + unsigned long GetNumberOfSamples( ) const; + + void Clear( ); + void AddValue( double v ); + + protected: + double m_M; + double m_V; + double m_N; + }; + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Common__IncrementalMeanAndVariance__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Common/PeakDetector.cxx b/lib/fpa/Common/PeakDetector.cxx new file mode 100644 index 0000000..0a53e1e --- /dev/null +++ b/lib/fpa/Common/PeakDetector.cxx @@ -0,0 +1,187 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#include +#include + +// ------------------------------------------------------------------------- +fpa::Common::PeakDetector:: +PeakDetector( ) + : m_K( 3 ), + m_T( 3.5 ), + m_I( 0.5 ) +{ +} + +// ------------------------------------------------------------------------- +fpa::Common::PeakDetector:: +~PeakDetector( ) +{ +} + +// ------------------------------------------------------------------------- +unsigned long fpa::Common::PeakDetector:: +GetKernelSize( ) const +{ + return( this->m_K ); +} + +// ------------------------------------------------------------------------- +double fpa::Common::PeakDetector:: +GetThreshold( ) const +{ + return( this->m_T ); +} + +// ------------------------------------------------------------------------- +double fpa::Common::PeakDetector:: +GetInfluence( ) const +{ + return( this->m_I ); +} + +// ------------------------------------------------------------------------- +void fpa::Common::PeakDetector:: +SetKernelSize( unsigned long k ) +{ + this->m_K = k; + this->Clear( ); +} + +// ------------------------------------------------------------------------- +void fpa::Common::PeakDetector:: +SetThreshold( double t ) +{ + this->m_T = t; + this->Clear( ); +} + +// ------------------------------------------------------------------------- +void fpa::Common::PeakDetector:: +SetInfluence( double i ) +{ + this->m_I = i; + this->Clear( ); +} + +// ------------------------------------------------------------------------- +void fpa::Common::PeakDetector:: +Clear( ) +{ + this->m_X.clear( ); + this->m_Y.clear( ); + this->m_YF.clear( ); + this->m_Avg.clear( ); + this->m_STD.clear( ); + this->m_Peaks.clear( ); + this->m_MeanAndVar.Clear( ); +} + +// ------------------------------------------------------------------------- +const std::vector< double >& fpa::Common::PeakDetector:: +GetXValues( ) const +{ + return( this->m_X ); +} + +// ------------------------------------------------------------------------- +const std::vector< double >& fpa::Common::PeakDetector:: +GetYValues( ) const +{ + return( this->m_Y ); +} + +// ------------------------------------------------------------------------- +const std::vector< double >& fpa::Common::PeakDetector:: +GetFilteredYValues( ) const +{ + return( this->m_YF ); +} + +// ------------------------------------------------------------------------- +const std::vector< double >& fpa::Common::PeakDetector:: +GetAverages( ) const +{ + return( this->m_Avg ); +} + +// ------------------------------------------------------------------------- +const std::vector< double >& fpa::Common::PeakDetector:: +GetDeviations( ) const +{ + return( this->m_STD ); +} + +// ------------------------------------------------------------------------- +const std::vector< fpa::Common::PeakDetector::TPeak >& fpa::Common:: +PeakDetector::GetPeaks( ) const +{ + return( this->m_Peaks ); +} + +// ------------------------------------------------------------------------- +unsigned long fpa::Common::PeakDetector:: +GetNumberOfSamples( ) const +{ + return( this->m_X.size( ) ); +} + +// ------------------------------------------------------------------------- +fpa::Common::PeakDetector:: +TPeak fpa::Common::PeakDetector:: +AddValue( double x, double y ) +{ + this->m_X.push_back( x ); + this->m_Y.push_back( y ); + + if( this->m_YF.size( ) < this->m_K ) + { + this->m_YF.push_back( y ); + this->m_Avg.push_back( double( 0 ) ); + this->m_STD.push_back( double( 0 ) ); + this->m_Peaks.push_back( Self::NoPeak ); + + this->m_MeanAndVar.AddValue( y ); + if( this->m_YF.size( ) == this->m_K ) + { + this->m_Avg.push_back( this->m_MeanAndVar.GetMean( ) ); + this->m_STD.push_back( this->m_MeanAndVar.GetDeviation( ) ); + + } // fi + } + else + { + unsigned long i = this->m_X.size( ) - 1; + if( + ( std::fabs( y - this->m_Avg[ i - 1 ] ) ) > + ( this->m_T * this->m_STD[ i - 1 ] ) + ) + { + this->m_Peaks.push_back( + ( y > this->m_Avg[ i - 1 ] )? Self::PosPeak: Self::NegPeak + ); + this->m_YF.push_back( + ( this->m_I * y ) + + ( ( double( 1 ) - this->m_I ) * this->m_YF[ i - 1 ] ) + ); + } + else + { + this->m_Peaks.push_back( Self::NoPeak ); + this->m_YF.push_back( y ); + + } // fi + + this->m_MeanAndVar.Clear( ); + unsigned long k = 0; + for( unsigned long j = i - this->m_K; j <= i; ++j, ++k ) + this->m_MeanAndVar.AddValue( this->m_YF[ j ] ); + this->m_Avg.push_back( this->m_MeanAndVar.GetMean( ) ); + this->m_STD.push_back( this->m_MeanAndVar.GetDeviation( ) ); + + } // fi + return( this->m_Peaks.back( ) ); +} + +// eof - $RCSfile$ diff --git a/lib/fpa/Common/PeakDetector.h b/lib/fpa/Common/PeakDetector.h new file mode 100644 index 0000000..8796cc3 --- /dev/null +++ b/lib/fpa/Common/PeakDetector.h @@ -0,0 +1,75 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Common__PeakDetector__h__ +#define __fpa__Common__PeakDetector__h__ + +#include +#include +#include + +namespace fpa +{ + namespace Common + { + /** + */ + /** + * https://stackoverflow.com/questions/22583391/peak-signal-detection-in-realtime-timeseries-data + */ + class FPA_EXPORT PeakDetector + { + public: + typedef PeakDetector Self; + + enum TPeak + { + NoPeak = 0, + PosPeak, + NegPeak + }; + + public: + PeakDetector( ); + virtual ~PeakDetector( ); + + unsigned long GetKernelSize( ) const; + double GetThreshold( ) const; + double GetInfluence( ) const; + + void SetKernelSize( unsigned long k ); + void SetThreshold( double t ); + void SetInfluence( double i ); + + const std::vector< double >& GetXValues( ) const; + const std::vector< double >& GetYValues( ) const; + const std::vector< double >& GetFilteredYValues( ) const; + const std::vector< double >& GetAverages( ) const; + const std::vector< double >& GetDeviations( ) const; + const std::vector< TPeak >& GetPeaks( ) const; + + void Clear( ); + unsigned long GetNumberOfSamples( ) const; + TPeak AddValue( double x, double y ); + + protected: + unsigned long m_K; + double m_T; + double m_I; + + std::vector< double > m_X; + std::vector< double > m_Y; + std::vector< double > m_YF; + std::vector< double > m_Avg; + std::vector< double > m_STD; + std::vector< TPeak > m_Peaks; + fpa::Common::IncrementalMeanAndVariance m_MeanAndVar; + }; + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Common__PeakDetector__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Config.h.in b/lib/fpa/Config.h.in new file mode 100644 index 0000000..4ecc222 --- /dev/null +++ b/lib/fpa/Config.h.in @@ -0,0 +1,108 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Config__h__ +#define __fpa__Config__h__ + +#include + +#define VTK_FOUND @VTK_FOUND@ +#if VTK_FOUND == 1 +# define USE_VTK +#else +# undef USE_VTK +#endif + +// ------------------------------------------------------------------------- +#define fpaTraitsMacro( __p__, __t__ ) \ + typedef __p__ __t__::TFilter TFilter; \ + typedef __p__ __t__::TMarksInterface TMarksInterface; \ + typedef __p__ __t__::TSeedsInterface TSeedsInterface; \ + typedef __p__ __t__::TInternalTraits::TInputValue TInputValue; \ + typedef __p__ __t__::TInternalTraits::TMark TMark; \ + typedef __p__ __t__::TInternalTraits::TNeighborhood TNeighborhood; \ + typedef __p__ __t__::TInternalTraits::TNode TNode; \ + typedef __p__ __t__::TInternalTraits::TNodes TNodes; \ + typedef __p__ __t__::TInternalTraits::TOutputValue TOutputValue; \ + typedef __p__ __t__::TInternalTraits::TPoint TPoint; \ + typedef __p__ __t__::TInternalTraits::TSeed TSeed; \ + typedef __p__ __t__::TInternalTraits::TSeeds TSeeds; \ + typedef __p__ __t__::TInternalTraits::TVertex TVertex; \ + itkStaticConstMacro( \ + Dimension, unsigned int, __t__::TInternalTraits::Dimension \ + ) + +// ------------------------------------------------------------------------- +#define fpaInternalTraitsMacro( __p__, __t__ ) \ + typedef __p__ __t__::TInputValue TInputValue; \ + typedef __p__ __t__::TMark TMark; \ + typedef __p__ __t__::TNeighborhood TNeighborhood; \ + typedef __p__ __t__::TNode TNode; \ + typedef __p__ __t__::TNodes TNodes; \ + typedef __p__ __t__::TOutputValue TOutputValue; \ + typedef __p__ __t__::TPoint TPoint; \ + typedef __p__ __t__::TSeed TSeed; \ + typedef __p__ __t__::TSeeds TSeeds; \ + typedef __p__ __t__::TVertex TVertex; \ + itkStaticConstMacro( Dimension, unsigned int, __t__::Dimension ) + +// ------------------------------------------------------------------------- +#define fpaFilterInputMacro( __n__, __t__ ) \ + __t__* Get##__n__( ) \ + { \ + return( \ + dynamic_cast< __t__* >( \ + this->itk::ProcessObject::GetInput( \ + this->m_##__n__##Idx \ + ) ) ); \ + } \ + const __t__* Get##__n__( ) const \ + { \ + return( \ + dynamic_cast< const __t__* >( \ + this->itk::ProcessObject::GetInput( \ + this->m_##__n__##Idx \ + ) ) ); \ + } \ + void Set##__n__( __t__* i ) \ + { \ + this->itk::ProcessObject::SetNthInput( this->m_##__n__##Idx, i ); \ + } + +// ------------------------------------------------------------------------- +#define fpaFilterInputConfigureMacro( __n__, __t__ ) \ + this->m_##__n__##Idx = this->GetNumberOfRequiredInputs( ); \ + this->itk::ProcessObject::SetNumberOfRequiredInputs( \ + this->m_##__n__##Idx + 1 \ + ) + +// ------------------------------------------------------------------------- +#define fpaFilterOutputMacro( __n__, __t__ ) \ + __t__* Get##__n__( ) \ + { \ + return( \ + dynamic_cast< __t__* >( \ + this->itk::ProcessObject::GetOutput( \ + this->m_##__n__##Idx \ + ) ) ); \ + } \ + const __t__* Get##__n__( ) const \ + { \ + return( \ + dynamic_cast< const __t__* >( \ + this->itk::ProcessObject::GetOutput( \ + this->m_##__n__##Idx \ + ) ) ); \ + } + +// ------------------------------------------------------------------------- +#define fpaFilterOutputConfigureMacro( __n__, __t__ ) \ + this->m_##__n__##Idx = this->GetNumberOfRequiredOutputs( ); \ + this->itk::ProcessObject::SetNumberOfRequiredOutputs( \ + this->m_##__n__##Idx + 1 \ + ); \ + this->SetNthOutput( this->m_##__n__##Idx, __t__::New( ) ) + +#endif // __fpa__Config__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/DataStructures/Graph.h b/lib/fpa/DataStructures/Graph.h new file mode 100644 index 0000000..79d118b --- /dev/null +++ b/lib/fpa/DataStructures/Graph.h @@ -0,0 +1,169 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__DataStructures__Graph__h__ +#define __fpa__DataStructures__Graph__h__ + +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace DataStructures + { + /** \brief A generic graph with templated index types. + * + * @param _TVertex Vertex type. + * @param _TCost Cost type. + * @param _TIndex Index type (it should be a strict weak ordering type). + */ + template< class _TVertex, class _TCost, class _TIndex = unsigned long, class _TIndexCompare = std::less< _TIndex > > + class Graph + : public itk::DataObject + { + public: + typedef Graph Self; + typedef itk::DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TVertex TVertex; + typedef _TCost TCost; + typedef _TIndex TIndex; + typedef _TIndexCompare TIndexCompare; + + // Base types + typedef std::map< TIndex, TVertex, TIndexCompare > TVertices; + typedef std::vector< TCost > TEdges; + typedef std::map< TIndex, TEdges, TIndexCompare > TMatrixRow; + typedef std::map< TIndex, TMatrixRow, TIndexCompare > TMatrix; + + public: + itkNewMacro( Self ); + itkTypeMacro( Graph, itk::DataObject ); + + public: + /*! \brief Iterators over vertices. + * These allow you to iterate over all of graph's vertices. + * + * Typical iteration should be done as: + * + * TGraph g; + * ... + * TGraph::TVertices::[const_]iterator vIt = g.BeginVertices( ); + * for( ; vIt != g.EndVertices( ); ++vIt ) + * { + * vIt->first; --> this is the vertex's index <-- + * vIt->second; --> this is the vertex's value <-- + * } + */ + inline typename TVertices::iterator BeginVertices( ) + { return( this->m_Vertices.begin( ) ); } + inline typename TVertices::iterator EndVertices( ) + { return( this->m_Vertices.end( ) ); } + inline typename TVertices::const_iterator BeginVertices( ) const + { return( this->m_Vertices.begin( ) ); } + inline typename TVertices::const_iterator EndVertices( ) const + { return( this->m_Vertices.end( ) ); } + + /*! \brief Iterators over edges. + * These allow you to iterate over all of graph's edges. + * + * Typical iteration should be done as: + * + * TGraph g; + * ... + * TGraph::TMatrix::[const_]iterator mIt = g.BeginEdgesRows( ); + * for( ; mIt != g.EndEdgesRows( ); ++mIt ) + * { + * mIt->first; --> this is the row index. <-- + * TGraph::TMatrixRow::[const_]iterator rIt = mIt->second.begin( ); + * for( ; rIt != mIt->second.end( ); ++rIt ) + * { + * rIt->first; --> this is the column index. + * TGraph::TEdges::[const_]iterator eIt = rIt->second.begin( ); + * for( ; eIt != rIt->second.end( ); ++eIt ) + * *eIt; --> this is the cost between mIt->first and rIt->first + * } + * } + */ + inline typename TMatrix::iterator BeginEdgesRows( ) + { return( this->m_Matrix.begin( ) ); } + inline typename TMatrix::iterator EndEdgetsRows( ) + { return( this->m_Matrix.end( ) ); } + inline typename TMatrix::const_iterator BeginEdgesRows( ) const + { return( this->m_Matrix.begin( ) ); } + inline typename TMatrix::const_iterator EndEdgesRows( ) const + { return( this->m_Matrix.end( ) ); } + + /*! \brief Clear all vertices and edges. + */ + void Clear( ); + + /*! \brief Clear all edges. + */ + inline void ClearEdges( ) + { this->m_Matrix.clear( ); } + + /*! \brief Vertex manipulation methods. + * Names are self-explanatory. + */ + inline bool HasVertexIndex( const TIndex& i ) const + { return( this->m_Vertices.find( i ) != this->m_Vertices.end( ) ); } + inline void SetVertex( const TIndex& index, TVertex& vertex ) + { this->m_Vertices[ index ] = vertex; } + inline TVertex& GetVertex( const TIndex& index ) + { return( this->m_Vertices[ index ] ); } + inline const TVertex& GetVertex( const TIndex& index ) const + { return( this->m_Vertices[ index ] ); } + bool RenameVertex( const TIndex& old_index, const TIndex& new_index ); + void RemoveVertex( const TIndex& index ); + + /*! \brief Edge manipulation methods. + * Names are self-explanatory. + */ + inline void AddEdge( const TIndex& orig, const TIndex& dest, const TCost& cost ) + { this->m_Matrix[ orig ][ dest ].push_back( cost ); } + TEdges& GetEdges( const TIndex& orig, const TIndex& dest ); + const TEdges& GetEdges( const TIndex& orig, const TIndex& dest ) const; + bool HasEdge( const TIndex& orig, const TIndex& dest ) const; + void RemoveEdge( const TIndex& orig, const TIndex& dest, const TCost& cost ); + void RemoveEdges( const TIndex& orig, const TIndex& dest ); + + /*! \brief Returns graph's sinks. + * + * A sink is a special vertex which does not have any "exiting" edges. + * + * @return Sinks ordered by their index. + */ + std::set< TIndex, TIndexCompare > GetSinks( ) const; + + protected: + Graph( ); + virtual ~Graph( ); + + private: + // Purposely not implemented + Graph( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TVertices m_Vertices; + TMatrix m_Matrix; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__DataStructures__Graph__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/DataStructures/Graph.hxx b/lib/fpa/DataStructures/Graph.hxx new file mode 100644 index 0000000..4d348d5 --- /dev/null +++ b/lib/fpa/DataStructures/Graph.hxx @@ -0,0 +1,270 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__DataStructures__Graph__hxx__ +#define __fpa__DataStructures__Graph__hxx__ + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +Clear( ) +{ + this->m_Vertices.clear( ); + this->m_Matrix.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +bool fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RenameVertex( const TIndex& old_index, const TIndex& new_index ) +{ + typename TVertices::iterator old_v = this->m_Vertices.find( old_index ); + typename TVertices::iterator new_v = this->m_Vertices.find( new_index ); + if( old_v != this->m_Vertices.end( ) && new_v == this->m_Vertices.end( ) ) + { + // Replace vertex + this->m_Vertices[ new_index ] = old_v->second; + this->m_Vertices.erase( old_index ); + + // Duplicate edges + typename TMatrix::iterator mIt = this->m_Matrix.begin( ); + typename TMatrix::iterator found_row = this->m_Matrix.end( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + { + if( mIt->first == old_index ) + found_row = mIt; + + typename TMatrixRow::iterator rIt = mIt->second.begin( ); + for( ; rIt != mIt->second.end( ); ++rIt ) + { + if( mIt->first == old_index ) + this->m_Matrix[ new_index ][ rIt->first ] = rIt->second; + else if( rIt->first == old_index ) + this->m_Matrix[ mIt->first ][ new_index ] = rIt->second; + + } // rof + + } // rof + + // Delete old edges + if( found_row != this->m_Matrix.end( ) ) + this->m_Matrix.erase( found_row ); + + mIt = this->m_Matrix.begin( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + { + typename TMatrixRow::iterator rIt = mIt->second.begin( ); + while( rIt != mIt->second.end( ) ) + { + if( rIt->first == old_index ) + { + mIt->second.erase( rIt ); + rIt = mIt->second.begin( ); + } + else + ++rIt; + + } // elihw + + } // rof + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RemoveVertex( const TIndex& index ) +{ + typename TVertices::iterator i = this->m_Vertices.find( index ); + if( i != this->m_Vertices.end( ) ) + { + // Delete vertex + this->m_Vertices.erase( i ); + + // Delete edges starting from given vertex + typename TMatrix::iterator mIt = this->m_Matrix.find( index ); + if( mIt != this->m_Matrix.end( ) ) + this->m_Matrix.erase( mIt ); + + // Delete edges arriving to given vertex + mIt = this->m_Matrix.begin( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + { + typename TMatrixRow::iterator rIt = mIt->second.begin( ); + while( rIt != mIt->second.end( ) ) + { + if( rIt->first == index ) + { + mIt->second.erase( rIt ); + rIt = mIt->second.begin( ); + } + else + ++rIt; + + } // elihw + + } // rof + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +typename +fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +TEdges& +fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +GetEdges( const TIndex& orig, const TIndex& dest ) +{ + static TEdges null_edges; + typename TMatrix::iterator o = this->m_Matrix.find( orig ); + if( o != this->m_Matrix.find( orig ) ) + { + typename TMatrixRow::iterator d = o->second.find( dest ); + if( d == o->second.end( ) ) + { + null_edges.clear( ); + return( null_edges ); + } + else + return( d->second ); + } + else + { + null_edges.clear( ); + return( null_edges ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +const typename +fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +TEdges& +fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +GetEdges( const TIndex& orig, const TIndex& dest ) const +{ + static const TEdges null_edges; + typename TMatrix::iterator o = this->m_Matrix.find( orig ); + if( o != this->m_Matrix.find( orig ) ) + { + typename TMatrixRow::iterator d = o->second.find( dest ); + if( d == o->second.end( ) ) + return( null_edges ); + else + return( d->second ); + } + else + return( null_edges ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +bool fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +HasEdge( const TIndex& orig, const TIndex& dest ) const +{ + typename TMatrix::const_iterator mIt = this->m_Matrix.find( orig ); + if( mIt != this->m_Matrix.end( ) ) + return( mIt->second.find( dest ) != mIt->second.end( ) ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RemoveEdge( const TIndex& orig, const TIndex& dest, const TCost& cost ) +{ + typename TMatrix::iterator m = this->m_Matrix.find( orig ); + if( m != this->m_Matrix.end( ) ) + { + typename TMatrixRow::iterator r = m->second.find( dest ); + if( r != m->second.end( ) ) + { + typename TEdges::iterator e = r->second.end( ); + for( + typename TEdges::iterator i = r->second.begin( ); + i != r->second.end( ) && e == r->second.end( ); + ++i + ) + if( *i == cost ) + e = i; + if( e != r->second.end( ) ) + { + r->second.erase( e ); + if( r->second.size( ) == 0 ) + { + m->second.erase( r ); + if( m->second.size( ) == 0 ) + this->m_Matrix.erase( m ); + + } // fi + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RemoveEdges( const TIndex& orig, const TIndex& dest ) +{ + typename TMatrix::iterator m = this->m_Matrix.find( orig ); + if( m != this->m_Matrix.end( ) ) + { + typename TMatrixRow::iterator r = m->second.find( dest ); + if( r != m->second.end( ) ) + { + m->second.erase( r ); + if( m->second.size( ) == 0 ) + this->m_Matrix.erase( m ); + + } // fi + + } // fi + +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +std::set< _TIndex, _TIndexCompare > +fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +GetSinks( ) const +{ + std::set< _TIndex, _TIndexCompare > sinks; + + typename TVertices::iterator vIt = this->m_Vertices.begin( ); + for( ; vIt != this->m_Vertices.end( ); ++vIt ) + sinks.insert( vIt->first ); + typename TMatrix::iterator mIt = this->m_Matrix.begin( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + sinks.erase( mIt->first ); + + return( sinks ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +Graph( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +fpa::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +~Graph( ) +{ +} + +#endif // __fpa__DataStructures__Graph__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/DataStructures/Image/MinimumSpanningTree.h b/lib/fpa/DataStructures/Image/MinimumSpanningTree.h new file mode 100644 index 0000000..0c5a050 --- /dev/null +++ b/lib/fpa/DataStructures/Image/MinimumSpanningTree.h @@ -0,0 +1,80 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__DataStructures__Image__MinimumSpanningTree__h__ +#define __fpa__DataStructures__Image__MinimumSpanningTree__h__ + +#include +#include +#include + +namespace fpa +{ + namespace DataStructures + { + namespace Image + { + /** + */ + template< unsigned int _VDim > + class MinimumSpanningTree + : public fpa::DataStructures::MinimumSpanningTree< itk::Index< _VDim >, itk::Image< itk::Offset< _VDim >, _VDim > > + { + public: + typedef itk::Index< _VDim > TVertex; + typedef itk::Image< itk::Offset< _VDim >, _VDim > TDataStructuresImage; + + typedef MinimumSpanningTree Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + typedef fpa::DataStructures::MinimumSpanningTree< TVertex, TDataStructuresImage > Superclass; + + typedef typename Superclass::TCollision TCollision; + typedef typename Superclass::TCollisionsRow TCollisionsRow; + typedef typename Superclass::TCollisions TCollisions; + typedef typename Superclass::TVertices TVertices; + + typedef fpa::DataStructures::Image::PolyLineParametricPath< _VDim > TPolyLineParametricPath; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::DataStructures::Image::MinimumSpanningTree, + fpa::DataStructures::MinimumSpanningTree + ); + + public: + virtual TVertex GetParent( const TVertex& v ) const override; + virtual void SetParent( const TVertex& v, const TVertex& p ) override; + + void GetPolyLineParametricPath( + typename TPolyLineParametricPath::Pointer& path, + const TVertex& a + ) const; + void GetPolyLineParametricPath( + typename TPolyLineParametricPath::Pointer& path, + const TVertex& a, const TVertex& b + ) const; + + protected: + MinimumSpanningTree( ); + virtual ~MinimumSpanningTree( ); + + private: + MinimumSpanningTree( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__DataStructures__Image__MinimumSpanningTree__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/DataStructures/Image/MinimumSpanningTree.hxx b/lib/fpa/DataStructures/Image/MinimumSpanningTree.hxx new file mode 100644 index 0000000..3cba74c --- /dev/null +++ b/lib/fpa/DataStructures/Image/MinimumSpanningTree.hxx @@ -0,0 +1,75 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__DataStructures__Image__MinimumSpanningTree__hxx__ +#define __fpa__DataStructures__Image__MinimumSpanningTree__hxx__ + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename fpa::DataStructures::Image::MinimumSpanningTree< _VDim >:: +TVertex fpa::DataStructures::Image::MinimumSpanningTree< _VDim >:: +GetParent( const TVertex& v ) const +{ + return( v + this->GetPixel( v ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::MinimumSpanningTree< _VDim >:: +SetParent( const TVertex& v, const TVertex& p ) +{ + this->SetPixel( v, p - v ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::MinimumSpanningTree< _VDim >:: +GetPolyLineParametricPath( + typename TPolyLineParametricPath::Pointer& path, + const TVertex& a + ) const +{ + TVertices v = this->GetPath( a ); + if( path.IsNull( ) ) + path = TPolyLineParametricPath::New( ); + path->SetReferenceImage( this ); + typename TVertices::const_iterator vIt = v.begin( ); + for( ; vIt != v.end( ); ++vIt ) + path->AddVertex( *vIt ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::MinimumSpanningTree< _VDim >:: +GetPolyLineParametricPath( + typename TPolyLineParametricPath::Pointer& path, + const TVertex& a, const TVertex& b + ) const +{ + TVertices v = this->GetPath( a, b ); + if( path.IsNull( ) ) + path = TPolyLineParametricPath::New( ); + path->SetReferenceImage( this ); + typename TVertices::const_iterator vIt = v.begin( ); + for( ; vIt != v.end( ); ++vIt ) + path->AddVertex( *vIt ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::DataStructures::Image::MinimumSpanningTree< _VDim >:: +MinimumSpanningTree( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::DataStructures::Image::MinimumSpanningTree< _VDim >:: +~MinimumSpanningTree( ) +{ +} + +#endif // __fpa__DataStructures__Image__MinimumSpanningTree__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/DataStructures/Image/PolyLineParametricPath.h b/lib/fpa/DataStructures/Image/PolyLineParametricPath.h new file mode 100644 index 0000000..c069e7a --- /dev/null +++ b/lib/fpa/DataStructures/Image/PolyLineParametricPath.h @@ -0,0 +1,104 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__DataStructures__Image__PolyLineParametricPath__h__ +#define __fpa__DataStructures__Image__PolyLineParametricPath__h__ + +#include +#include + +namespace fpa +{ + namespace DataStructures + { + namespace Image + { + /** + */ + template< unsigned int _VDim > + class PolyLineParametricPath + : public itk::PolyLineParametricPath< _VDim > + { + public: + typedef PolyLineParametricPath Self; + typedef itk::PolyLineParametricPath< _VDim > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkStaticConstMacro( Dimension, unsigned int, _VDim ); + + typedef itk::ImageBase< _VDim > TImageBase; + typedef typename TImageBase::SpacingType TSpacing; + typedef typename TImageBase::PointType TPoint; + typedef typename TImageBase::DirectionType TDirection; + typedef typename Superclass::ContinuousIndexType TContinuousIndex; + typedef typename TContinuousIndex::IndexType TIndex; + + public: + itkNewMacro( Self ); + itkTypeMacro( PolyLineParametricPath, itk::PolyLineParametricPath ); + + itkGetConstReferenceMacro( Spacing, TSpacing ); + itkGetConstReferenceMacro( Origin, TPoint ); + itkGetConstReferenceMacro( Direction, TDirection ); + itkGetConstReferenceMacro( InverseDirection, TDirection ); + + itkSetMacro( Origin, TPoint ); + + public: + unsigned long GetSize( ) const; + TContinuousIndex GetContinuousVertex( unsigned long i ) const; + TIndex GetVertex( unsigned long i ) const; + TPoint GetPoint( unsigned long i ) const; + + virtual void SetSpacing( const TSpacing& spac ); + virtual void SetSpacing( const double spac[ _VDim ] ); + virtual void SetSpacing( const float spac[ _VDim ] ); + virtual void SetOrigin( const double ori[ _VDim ] ); + virtual void SetOrigin( const float ori[ _VDim ] ); + virtual void SetDirection( const TDirection& dir ); + + template< class _TRefImage > + inline void SetReferenceImage( const _TRefImage* image ) + { + this->SetSpacing( image->GetSpacing( ) ); + this->SetOrigin( image->GetOrigin( ) ); + this->SetDirection( image->GetDirection( ) ); + } + + virtual void Graft( itk::DataObject* o ); + + protected: + PolyLineParametricPath( ); + virtual ~PolyLineParametricPath( ); + + virtual void _ComputeIndexToPhysicalPointMatrices( ); + + private: + // Purposely not implemented + PolyLineParametricPath( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TSpacing m_Spacing; + TPoint m_Origin; + TDirection m_Direction; + TDirection m_InverseDirection; + TDirection m_IndexToPhysicalPoint; + TDirection m_PhysicalPointToIndex; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__DataStructures__Image__PolyLineParametricPath__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/DataStructures/Image/PolyLineParametricPath.hxx b/lib/fpa/DataStructures/Image/PolyLineParametricPath.hxx new file mode 100644 index 0000000..c24e853 --- /dev/null +++ b/lib/fpa/DataStructures/Image/PolyLineParametricPath.hxx @@ -0,0 +1,216 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__DataStructures__Image__PolyLineParametricPath__hxx__ +#define __fpa__DataStructures__Image__PolyLineParametricPath__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +unsigned long fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +GetSize( ) const +{ + return( this->GetVertexList( )->Size( ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +TContinuousIndex +fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +GetContinuousVertex( unsigned long i ) const +{ + return( this->GetVertexList( )->GetElement( i ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +TIndex fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +GetVertex( unsigned long i ) const +{ + TContinuousIndex cidx = this->GetContinuousVertex( i ); + TIndex idx; + for( unsigned int d = 0; d < _VDim; ++d ) + idx[ d ] = cidx[ d ]; + return( idx ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +TPoint fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +GetPoint( unsigned long i ) const +{ + typedef typename TPoint::CoordRepType _TCoordRep; + TPoint pnt; + TContinuousIndex idx = this->GetVertex( i ); + for( unsigned int r = 0; r < _VDim; ++r ) + { + _TCoordRep sum = itk::NumericTraits< _TCoordRep >::ZeroValue( ); + for( unsigned int c = 0; c < _VDim; ++c ) + sum += this->m_IndexToPhysicalPoint( r, c ) * idx[ c ]; + pnt[ r ] = sum + this->m_Origin[ r ]; + + } // rof + return( pnt ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +SetSpacing( const TSpacing& spac ) +{ + if( this->m_Spacing != spac ) + { + this->m_Spacing = spac; + this->_ComputeIndexToPhysicalPointMatrices( ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +SetSpacing( const double spac[ _VDim ] ) +{ + this->SetSpacing( TSpacing( spac ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +SetSpacing( const float spac[ _VDim ] ) +{ + TSpacing s; + for( unsigned int d = 0; d < _VDim; ++d ) + s[ d ] = spac[ d ]; + this->SetSpacing( s ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +SetOrigin( const double ori[ _VDim ] ) +{ + this->SetOrigin( TPoint( ori ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +SetOrigin( const float ori[ _VDim ] ) +{ + this->SetOrigin( TPoint( ori ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +SetDirection( const TDirection& dir ) +{ + bool modified = false; + for( unsigned int r = 0; r < _VDim; r++ ) + { + for( unsigned int c = 0; c < _VDim; c++ ) + { + if( + itk::Math::NotExactlyEquals( + this->m_Direction[ r ][ c ], dir[ r ][ c ] + ) + ) + { + this->m_Direction[ r ][ c ] = dir[ r ][ c ]; + modified = true; + } // fi + + } // rof + + } // rof + if( modified ) + { + this->_ComputeIndexToPhysicalPointMatrices( ); + this->m_InverseDirection = this->m_Direction.GetInverse( ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +Graft( itk::DataObject* o ) +{ + this->Superclass::Graft( o ); + Self* other = dynamic_cast< Self* >( o ); + if( other != NULL ) + { + this->m_DefaultInputStepSize = other->m_DefaultInputStepSize; + this->Initialize( ); + for( unsigned long i = 0; i < other->GetSize( ); ++i ) + this->AddVertex( other->GetContinuousVertex( i ) ); + this->m_Spacing = other->m_Spacing; + this->m_Origin = other->m_Origin; + this->m_Direction = other->m_Direction; + this->m_InverseDirection = other->m_InverseDirection; + this->m_IndexToPhysicalPoint = other->m_IndexToPhysicalPoint; + this->m_PhysicalPointToIndex = other->m_PhysicalPointToIndex; + + } // fi +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +PolyLineParametricPath( ) + : Superclass( ) +{ + this->m_Spacing.Fill( 1.0 ); + this->m_Origin.Fill( 0.0 ); + this->m_Direction.SetIdentity( ); + this->m_InverseDirection.SetIdentity( ); + this->m_IndexToPhysicalPoint.SetIdentity( ); + this->m_PhysicalPointToIndex.SetIdentity( ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +~PolyLineParametricPath( ) +{ +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::PolyLineParametricPath< _VDim >:: +_ComputeIndexToPhysicalPointMatrices( ) +{ + TDirection scale; + scale.Fill( 0.0 ); + for( unsigned int i = 0; i < _VDim; i++ ) + { + if( this->m_Spacing[ i ] == 0.0 ) + itkExceptionMacro( + "A spacing of 0 is not allowed: Spacing is " << this->m_Spacing + ); + scale[ i ][ i ] = this->m_Spacing[ i ]; + + } // rof + + if( vnl_determinant( this->m_Direction.GetVnlMatrix( ) ) == 0.0 ) + itkExceptionMacro( + << "Bad direction, determinant is 0. Direction is " + << this->m_Direction + ); + this->m_IndexToPhysicalPoint = this->m_Direction * scale; + this->m_PhysicalPointToIndex = this->m_IndexToPhysicalPoint.GetInverse( ); + this->Modified( ); +} + +#endif // __fpa__DataStructures__Image__PolyLineParametricPath__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/DataStructures/Image/Skeleton.h b/lib/fpa/DataStructures/Image/Skeleton.h new file mode 100644 index 0000000..6fbb33d --- /dev/null +++ b/lib/fpa/DataStructures/Image/Skeleton.h @@ -0,0 +1,70 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__DataStructures__Image__Skeleton__h__ +#define __fpa__DataStructures__Image__Skeleton__h__ + +#include +#include +#include + +namespace fpa +{ + namespace DataStructures + { + namespace Image + { + /** + */ + template< unsigned int _VDim > + class Skeleton + : public fpa::DataStructures::Graph< typename fpa::DataStructures::Image::PolyLineParametricPath< _VDim >::TIndex, typename fpa::DataStructures::Image::PolyLineParametricPath< _VDim >::Pointer, typename fpa::DataStructures::Image::PolyLineParametricPath< _VDim >::TIndex, typename fpa::DataStructures::Image::PolyLineParametricPath< _VDim >::TIndex::LexicographicCompare > + { + public: + typedef fpa::DataStructures::Image::PolyLineParametricPath< _VDim > TPath; + typedef typename TPath::TIndex TIndex; + typedef typename TIndex::LexicographicCompare TIndexCompare; + typedef typename TPath::Pointer TPathPointer; + + itkStaticConstMacro( Dimension, unsigned int, _VDim ); + + typedef fpa::DataStructures::Graph< TIndex, TPathPointer, TIndex, TIndexCompare > Superclass; + typedef Skeleton Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( Skeleton, fpa::Image::Graph ); + + public: + void AddBranch( TPath* path ); + const TPath* GetBranch( const TIndex& a, const TIndex& b ) const; + + std::vector< TIndex > GetEndPoints( ) const; + std::vector< TIndex > GetBifurcations( ) const; + + protected: + Skeleton( ); + virtual ~Skeleton( ); + + private: + // Purposely not implemented + Skeleton( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__DataStructures__Image__Skeleton__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/DataStructures/Image/Skeleton.hxx b/lib/fpa/DataStructures/Image/Skeleton.hxx new file mode 100644 index 0000000..c3316da --- /dev/null +++ b/lib/fpa/DataStructures/Image/Skeleton.hxx @@ -0,0 +1,98 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__DataStructures__Image__Skeleton__hxx__ +#define __fpa__DataStructures__Image__Skeleton__hxx__ + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::DataStructures::Image::Skeleton< _VDim >:: +AddBranch( TPath* path ) +{ + // Check inputs + if( path == NULL ) + return; + unsigned long size = path->GetSize( ); + if( size == 0 ) + return; + TIndex a = path->GetVertex( 0 ); + TIndex b = path->GetVertex( size - 1 ); + if( this->HasEdge( a, b ) ) + return; + + // Add path + this->SetVertex( a, a ); + this->SetVertex( b, b ); + this->AddEdge( a, b, path ); + this->AddEdge( b, a, path ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +const typename fpa::DataStructures::Image::Skeleton< _VDim >:: +TPath* fpa::DataStructures::Image::Skeleton< _VDim >:: +GetBranch( const TIndex& a, const TIndex& b ) const +{ + static const TPath* null_path = NULL; + if( this->HasEdge( a, b ) ) + return( this->GetEdges( a, b ).front( ) ); + else + return( null_path ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +std::vector< typename fpa::DataStructures::Image::Skeleton< _VDim >::TIndex > +fpa::DataStructures::Image::Skeleton< _VDim >:: +GetEndPoints( ) const +{ + std::vector< TIndex > res; + typename Superclass::TMatrix::const_iterator mIt = this->BeginEdgesRows( ); + for( ; mIt != this->EndEdgesRows( ); ++mIt ) + { + unsigned long count = mIt->second.size( ); + if( count == 1 ) + res.push_back( mIt->first ); + + } // rof + return( res ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +std::vector< typename fpa::DataStructures::Image::Skeleton< _VDim >::TIndex > +fpa::DataStructures::Image::Skeleton< _VDim >:: +GetBifurcations( ) const +{ + std::vector< TIndex > res; + typename Superclass::TMatrix::const_iterator mIt = this->BeginEdgesRows( ); + for( ; mIt != this->EndEdgesRows( ); ++mIt ) + { + unsigned long count = mIt->second.size( ); + if( count > 1 ) + res.push_back( mIt->first ); + + } // rof + return( res ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::DataStructures::Image::Skeleton< _VDim >:: +Skeleton( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::DataStructures::Image::Skeleton< _VDim >:: +~Skeleton( ) +{ +} + +#endif // __fpa__DataStructures__Image__Skeleton__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/DataStructures/MinimumSpanningTree.h b/lib/fpa/DataStructures/MinimumSpanningTree.h new file mode 100644 index 0000000..475ecdd --- /dev/null +++ b/lib/fpa/DataStructures/MinimumSpanningTree.h @@ -0,0 +1,75 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__DataStructures__MinimumSpanningTree__h__ +#define __fpa__DataStructures__MinimumSpanningTree__h__ + +#include + +namespace fpa +{ + namespace DataStructures + { + /** + */ + template< class _TVertex, class _Superclass > + class MinimumSpanningTree + : public _Superclass + { + public: + typedef MinimumSpanningTree Self; + typedef _Superclass Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TVertex TVertex; + typedef std::pair< TVertex, bool > TCollision; + typedef std::vector< TCollision > TCollisionsRow; + typedef std::vector< TCollisionsRow > TCollisions; + typedef std::vector< TVertex > TVertices; + + protected: + typedef std::vector< unsigned long > _TRow; + typedef std::vector< _TRow > _TMatrix; + + public: + itkTypeMacro( fpa::Base::MinimumSpanningTree, _Superclass ); + + public: + const TCollisions& GetCollisions( ) const; + void SetCollisions( const TCollisions& collisions ); + + void ClearSeeds( ); + void AddSeed( const TVertex& seed ); + + virtual TVertex GetParent( const TVertex& v ) const = 0; + virtual void SetParent( const TVertex& v, const TVertex& p ) = 0; + + virtual TVertices GetPath( const TVertex& a ) const; + virtual TVertices GetPath( const TVertex& a, const TVertex& b ) const; + + protected: + MinimumSpanningTree( ); + virtual ~MinimumSpanningTree( ); + + private: + MinimumSpanningTree( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TCollisions m_Collisions; + _TMatrix m_FrontPaths; + std::vector< TVertex > m_Seeds; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__DataStructures__MinimumSpanningTree__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/DataStructures/MinimumSpanningTree.hxx b/lib/fpa/DataStructures/MinimumSpanningTree.hxx new file mode 100644 index 0000000..5eecf29 --- /dev/null +++ b/lib/fpa/DataStructures/MinimumSpanningTree.hxx @@ -0,0 +1,235 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__DataStructures__MinimumSpanningTree__hxx__ +#define __fpa__DataStructures__MinimumSpanningTree__hxx__ + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +const typename fpa::DataStructures::MinimumSpanningTree< _TVertex, _Superclass >:: +TCollisions& fpa::DataStructures::MinimumSpanningTree< _TVertex, _Superclass >:: +GetCollisions( ) const +{ + return( this->m_Collisions ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +void fpa::DataStructures::MinimumSpanningTree< _TVertex, _Superclass >:: +SetCollisions( const TCollisions& collisions ) +{ + static const unsigned long _inf = + std::numeric_limits< unsigned long >::max( ); + if( this->m_Collisions == collisions ) + return; + + this->m_Collisions = collisions; + + // Prepare a front graph + unsigned long N = this->m_Collisions.size( ); + _TMatrix dist( N, _TRow( N, _inf ) ); + this->m_FrontPaths = dist; + for( unsigned long i = 0; i < N; ++i ) + { + for( unsigned long j = 0; j < N; ++j ) + { + if( this->m_Collisions[ i ][ j ].second ) + { + dist[ i ][ j ] = 1; + dist[ j ][ i ] = 1; + this->m_FrontPaths[ i ][ j ] = j; + this->m_FrontPaths[ j ][ i ] = i; + + } // fi + + } // rof + dist[ i ][ i ] = 0; + this->m_FrontPaths[ i ][ i ] = i; + + } // rof + + // Use Floyd-Warshall to compute all possible paths between fronts + for( unsigned long k = 0; k < N; ++k ) + { + for( unsigned long i = 0; i < N; ++i ) + { + for( unsigned long j = 0; j < N; ++j ) + { + // WARNING: you don't want a numeric overflow!!! + unsigned long dik = dist[ i ][ k ]; + unsigned long dkj = dist[ k ][ j ]; + unsigned long sum = _inf; + if( dik < _inf && dkj < _inf ) + sum = dik + dkj; + + // Ok, continue Floyd-Warshall + if( sum < dist[ i ][ j ] ) + { + dist[ i ][ j ] = sum; + this->m_FrontPaths[ i ][ j ] = this->m_FrontPaths[ i ][ k ]; + + } // fi + + } // rof + + } // rof + + } // rof + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +void fpa::DataStructures::MinimumSpanningTree< _TVertex, _Superclass >:: +ClearSeeds( ) +{ + this->m_Seeds.clear( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +void fpa::DataStructures::MinimumSpanningTree< _TVertex, _Superclass >:: +AddSeed( const _TVertex& seed ) +{ + this->m_Seeds.push_back( seed ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +typename fpa::DataStructures::MinimumSpanningTree< _TVertex, _Superclass >:: +TVertices fpa::DataStructures::MinimumSpanningTree< _TVertex, _Superclass >:: +GetPath( const _TVertex& a ) const +{ + TVertices vertices; + _TVertex it = a; + _TVertex p = this->GetParent( it ); + while( it != p ) + { + vertices.push_back( it ); + it = p; + p = this->GetParent( it ); + + } // elihw + vertices.push_back( it ); + return( vertices ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +typename fpa::DataStructures::MinimumSpanningTree< _TVertex, _Superclass >:: +TVertices fpa::DataStructures::MinimumSpanningTree< _TVertex, _Superclass >:: +GetPath( const _TVertex& a, const _TVertex& b ) const +{ + static const unsigned long _inf = + std::numeric_limits< unsigned long >::max( ); + + TVertices vertices; + TVertices pa = this->GetPath( a ); + TVertices pb = this->GetPath( b ); + if( pa.size( ) > 0 && pb.size( ) > 0 ) + { + // Find front identifiers + unsigned long ia = _inf, ib = _inf; + unsigned long N = this->m_Seeds.size( ); + for( unsigned long i = 0; i < N; ++i ) + { + if( this->m_Seeds[ i ] == pa[ pa.size( ) - 1 ] ) + ia = i; + if( this->m_Seeds[ i ] == pb[ pb.size( ) - 1 ] ) + ib = i; + + } // rof + + // Check if there is a front-jump between given seeds + if( ia != ib ) + { + // Compute front path + std::vector< long > fpath; + fpath.push_back( ia ); + while( ia != ib ) + { + ia = this->m_FrontPaths[ ia ][ ib ]; + fpath.push_back( ia ); + + } // elihw + + // Continue only if both fronts are connected + unsigned int N = fpath.size( ); + if( N > 0 ) + { + // First path: from start vertex to first collision + vertices = this->GetPath( + a, this->m_Collisions[ fpath[ 0 ] ][ fpath[ 1 ] ].first + ); + + // Intermediary paths + for( unsigned int i = 1; i < N - 1; ++i ) + { + TVertices ipath = + this->GetPath( + this->m_Collisions[ fpath[ i - 1 ] ][ fpath[ i ] ].first, + this->m_Collisions[ fpath[ i + 1 ] ][ fpath[ i ] ].first + ); + for( long id = 0; id < ipath.size( ); ++id ) + vertices.push_back( ipath[ id ] ); + + } // rof + + // Final path: from last collision to end point + TVertices lpath = + this->GetPath( + this->m_Collisions[ fpath[ N - 1 ] ][ fpath[ N - 2 ] ].first, b + ); + for( long id = 0; id < lpath.size( ); ++id ) + vertices.push_back( lpath[ id ] ); + + } // fi + } + else + { + // Ignore common part: find common ancestor + long aIt = pa.size( ) - 1; + long bIt = pb.size( ) - 1; + bool cont = true; + while( aIt >= 0 && bIt >= 0 && cont ) + { + cont = ( pa[ aIt ] == pb[ bIt ] ); + aIt--; + bIt--; + + } // elihw + aIt++; + bIt++; + + // Glue both parts + for( long cIt = 0; cIt <= aIt; ++cIt ) + vertices.push_back( pa[ cIt ] ); + for( ; bIt >= 0; --bIt ) + vertices.push_back( pb[ bIt ] ); + + } // fi + + } // fi + return( vertices ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +fpa::DataStructures::MinimumSpanningTree< _TVertex, _Superclass >:: +MinimumSpanningTree( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +fpa::DataStructures::MinimumSpanningTree< _TVertex, _Superclass >:: +~MinimumSpanningTree( ) +{ +} + +#endif // __fpa__DataStructures__MinimumSpanningTree__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Algorithm.h b/lib/fpa/Filters/Algorithm.h new file mode 100644 index 0000000..f0a6cfb --- /dev/null +++ b/lib/fpa/Filters/Algorithm.h @@ -0,0 +1,115 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Algorithm__h__ +#define __fpa__Filters__Algorithm__h__ + +#include +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + /** + */ + template< class _TTraits > + class Algorithm + : public _TTraits::TFilter, + public _TTraits::TMarksInterface, + public _TTraits::TSeedsInterface + { + public: + typedef _TTraits TTraits; + fpaTraitsMacro( typename, TTraits ); + + typedef TFilter Superclass; + typedef Algorithm Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef fpa::Filters::Event< TVertex > TEvent; + + protected: + itkConceptMacro( + Check_Marks, + ( itk::Concept::IsUnsignedInteger< TMark > ) + ); + + public: + itkTypeMacro( fpa::Filters::Image::Algorithm, TFilter ); + + itkBooleanMacro( VisualDebug ); + itkGetConstMacro( VisualDebug, bool ); + itkSetMacro( VisualDebug, bool ); + + itkGetConstMacro( InitValue, TOutputValue ); + itkSetMacro( InitValue, TOutputValue ); + + public: + virtual itk::ModifiedTimeType GetMTime( ) const override; + virtual void InvokeEvent( const itk::EventObject& e ); + virtual void InvokeEvent( const itk::EventObject& e ) const; + + protected: + Algorithm( ); + virtual ~Algorithm( ); + + virtual void GenerateData( ) override; + + // Object association + void _Associate( itk::Object* o ); + void _Deassociate( itk::Object* o ); + void _DeassociateAll( ); + + // Preparation and termination + virtual void _BeforeGenerateData( ); + virtual void _AfterGenerateData( ); + virtual void _Reinitialize( ); + + // Memory allocation + virtual void _ConfigureOutputs( ) = 0; + + // Value assignation/recuperation + virtual const itk::DataObject* _GetReferenceInput( ) const; + virtual TInputValue _GetInputValue( const TVertex& v ) const = 0; + virtual TInputValue _GetInputValue( const TNode& n ) const; + virtual TOutputValue _GetOutputValue( const TVertex& v ) const = 0; + virtual TOutputValue _GetOutputValue( const TNode& n ) const; + virtual TNeighborhood _GetNeighbors( const TVertex& v ) const = 0; + virtual void _UpdateOutputValue( TNode& n ) = 0; + + // Queue management + virtual void _QueueClear( ) = 0; + virtual TNode _QueuePop( ) = 0; + virtual void _QueuePush( const TNode& n ) = 0; + virtual unsigned long _QueueSize( ) const = 0; + + // Value update according to the particular algorithm + virtual void _ComputeOutputValue( TNode& n ) = 0; + + private: + // Purposely not implemented. + Algorithm( const Self& other ); + Self& operator=( const Self& other ); + + protected: + bool m_VisualDebug; + TOutputValue m_InitValue; + + std::set< itk::Object* > m_AssociatedObjects; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Filters__Algorithm__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Algorithm.hxx b/lib/fpa/Filters/Algorithm.hxx new file mode 100644 index 0000000..1d03a72 --- /dev/null +++ b/lib/fpa/Filters/Algorithm.hxx @@ -0,0 +1,250 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Algorithm__hxx__ +#define __fpa__Filters__Algorithm__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< class _TTraits > +itk::ModifiedTimeType fpa::Filters::Algorithm< _TTraits >:: +GetMTime( ) const +{ + itk::ModifiedTimeType q = this->Superclass::GetMTime( ); + itk::ModifiedTimeType t; + for( itk::Object* o: this->m_AssociatedObjects ) + { + if( o != NULL ) + { + t = o->GetMTime( ); + q = ( q < t )? q: t; + + } // fi + + } // rof + return( q ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Algorithm< _TTraits >:: +InvokeEvent( const itk::EventObject& e ) +{ + TEvent a; + if( a.CheckEvent( &e ) ) + { + if( this->m_VisualDebug ) + this->Superclass::InvokeEvent( e ); + } + else + this->Superclass::InvokeEvent( e ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Algorithm< _TTraits >:: +InvokeEvent( const itk::EventObject& e ) const +{ + TEvent a; + if( a.CheckEvent( &e ) ) + { + if( this->m_VisualDebug ) + this->Superclass::InvokeEvent( e ); + } + else + this->Superclass::InvokeEvent( e ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::Algorithm< _TTraits >:: +Algorithm( ) + : Superclass( ), + TMarksInterface( this ), + TSeedsInterface( this ), + m_VisualDebug( false ), + m_InitValue( TOutputValue( 0 ) ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::Algorithm< _TTraits >:: +~Algorithm( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Algorithm< _TTraits >:: +GenerateData( ) +{ + // Init algorithm + this->InvokeEvent( itk::StartEvent( ) ); + this->_BeforeGenerateData( ); + this->_ConfigureOutputs( ); + this->_PrepareSeeds( this->_GetReferenceInput( ) ); + this->_InitCollisions( this->GetSeeds( ).size( ) ); + + // Init queue + for( TNode seed: this->GetSeeds( ) ) + { + seed.Value = this->m_InitValue; + this->_QueuePush( seed ); + this->InvokeEvent( TEvent( seed.Vertex, seed.FrontId, true ) ); + + } // rof + + // Main loop + while( this->_QueueSize( ) > 0 ) + { + // Get next candidate + TNode node = this->_QueuePop( ); + this->InvokeEvent( TEvent( node.Vertex, node.FrontId, false ) ); + + if( !( this->_IsMarked( node ) ) ) + { + // Update output value and mark vertex + this->_UpdateOutputValue( node ); + this->_Mark( node ); + + // The actual node was effectively marked? + if( node.FrontId > 0 ) + { + // Add neighborhood + TNeighborhood neighbors = this->_GetNeighbors( node.Vertex ); + typename TNeighborhood::const_iterator nIt = neighbors.begin( ); + bool coll = false; + while( nIt != neighbors.end( ) && !coll ) + { + if( this->_IsMarked( *nIt ) ) + { + // Invoke stop at collisions + if( this->_Collisions( node.Vertex, *nIt ) ) + { + this->_QueueClear( ); + coll = true; + + } // fi + } + else + { + TNode nnode; + nnode.Vertex = *nIt; + nnode.Parent = node.Vertex; + nnode.FrontId = node.FrontId; + this->_ComputeOutputValue( nnode ); + this->_QueuePush( nnode ); + this->InvokeEvent( TEvent( nnode.Vertex, nnode.FrontId, true ) ); + + } // fi + ++nIt; + + } // elihw + + } // fi + + } // fi + this->_Reinitialize( ); + + } // elihw + + // Finish algorithm + this->_AfterGenerateData( ); + this->InvokeEvent( itk::EndEvent( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Algorithm< _TTraits >:: +_Associate( itk::Object* o ) +{ + if( this->m_AssociatedObjects.insert( o ).second ) + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Algorithm< _TTraits >:: +_Deassociate( itk::Object* o ) +{ + std::set< itk::Object* >::iterator i = this->m_AssociatedObjects.find( o ); + if( i != this->m_AssociatedObjects.end( ) ) + { + this->m_AssociatedObjects.erase( i ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Algorithm< _TTraits >:: +_DeassociateAll( ) +{ + if( this->m_AssociatedObjects.size( ) > 0 ) + this->Modified( ); + this->m_AssociatedObjects.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Algorithm< _TTraits >:: +_BeforeGenerateData( ) +{ + typedef fpa::Functors::LightBaseVertexFunction< TVertex > _TVertexFunc; + const itk::DataObject* input = this->GetInput( ); + for( itk::Object* o: this->m_AssociatedObjects ) + { + _TVertexFunc* f = dynamic_cast< _TVertexFunc* >( o ); + if( f != NULL ) + f->SetDataObject( input ); + + } // rof +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Algorithm< _TTraits >:: +_AfterGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Algorithm< _TTraits >:: +_Reinitialize( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +const itk::DataObject* fpa::Filters::Algorithm< _TTraits >:: +_GetReferenceInput( ) const +{ + return( this->GetInput( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +typename fpa::Filters::Algorithm< _TTraits >:: +TInputValue fpa::Filters::Algorithm< _TTraits >:: +_GetInputValue( const TNode& n ) const +{ + return( this->_GetInputValue( n.Vertex ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +typename fpa::Filters::Algorithm< _TTraits >:: +TOutputValue fpa::Filters::Algorithm< _TTraits >:: +_GetOutputValue( const TNode& n ) const +{ + return( this->_GetOutputValue( n.Vertex ) ); +} + +#endif // __fpa__Filters__Algorithm__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Dijkstra.h b/lib/fpa/Filters/Dijkstra.h new file mode 100644 index 0000000..0a77022 --- /dev/null +++ b/lib/fpa/Filters/Dijkstra.h @@ -0,0 +1,64 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Dijkstra__h__ +#define __fpa__Filters__Dijkstra__h__ + +#include + +namespace fpa +{ + namespace Filters + { + /** + */ + template< class _TTraits, class _TMST > + class Dijkstra + : public fpa::Filters::DijkstraBase< _TTraits > + { + public: + typedef _TTraits TTraits; + typedef _TMST TMST; + fpaTraitsMacro( typename, TTraits ); + + typedef fpa::Filters::DijkstraBase< _TTraits > Superclass; + typedef Dijkstra Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TScalarWeight TScalarWeight; + typedef typename Superclass::TVertexWeight TVertexWeight; + + public: + itkTypeMacro( fpa::Filters::Dijkstra, fpa::Filters::DijkstraBase ); + + fpaFilterOutputMacro( MinimumSpanningTree, TMST ); + + + protected: + Dijkstra( ); + virtual ~Dijkstra( ); + + virtual void _AfterGenerateData( ) override; + virtual void _UpdateOutputValue( TNode& n ) override; + + private: + // Purposely not implemented. + Dijkstra( const Self& other ); + Self& operator=( const Self& other ); + + protected: + unsigned int m_MinimumSpanningTreeIdx; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Filters__Dijkstra__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Dijkstra.hxx b/lib/fpa/Filters/Dijkstra.hxx new file mode 100644 index 0000000..a27669a --- /dev/null +++ b/lib/fpa/Filters/Dijkstra.hxx @@ -0,0 +1,48 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Dijkstra__hxx__ +#define __fpa__Filters__Dijkstra__hxx__ + +// ------------------------------------------------------------------------- +template< class _TTraits, class _TMST > +fpa::Filters::Dijkstra< _TTraits, _TMST >:: +Dijkstra( ) + : Superclass( ) +{ + fpaFilterOutputConfigureMacro( MinimumSpanningTree, TMST ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits, class _TMST > +fpa::Filters::Dijkstra< _TTraits, _TMST >:: +~Dijkstra( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits, class _TMST > +void fpa::Filters::Dijkstra< _TTraits, _TMST >:: +_AfterGenerateData( ) +{ + this->Superclass::_AfterGenerateData( ); + + TMST* mst = this->GetMinimumSpanningTree( ); + mst->ClearSeeds( ); + mst->SetCollisions( this->m_Collisions ); + for( TNode n: this->GetSeeds( ) ) + mst->AddSeed( n.Vertex ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits, class _TMST > +void fpa::Filters::Dijkstra< _TTraits, _TMST >:: +_UpdateOutputValue( TNode& n ) +{ + this->Superclass::_UpdateOutputValue( n ); + this->GetMinimumSpanningTree( )->SetParent( n.Vertex, n.Parent ); +} + +#endif // __fpa__Filters__Dijkstra__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/DijkstraBase.h b/lib/fpa/Filters/DijkstraBase.h new file mode 100644 index 0000000..da844ee --- /dev/null +++ b/lib/fpa/Filters/DijkstraBase.h @@ -0,0 +1,97 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__DijkstraBase__h__ +#define __fpa__Filters__DijkstraBase__h__ + +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + /** + */ + template< class _TTraits > + class DijkstraBase + : public fpa::Filters::Algorithm< _TTraits > + { + public: + typedef _TTraits TTraits; + fpaTraitsMacro( typename, TTraits ); + + typedef fpa::Filters::Algorithm< TTraits > Superclass; + typedef DijkstraBase Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef std::vector< TNode > TQueue; + struct TQueueOrder + { + bool operator()( const TNode& a, const TNode& b ) const + { + return( b.Value < a.Value ); + } + }; + + typedef itk::FunctionBase< TOutputValue, TOutputValue > TScalarWeight; + typedef fpa::Functors::BaseVertexFunction< TVertex, TOutputValue > TVertexWeight; + + protected: + itkConceptMacro( + Check_TOutputValue, + ( itk::Concept::IsFloatingPoint< TOutputValue > ) + ); + + public: + itkTypeMacro( fpa::Filters::DijkstraBase, fpa::Filters::Algorithm ); + + itkGetConstObjectMacro( ScalarWeight, TScalarWeight ); + itkGetObjectMacro( ScalarWeight, TScalarWeight ); + + itkGetConstObjectMacro( VertexWeight, TVertexWeight ); + itkGetObjectMacro( VertexWeight, TVertexWeight ); + + public: + void SetWeightFunction( TScalarWeight* w ); + void SetWeightFunction( TVertexWeight* w ); + + protected: + DijkstraBase( ); + virtual ~DijkstraBase( ); + + virtual void _UpdateOutputValue( TNode& n ) override; + virtual void _QueueClear( ) override; + virtual TNode _QueuePop( ) override; + virtual void _QueuePush( const TNode& n ) override; + virtual unsigned long _QueueSize( ) const override; + virtual void _ComputeOutputValue( TNode& n ) override; + + private: + // Purposely not implemented. + DijkstraBase( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TScalarWeight::Pointer m_ScalarWeight; + typename TVertexWeight::Pointer m_VertexWeight; + + TQueue m_Queue; + TQueueOrder m_QueueOrder; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Filters__DijkstraBase__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/DijkstraBase.hxx b/lib/fpa/Filters/DijkstraBase.hxx new file mode 100644 index 0000000..ae6c6ad --- /dev/null +++ b/lib/fpa/Filters/DijkstraBase.hxx @@ -0,0 +1,129 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__DijkstraBase__hxx__ +#define __fpa__Filters__DijkstraBase__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::DijkstraBase< _TTraits >:: +SetWeightFunction( TScalarWeight* w ) +{ + if( this->m_ScalarWeight.GetPointer( ) != w ) + { + this->_Deassociate( this->m_ScalarWeight ); + this->m_ScalarWeight = w; + this->_Associate( this->m_ScalarWeight ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::DijkstraBase< _TTraits >:: +SetWeightFunction( TVertexWeight* w ) +{ + if( this->m_VertexWeight.GetPointer( ) != w ) + { + this->_Deassociate( this->m_VertexWeight ); + this->m_VertexWeight = w; + this->_Associate( this->m_VertexWeight ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::DijkstraBase< _TTraits >:: +DijkstraBase( ) + : Superclass( ) +{ + this->SetInitValue( TOutputValue( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::DijkstraBase< _TTraits >:: +~DijkstraBase( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::DijkstraBase< _TTraits >:: +_UpdateOutputValue( TNode& n ) +{ + // Do nothing +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::DijkstraBase< _TTraits >:: +_QueueClear( ) +{ + this->m_Queue.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +typename fpa::Filters::DijkstraBase< _TTraits >:: +TNode fpa::Filters::DijkstraBase< _TTraits >:: +_QueuePop( ) +{ + std::pop_heap( + this->m_Queue.begin( ), this->m_Queue.end( ), this->m_QueueOrder + ); + TNode n = this->m_Queue.back( ); + this->m_Queue.pop_back( ); + return( n ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::DijkstraBase< _TTraits >:: +_QueuePush( const TNode& n ) +{ + bool push_needed = ( n.Parent == n.Vertex ); + push_needed |= !( n.Value < this->_GetOutputValue( n.Parent ) ); + if( push_needed ) + { + this->m_Queue.push_back( n ); + std::push_heap( + this->m_Queue.begin( ), this->m_Queue.end( ), this->m_QueueOrder + ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +unsigned long fpa::Filters::DijkstraBase< _TTraits >:: +_QueueSize( ) const +{ + return( this->m_Queue.size( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::DijkstraBase< _TTraits >:: +_ComputeOutputValue( TNode& n ) +{ + if( this->m_VertexWeight.IsNotNull( ) ) + { + TOutputValue c = this->m_VertexWeight->Evaluate( n.Vertex, n.Parent ); + if( this->m_ScalarWeight.IsNotNull( ) ) + c = this->m_ScalarWeight->Evaluate( c ); + n.Value = c + this->_GetOutputValue( n.Parent ); + } + else + n.Value = TOutputValue( -1 ); +} + +#endif // __fpa__Filters__DijkstraBase__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Event.h b/lib/fpa/Filters/Event.h new file mode 100644 index 0000000..ee81d7c --- /dev/null +++ b/lib/fpa/Filters/Event.h @@ -0,0 +1,52 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Event__h__ +#define __fpa__Filters__Event__h__ + +#include + +namespace fpa +{ + namespace Filters + { + /** + */ + template< class _TVertex > + class Event + : public itk::EventObject + { + public: + typedef Event Self; + typedef itk::EventObject Superclass; + typedef _TVertex TVertex; + + public: + Event( ); + Event( const TVertex& v, unsigned long fid, bool intoq ); + virtual ~Event( ); + virtual const char* GetEventName( ) const override; + virtual bool CheckEvent( const itk::EventObject* e ) const override; + virtual itk::EventObject* MakeObject( ) const override; + + private: + // Purposely not implemented. + Self& operator=( const Self& other ); + + public: + TVertex Vertex; + unsigned long FrontId; + bool IntoQueue; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__Filters__Event__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Event.hxx b/lib/fpa/Filters/Event.hxx new file mode 100644 index 0000000..105c603 --- /dev/null +++ b/lib/fpa/Filters/Event.hxx @@ -0,0 +1,59 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Event__hxx__ +#define __fpa__Filters__Event__hxx__ + +// ------------------------------------------------------------------------- +template< class _TVertex > +fpa::Filters::Event< _TVertex >:: +Event( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +fpa::Filters::Event< _TVertex >:: +Event( const TVertex& v, unsigned long fid, bool intoq ) + : Superclass( ), + Vertex( v ), + FrontId( fid ), + IntoQueue( intoq ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +fpa::Filters::Event< _TVertex >:: +~Event( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +const char* fpa::Filters::Event< _TVertex >:: +GetEventName( ) const +{ + return( "fpa::Filters::Event< _TVertex >" ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +bool fpa::Filters::Event< _TVertex >:: +CheckEvent( const itk::EventObject* e ) const +{ + return( dynamic_cast< const Self* >( e ) != NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +itk::EventObject* fpa::Filters::Event< _TVertex >:: +MakeObject( ) const +{ + return( new Self ); +} + +#endif // __fpa__Filters__Event__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/Algorithm.h b/lib/fpa/Filters/Image/Algorithm.h new file mode 100644 index 0000000..ce20e7a --- /dev/null +++ b/lib/fpa/Filters/Image/Algorithm.h @@ -0,0 +1,77 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__Algorithm__h__ +#define __fpa__Filters__Image__Algorithm__h__ + +#include + +namespace fpa +{ + namespace Filters + { + namespace Image + { + /** + */ + template< class _TBaseAlgorithm > + class Algorithm + : public _TBaseAlgorithm + { + public: + typedef _TBaseAlgorithm TBaseAlgorithm; + typedef typename TBaseAlgorithm::TTraits TTraits; + fpaTraitsMacro( typename, TTraits ); + + typedef TBaseAlgorithm Superclass; + typedef Algorithm Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename TTraits::TInputImage TInputImage; + typedef typename TTraits::TOutputImage TOutputImage; + typedef itk::Image< TMark, Self::Dimension > TMarksImage; + + public: + itkTypeMacro( fpa::Filters::Image::Algorithm, TBaseAlgorithm ); + + itkGetConstMacro( NeighborhoodOrder, unsigned int ); + itkSetMacro( NeighborhoodOrder, unsigned int ); + + fpaFilterOutputMacro( Marks, TMarksImage ); + + protected: + Algorithm( ); + virtual ~Algorithm( ); + + virtual void _ConfigureOutputs( ) override; + virtual TInputValue _GetInputValue( const TVertex& v ) const override; + virtual TOutputValue _GetOutputValue( const TVertex& v ) const override; + virtual TNeighborhood _GetNeighbors( const TVertex& v ) const override; + virtual void _UpdateOutputValue( TNode& n ) override; + virtual unsigned long _GetMark( const TVertex& v ) const override; + virtual bool _IsMarked( const TVertex& v ) const override; + virtual void _Mark( const TVertex& v, unsigned long m ) override; + + private: + // Purposely not implemented. + Algorithm( const Self& other ); + Self& operator=( const Self& other ); + + protected: + unsigned int m_MarksIdx; + unsigned int m_NeighborhoodOrder; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__Filters__Image__Algorithm__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/Algorithm.hxx b/lib/fpa/Filters/Image/Algorithm.hxx new file mode 100644 index 0000000..5095992 --- /dev/null +++ b/lib/fpa/Filters/Image/Algorithm.hxx @@ -0,0 +1,137 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__Algorithm__hxx__ +#define __fpa__Filters__Image__Algorithm__hxx__ + +// ------------------------------------------------------------------------- +template< class _TBaseAlgorithm > +fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +Algorithm( ) + : Superclass( ), + m_NeighborhoodOrder( 1 ) +{ + fpaFilterOutputConfigureMacro( Marks, TMarksImage ); +} + +// ------------------------------------------------------------------------- +template< class _TBaseAlgorithm > +fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +~Algorithm( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TBaseAlgorithm > +void fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +_ConfigureOutputs( ) +{ + const TInputImage* in = this->GetInput( ); + + TOutputImage* out = this->GetOutput( ); + out->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) ); + out->SetRequestedRegion( in->GetRequestedRegion( ) ); + out->SetBufferedRegion( in->GetBufferedRegion( ) ); + out->SetSpacing( in->GetSpacing( ) ); + out->SetOrigin( in->GetOrigin( ) ); + out->SetDirection( in->GetDirection( ) ); + out->Allocate( ); + out->FillBuffer( this->GetInitValue( ) ); + + TMarksImage* marks = this->GetMarks( ); + marks->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) ); + marks->SetRequestedRegion( in->GetRequestedRegion( ) ); + marks->SetBufferedRegion( in->GetBufferedRegion( ) ); + marks->SetSpacing( in->GetSpacing( ) ); + marks->SetOrigin( in->GetOrigin( ) ); + marks->SetDirection( in->GetDirection( ) ); + marks->Allocate( ); + marks->FillBuffer( TMark( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< class _TBaseAlgorithm > +typename fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +TInputValue fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +_GetInputValue( const TVertex& v ) const +{ + return( this->GetInput( )->GetPixel( v ) ); +} + +// ------------------------------------------------------------------------- +template< class _TBaseAlgorithm > +typename fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +TOutputValue fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +_GetOutputValue( const TVertex& v ) const +{ + return( this->GetOutput( )->GetPixel( v ) ); +} + +// ------------------------------------------------------------------------- +template< class _TBaseAlgorithm > +typename fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +TNeighborhood fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +_GetNeighbors( const TVertex& v ) const +{ + typename TInputImage::RegionType region = + this->GetInput( )->GetRequestedRegion( ); + TNeighborhood neighborhood; + if( this->m_NeighborhoodOrder == 1 ) + { + for( unsigned int d = 0; d < Self::Dimension; ++d ) + { + for( int s = -1; s <= 1; s += 2 ) + { + TVertex n = v; + n[ d ] += s; + if( region.IsInside( n ) ) + neighborhood.push_back( n ); + + } // rof + + } // rof + } + else if( this->m_NeighborhoodOrder == 2 ) + { + // TODO + + } // fi + return( neighborhood ); +} + +// ------------------------------------------------------------------------- +template< class _TBaseAlgorithm > +void fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +_UpdateOutputValue( TNode& n ) +{ + this->Superclass::_UpdateOutputValue( n ); + this->GetOutput( )->SetPixel( n.Vertex, n.Value ); +} + +// ------------------------------------------------------------------------- +template< class _TBaseAlgorithm > +unsigned long fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +_GetMark( const TVertex& v ) const +{ + return( ( unsigned long )( this->GetMarks( )->GetPixel( v ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TBaseAlgorithm > +bool fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +_IsMarked( const TVertex& v ) const +{ + return( this->GetMarks( )->GetPixel( v ) != TMark( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< class _TBaseAlgorithm > +void fpa::Filters::Image::Algorithm< _TBaseAlgorithm >:: +_Mark( const TVertex& v, unsigned long m ) +{ + this->GetMarks( )->SetPixel( v, TMark( m ) ); +} + +#endif // __fpa__Filters__Image__Algorithm__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/DefaultTraits.h b/lib/fpa/Filters/Image/DefaultTraits.h new file mode 100644 index 0000000..a095704 --- /dev/null +++ b/lib/fpa/Filters/Image/DefaultTraits.h @@ -0,0 +1,94 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__DefaultTraits__h__ +#define __fpa__Filters__Image__DefaultTraits__h__ + +#include +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage, class _TMark > + class DefaultTraits + { + public: + typedef _TInputImage TInputImage; + typedef _TOutputImage TOutputImage; + + class TInternalTraits + { + public: + typedef _TMark TMark; + typedef typename TInputImage::IndexType TVertex; + typedef typename TInputImage::PixelType TInputValue; + typedef typename TInputImage::PointType TPoint; + typedef typename TOutputImage::PixelType TOutputValue; + typedef typename TVertex::LexicographicCompare TVertexCompare; + itkStaticConstMacro( + Dimension, unsigned int, _TInputImage::ImageDimension + ); + + typedef std::vector< TVertex > TNeighborhood; + struct TSeed + { + TVertex Vertex; + TPoint Point; + bool IsPoint; + TMark FrontId; + TSeed( const TMark& fid = 0 ) + : FrontId( fid ) + { } + }; + typedef std::vector< TSeed > TSeeds; + + struct TNode + { + TVertex Vertex; + TVertex Parent; + TMark FrontId; + + // Hack to hide the fact that nodes need to be (re-)initialized + mutable TOutputValue Value; + }; + struct TNodeCompare + { + bool operator()( const TNode& a, const TNode& b ) const + { + static TVertexCompare c; + return( c( a.Vertex, b.Vertex ) ); + } + }; + typedef std::set< TNode, TNodeCompare > TNodes; + }; + + typedef itk::ImageToImageFilter< TInputImage, TOutputImage > TFilter; + typedef fpa::Filters::MarksWithCollisionsInterface< TInternalTraits > TMarksInterface; + typedef fpa::Filters::SeedsInterface< TInternalTraits > TSeedsInterface; + + protected: + itkConceptMacro( + Check_Dimensions, + ( itk::Concept::SameDimension< TInputImage::ImageDimension, TOutputImage::ImageDimension > ) + ); + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Filters__Image__DefaultTraits__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/Dijkstra.h b/lib/fpa/Filters/Image/Dijkstra.h new file mode 100644 index 0000000..712d5fa --- /dev/null +++ b/lib/fpa/Filters/Image/Dijkstra.h @@ -0,0 +1,66 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__Dijkstra__h__ +#define __fpa__Filters__Image__Dijkstra__h__ + +#include +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage, class _TMark = unsigned char, class _TTraits = fpa::Filters::Image::DefaultTraits< _TInputImage, _TOutputImage, _TMark >, class _TMST = fpa::DataStructures::Image::MinimumSpanningTree< _TTraits::TInternalTraits::Dimension > > + class Dijkstra + : public fpa::Filters::Image::Algorithm< fpa::Filters::Dijkstra< _TTraits, _TMST > > + { + public: + typedef _TInputImage TInputImage; + typedef _TOutputImage TOutputImage; + typedef _TTraits TTraits; + typedef _TMST TMST; + fpaTraitsMacro( typename, TTraits ); + + typedef fpa::Filters::Dijkstra< TTraits, TMST > TAlgorithm; + typedef fpa::Filters::Image::Algorithm< TAlgorithm > Superclass; + typedef Dijkstra Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Filters::Image::Dijkstra, fpa::Filters::Image::Algorithm + ); + + protected: + Dijkstra( ); + virtual ~Dijkstra( ); + + virtual void _ConfigureOutputs( ) override; + + private: + // Purposely not implemented. + Dijkstra( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__Filters__Image__Dijkstra__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/Dijkstra.hxx b/lib/fpa/Filters/Image/Dijkstra.hxx new file mode 100644 index 0000000..b7a2f86 --- /dev/null +++ b/lib/fpa/Filters/Image/Dijkstra.hxx @@ -0,0 +1,51 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__Dijkstra__hxx__ +#define __fpa__Filters__Image__Dijkstra__hxx__ + +#include + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMark, class _TTraits, class _TMST > +fpa::Filters::Image::Dijkstra< _TInputImage, _TOutputImage, _TMark, _TTraits, _TMST >:: +Dijkstra( ) + : Superclass( ) +{ + typedef fpa::Functors::Dijkstra::Image::Identity< TInputImage, TOutputValue > _TFunc; + + this->SetWeightFunction( _TFunc::New( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMark, class _TTraits, class _TMST > +fpa::Filters::Image::Dijkstra< _TInputImage, _TOutputImage, _TMark, _TTraits, _TMST >:: +~Dijkstra( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMark, class _TTraits, class _TMST > +void fpa::Filters::Image::Dijkstra< _TInputImage, _TOutputImage, _TMark, _TTraits, _TMST >:: +_ConfigureOutputs( ) +{ + this->Superclass::_ConfigureOutputs( ); + + const TInputImage* in = this->GetInput( ); + TMST* mst = this->GetMinimumSpanningTree( ); + mst->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) ); + mst->SetRequestedRegion( in->GetRequestedRegion( ) ); + mst->SetBufferedRegion( in->GetBufferedRegion( ) ); + mst->SetSpacing( in->GetSpacing( ) ); + mst->SetOrigin( in->GetOrigin( ) ); + mst->SetDirection( in->GetDirection( ) ); + mst->Allocate( ); + + typename TVertex::OffsetType o; + o.Fill( 0 ); + mst->FillBuffer( o ); +} + +#endif // __fpa__Filters__Image__Dijkstra__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/ExtractAxis.h b/lib/fpa/Filters/Image/ExtractAxis.h new file mode 100644 index 0000000..a36991f --- /dev/null +++ b/lib/fpa/Filters/Image/ExtractAxis.h @@ -0,0 +1,106 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__ExtractAxis__h__ +#define __fpa__Filters__Image__ExtractAxis__h__ + +#include +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + namespace Image + { + /** + */ + template< class _TInputImage, class _TScalar > + class ExtractAxis + : public itk::ProcessObject + { + public: + typedef ExtractAxis Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TInputImage TInputImage; + typedef _TScalar TScalar; + typedef typename TInputImage::IndexType TIndex; + typedef typename TInputImage::PointType TPoint; + + itkStaticConstMacro( + Dimension, + unsigned int, + TInputImage::ImageDimension + ); + + typedef itk::Image< TScalar, Self::Dimension > TScalarImage; + typedef itk::ImageToImageFilter< TInputImage, TScalarImage > TCenterness; + + typedef fpa::DataStructures::Image::PolyLineParametricPath< Self::Dimension > TPath; + typedef fpa::Filters::Image::Dijkstra< TScalarImage, TScalarImage > TDijkstra; + + public: + itkNewMacro( Self ); + itkTypeMacro( fpa::Image::ExtractAxis, itk::ProcessObject ); + + itkGetConstObjectMacro( Centerness, TCenterness ); + itkGetObjectMacro( Centerness, TCenterness ); + itkSetObjectMacro( Centerness, TCenterness ); + + itkGetConstMacro( StartIndex, TIndex ); + itkSetMacro( StartIndex, TIndex ); + + itkGetConstMacro( EndIndex, TIndex ); + itkSetMacro( EndIndex, TIndex ); + + public: + virtual itk::ModifiedTimeType GetMTime( ) const override; + + virtual void AddSeed( const TIndex& seed ); + virtual void AddSeed( const TPoint& seed ); + virtual void ClearSeeds( ); + + void SetInput( TInputImage* input ); + TInputImage* GetInput( ); + const TInputImage* GetInput( ) const; + + TPath* GetOutput( ); + const TPath* GetOutput( ) const; + + protected: + ExtractAxis( ); + virtual ~ExtractAxis( ); + + virtual void GenerateData( ) override; + + private: + // Purposely not implemented. + ExtractAxis( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TCenterness::Pointer m_Centerness; + typename TDijkstra::Pointer m_Dijkstra; + + TIndex m_StartIndex; + TIndex m_EndIndex; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__Filters__Image__ExtractAxis__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/ExtractAxis.hxx b/lib/fpa/Filters/Image/ExtractAxis.hxx new file mode 100644 index 0000000..203ea20 --- /dev/null +++ b/lib/fpa/Filters/Image/ExtractAxis.hxx @@ -0,0 +1,150 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__ExtractAxis__hxx__ +#define __fpa__Filters__Image__ExtractAxis__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +itk::ModifiedTimeType +fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +GetMTime( ) const +{ + itk::ModifiedTimeType a = this->Superclass::GetMTime( ); + itk::ModifiedTimeType b = this->m_Centerness->GetMTime( ); + itk::ModifiedTimeType c = this->m_Dijkstra->GetMTime( ); + a = ( a < b )? a: b; + return( ( a < c )? a: c ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +void fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +AddSeed( const TIndex& seed ) +{ + this->m_Dijkstra->AddSeed( seed ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +void fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +AddSeed( const TPoint& seed ) +{ + this->m_Dijkstra->AddSeed( seed ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +void fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +ClearSeeds( ) +{ + this->m_Dijkstra->ClearSeeds( ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +void fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +SetInput( TInputImage* input ) +{ + this->Superclass::SetNthInput( 0, input ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +typename fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +TInputImage* fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +GetInput( ) +{ + return( dynamic_cast< TInputImage* >( this->Superclass::GetInput( 0 ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +const typename fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +TInputImage* fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +GetInput( ) const +{ + return( + dynamic_cast< const TInputImage* >( this->Superclass::GetInput( 0 ) ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +typename fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +TPath* fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +GetOutput( ) +{ + return( dynamic_cast< TPath* >( this->Superclass::GetOutput( 0 ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +const typename fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +TPath* fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +GetOutput( ) const +{ + return( dynamic_cast< const TPath* >( this->Superclass::GetOutput( 0 ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +ExtractAxis( ) + : Superclass( ) +{ + // I/O configuration + this->SetNumberOfRequiredInputs( 1 ); + this->SetNumberOfRequiredOutputs( 1 ); + this->SetNthOutput( 0, TPath::New( ) ); + + // Prepare weight function + typedef fpa::Functors::Dijkstra::Invert< TScalar > _TWeight; + typename _TWeight::Pointer weight = _TWeight::New( ); + weight->SetAlpha( 1 ); + weight->SetBeta( 1 ); + + // Filters + typedef itk::SignedMaurerDistanceMapImageFilter< TInputImage, TScalarImage > _TDefaultCenterness; + typename _TDefaultCenterness::Pointer dc = _TDefaultCenterness::New( ); + dc->InsideIsPositiveOn( ); + dc->SquaredDistanceOn( ); + dc->UseImageSpacingOn( ); + this->m_Centerness = dc; + + // Axis extractor + this->m_Dijkstra = TDijkstra::New( ); + this->m_Dijkstra->SetWeightFunction( weight ); + this->m_Dijkstra->StopAtOneFront( ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +~ExtractAxis( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TScalar > +void fpa::Filters::Image::ExtractAxis< _TInputImage, _TScalar >:: +GenerateData( ) +{ + // Execute minipipeline + this->m_Centerness->SetInput( this->GetInput( ) ); + this->m_Dijkstra->SetInput( this->m_Centerness->GetOutput( ) ); + this->m_Dijkstra->Update( ); + + // Extract axis + typename TPath::Pointer out = this->GetOutput( ); + this->m_Dijkstra->GetMinimumSpanningTree( )->GetPolyLineParametricPath( + out, this->m_StartIndex, this->m_EndIndex + ); +} + +#endif // __fpa__Filters__Image__ExtractAxis__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/LabelsSeedInterface.h b/lib/fpa/Filters/Image/LabelsSeedInterface.h new file mode 100644 index 0000000..04b462a --- /dev/null +++ b/lib/fpa/Filters/Image/LabelsSeedInterface.h @@ -0,0 +1,54 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__LabelsSeedInterface__h__ +#define __fpa__Filters__Image__LabelsSeedInterface__h__ + +namespace fpa +{ + namespace Filters + { + namespace Image + { + /** + */ + template< class _TTraits > + class LabelsSeedInterface + { + public: + typedef LabelsSeedInterface Self; + typedef _TTraits TTraits; + fpaInternalTraitsMacro( typename, TTraits ); + + public: + LabelsSeedInterface( itk::ProcessObject* f ) + : m_Filter( f ) + { + } + + virtual ~LabelsSeedInterface( ) + { + } + + const TNodes& GetSeeds( ) const + { + return( this->m_UnifiedSeeds ); + } + + protected: + virtual void _PrepareSeeds( const itk::DataObject* input ) = 0; + + protected: + TNodes m_UnifiedSeeds; + itk::ProcessObject::Pointer m_Filter; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Filters__Image__LabelsSeedInterface__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/Mori.h b/lib/fpa/Filters/Image/Mori.h new file mode 100644 index 0000000..66a5fa3 --- /dev/null +++ b/lib/fpa/Filters/Image/Mori.h @@ -0,0 +1,83 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__Mori__h__ +#define __fpa__Filters__Image__Mori__h__ + +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage > + class MoriTraits + : public fpa::Filters::Image::DefaultTraits< _TInputImage, _TOutputImage, unsigned long > + { + public: + typedef _TInputImage TInputImage; + typedef _TOutputImage TOutputImage; + typedef fpa::Filters::Image::DefaultTraits< TInputImage, TOutputImage, unsigned long > Superclass; + + typedef typename Superclass::TInternalTraits TInternalTraits; + typedef typename Superclass::TFilter TFilter; + typedef fpa::Filters::MarksInterface< TInternalTraits > TMarksInterface; + typedef fpa::Filters::SingleSeedInterface< TInternalTraits > TSeedsInterface; + }; + + /** + */ + template< class _TInputImage, class _TOutputImage, class _TTraits = fpa::Filters::Image::MoriTraits< _TInputImage, _TOutputImage > > + class Mori + : public fpa::Filters::Image::Algorithm< fpa::Filters::Mori< _TTraits > > + { + public: + typedef _TInputImage TInputImage; + typedef _TOutputImage TOutputImage; + typedef _TTraits TTraits; + fpaTraitsMacro( typename, TTraits ); + + typedef fpa::Filters::Mori< TTraits > TAlgorithm; + typedef fpa::Filters::Image::Algorithm< TAlgorithm > Superclass; + typedef Mori Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Filters::Image::Mori, fpa::Filters::Image::Algorithm + ); + + protected: + Mori( ) + : Superclass( ) + { + } + virtual ~Mori( ) + { + } + + private: + // Purposely not implemented. + Mori( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Filters__Image__Mori__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/RandomWalker.h b/lib/fpa/Filters/Image/RandomWalker.h new file mode 100644 index 0000000..41fba2c --- /dev/null +++ b/lib/fpa/Filters/Image/RandomWalker.h @@ -0,0 +1,105 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__RandomWalker__h__ +#define __fpa__Filters__Image__RandomWalker__h__ + +#include +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + namespace Image + { + /** + */ + template< class _TInputImage, class _TInputLabels, class _TCostsImage > + class RandomWalkerTraits + : public fpa::Filters::Image::DefaultTraits< _TInputImage, _TCostsImage, typename _TInputLabels::PixelType > + { + public: + typedef _TInputImage TInputImage; + typedef _TInputLabels TInputLabels; + typedef _TCostsImage TCostsImage; + typedef fpa::Filters::Image::DefaultTraits< TInputImage, TCostsImage, typename _TInputLabels::PixelType > Superclass; + + typedef typename Superclass::TInternalTraits TInternalTraits; + typedef typename Superclass::TFilter TFilter; + typedef fpa::Filters::MarksInterface< TInternalTraits > TMarksInterface; + typedef fpa::Filters::Image::LabelsSeedInterface< TInternalTraits > TSeedsInterface; + }; + + /** + */ + template< class _TInputImage, class _TInputLabels, class _TCostsImage = itk::Image< float, _TInputImage::ImageDimension >, class _TTraits = fpa::Filters::Image::RandomWalkerTraits< _TInputImage, _TInputLabels, _TCostsImage > > + class RandomWalker + : public fpa::Filters::Image::Algorithm< fpa::Filters::DijkstraBase< _TTraits > > + { + public: + typedef _TInputImage TInputImage; + typedef _TInputLabels TInputLabels; + typedef _TCostsImage TCostsImage; + typedef _TTraits TTraits; + fpaTraitsMacro( typename, TTraits ); + + typedef fpa::Filters::DijkstraBase< TTraits > TAlgorithm; + typedef fpa::Filters::Image::Algorithm< TAlgorithm > Superclass; + typedef RandomWalker Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TMarksImage TOutputLabels; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Filters::Image::RandomWalker, fpa::Filters::Image::Algorithm + ); + + fpaFilterInputMacro( InputLabels, TInputLabels ); + + public: + TCostsImage* GetOutputCosts( ); + const TCostsImage* GetOutputCosts( ) const; + + TOutputLabels* GetOutputLabels( ); + const TOutputLabels* GetOutputLabels( ) const; + + TInputImage* GetInputImage( ); + const TInputImage* GetInputImage( ) const; + void SetInputImage( TInputImage* image ); + + protected: + RandomWalker( ); + virtual ~RandomWalker( ); + + virtual const itk::DataObject* _GetReferenceInput( ) const override; + virtual void _PrepareSeeds( const itk::DataObject* input ) override; + + private: + // Purposely not implemented. + RandomWalker( const Self& other ); + Self& operator=( const Self& other ); + + protected: + unsigned int m_InputLabelsIdx; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__Filters__Image__RandomWalker__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/RandomWalker.hxx b/lib/fpa/Filters/Image/RandomWalker.hxx new file mode 100644 index 0000000..ef858b5 --- /dev/null +++ b/lib/fpa/Filters/Image/RandomWalker.hxx @@ -0,0 +1,166 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__RandomWalker__hxx__ +#define __fpa__Filters__Image__RandomWalker__hxx__ + +#include + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TInputLabels, class _TCostsImage, class _TTraits > +typename +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +TCostsImage* +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +GetOutputCosts( ) +{ + return( this->GetOutput( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TInputLabels, class _TCostsImage, class _TTraits > +const typename +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +TCostsImage* +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +GetOutputCosts( ) const +{ + return( this->GetOutput( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TInputLabels, class _TCostsImage, class _TTraits > +typename +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +TOutputLabels* +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +GetOutputLabels( ) +{ + return( this->GetMarks( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TInputLabels, class _TCostsImage, class _TTraits > +const typename +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +TOutputLabels* +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +GetOutputLabels( ) const +{ + return( this->GetMarks( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TInputLabels, class _TCostsImage, class _TTraits > +typename +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +TInputImage* +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +GetInputImage( ) +{ + return( this->GetInput( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TInputLabels, class _TCostsImage, class _TTraits > +const typename +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +TInputImage* +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +GetInputImage( ) const +{ + return( this->GetInput( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TInputLabels, class _TCostsImage, class _TTraits > +void +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +SetInputImage( TInputImage* image ) +{ + this->SetInput( image ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TInputLabels, class _TCostsImage, class _TTraits > +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +RandomWalker( ) + : Superclass( ) +{ + fpaFilterInputConfigureMacro( InputLabels, TInputLabels ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TInputLabels, class _TCostsImage, class _TTraits > +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +~RandomWalker( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TInputLabels, class _TCostsImage, class _TTraits > +const itk::DataObject* +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +_GetReferenceInput( ) const +{ + return( this->GetInputLabels( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TInputLabels, class _TCostsImage, class _TTraits > +void +fpa::Filters::Image::RandomWalker< _TInputImage, _TInputLabels, _TCostsImage, _TTraits >:: +_PrepareSeeds( const itk::DataObject* input ) +{ + // Input object is a labelled image? + const TInputLabels* labels = dynamic_cast< const TInputLabels* >( input ); + if( labels != NULL ) + { + this->m_UnifiedSeeds.clear( ); + + // Iterate over labels + typedef itk::ImageRegionConstIteratorWithIndex< TInputLabels > _TIt; + typename TInputLabels::RegionType reg = labels->GetRequestedRegion( ); + _TIt lIt( labels, reg ); + for( lIt.GoToBegin( ); !lIt.IsAtEnd( ); ++lIt ) + { + if( lIt.Get( ) > 0 ) + { + bool is_seed = false; + for( unsigned int d = 0; d < Self::Dimension; ++d ) + { + for( int s = -1; s <= 1; s += 2 ) + { + TVertex neigh = lIt.GetIndex( ); + neigh[ d ] += s; + if( reg.IsInside( neigh ) ) + is_seed |= ( labels->GetPixel( neigh ) == 0 ); + + } // rof + + } // rof + + // Add pixel as seed or already marked + TNode node; + node.Vertex = lIt.GetIndex( ); + node.Parent = lIt.GetIndex( ); + node.FrontId = lIt.Get( ); + node.Value = TOutputValue( 0 ); + if( !is_seed ) + { + this->_Mark( node.Vertex, node.FrontId ); + this->_UpdateOutputValue( node ); + } + else + this->m_UnifiedSeeds.insert( node ); + + } // fi + + } // rof + + } // fi +} + +#endif // __fpa__Filters__Image__RandomWalker__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/RegionGrow.h b/lib/fpa/Filters/Image/RegionGrow.h new file mode 100644 index 0000000..7004172 --- /dev/null +++ b/lib/fpa/Filters/Image/RegionGrow.h @@ -0,0 +1,64 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__RegionGrow__h__ +#define __fpa__Filters__Image__RegionGrow__h__ + +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage, class _TMark = unsigned char, class _TTraits = fpa::Filters::Image::DefaultTraits< _TInputImage, _TOutputImage, _TMark > > + class RegionGrow + : public fpa::Filters::Image::Algorithm< fpa::Filters::RegionGrow< _TTraits > > + { + public: + typedef _TInputImage TInputImage; + typedef _TOutputImage TOutputImage; + typedef _TTraits TTraits; + fpaTraitsMacro( typename, TTraits ); + + typedef fpa::Filters::RegionGrow< TTraits > TAlgorithm; + typedef fpa::Filters::Image::Algorithm< TAlgorithm > Superclass; + typedef RegionGrow Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Filters::Image::RegionGrow, fpa::Filters::Image::Algorithm + ); + + protected: + RegionGrow( ) + : Superclass( ) + { + } + virtual ~RegionGrow( ) + { + } + + private: + // Purposely not implemented. + RegionGrow( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Filters__Image__RegionGrow__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/Skeleton.h b/lib/fpa/Filters/Image/Skeleton.h new file mode 100644 index 0000000..39fd41a --- /dev/null +++ b/lib/fpa/Filters/Image/Skeleton.h @@ -0,0 +1,153 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__Skeleton__h__ +#define __fpa__Filters__Image__Skeleton__h__ + +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + namespace Image + { + /** + */ + template< class _TInputImage, class _TDistanceMap = itk::SignedMaurerDistanceMapImageFilter< _TInputImage, itk::Image< double, _TInputImage::ImageDimension > > > + class Skeleton + : public itk::ProcessObject + { + public: + typedef Skeleton Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TInputImage TInputImage; + typedef _TDistanceMap TDistanceMap; + itkStaticConstMacro( + Dimension, + unsigned int, + TInputImage::ImageDimension + ); + + typedef typename TDistanceMap::OutputImageType TOutputImage; + typedef typename TInputImage::IndexType TIndex; + typedef typename TOutputImage::PixelType TScalar; + + typedef fpa::DataStructures::Image::Skeleton< Self::Dimension > TSkeleton; + + protected: + typedef std::multimap< TScalar, TIndex > _TSkeletonQueue; + + /** + */ + class _TDijkstra + : public fpa::Filters::Image::Dijkstra< TOutputImage, TOutputImage > + { + public: + typedef fpa::Filters::Image::Dijkstra< TOutputImage, TOutputImage > Superclass; + typedef _TDijkstra Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TNode TNode; + typedef typename Superclass::TMST TMST; + + public: + itkNewMacro( Self ); + itkTypeMacro( _TDijkstra, fpa::Image::Dijkstra ); + + itkGetConstReferenceMacro( SkeletonQueue, _TSkeletonQueue ); + + protected: + _TDijkstra( ); + virtual ~_TDijkstra( ); + + virtual void _BeforeGenerateData( ) override; + virtual void _UpdateOutputValue( TNode& n ) override; + + private: + // Purposely not implemented + _TDijkstra( const Self& other ); + Self& operator=( const Self& other ); + + protected: + _TSkeletonQueue m_SkeletonQueue; + }; + typedef typename _TDijkstra::TMST _TMST; + + public: + itkNewMacro( Self ); + itkTypeMacro( fpa::Image::Skeleton, fpa::Image::Dijkstra ); + + itkBooleanMacro( SeedFromMaximumDistance ); + itkGetConstMacro( SeedFromMaximumDistance, bool ); + itkSetMacro( SeedFromMaximumDistance, bool ); + + itkGetConstObjectMacro( DistanceMap, TDistanceMap ); + itkGetObjectMacro( DistanceMap, TDistanceMap ); + + itkGetConstMacro( Seed, TIndex ); + itkSetMacro( Seed, TIndex ); + + public: + virtual itk::ModifiedTimeType GetMTime( ) const override; + + void SetInput( TInputImage* input ); + TInputImage* GetInput( ); + const TInputImage* GetInput( ) const; + + TSkeleton* GetOutput( ); + const TSkeleton* GetOutput( ) const; + + protected: + Skeleton( ); + virtual ~Skeleton( ); + + virtual void GenerateData( ) override; + + template< class _TMarksPointer > + void _MarkSphere( + _TMarksPointer& marks, + const TOutputImage* dmap, + const TIndex& center + ); + + void _EndPoints( + std::vector< TIndex >& end_points, + const TOutputImage* dmap, + const _TMST* mst, + const _TSkeletonQueue& queue + ); + + private: + // Purposely not implemented. + Skeleton( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TDistanceMap::Pointer m_DistanceMap; + bool m_SeedFromMaximumDistance; + TIndex m_Seed; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Filters__Image__Skeleton__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Image/Skeleton.hxx b/lib/fpa/Filters/Image/Skeleton.hxx new file mode 100644 index 0000000..13392a5 --- /dev/null +++ b/lib/fpa/Filters/Image/Skeleton.hxx @@ -0,0 +1,353 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Image__Skeleton__hxx__ +#define __fpa__Filters__Image__Skeleton__hxx__ + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >::_TDijkstra:: +_TDijkstra( ) + : Superclass( ) +{ + // Prepare weight function + typedef fpa::Functors::Dijkstra::Invert< TScalar > _TWeight; + typename _TWeight::Pointer weight = _TWeight::New( ); + weight->SetAlpha( 1 ); + weight->SetBeta( 1 ); + this->SetWeightFunction( weight ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >::_TDijkstra:: +~_TDijkstra( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +void fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >::_TDijkstra:: +_BeforeGenerateData( ) +{ + this->Superclass::_BeforeGenerateData( ); + this->m_SkeletonQueue.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +void fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >::_TDijkstra:: +_UpdateOutputValue( TNode& n ) +{ + typedef typename _TSkeletonQueue::value_type _TSkeletonQueueValue; + + this->Superclass::_UpdateOutputValue( n ); + double d = double( this->GetInput( )->GetPixel( n.Vertex ) ); + if( d >= double( 0 ) ) + { + // Update skeleton candidates + d += double( 1e-5 ); + double v = double( n.Value ) / ( d * d ); + this->m_SkeletonQueue.insert( _TSkeletonQueueValue( v, n.Vertex ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +itk::ModifiedTimeType +fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +GetMTime( ) const +{ + itk::ModifiedTimeType t = this->Superclass::GetMTime( ); + itk::ModifiedTimeType q = this->m_DistanceMap->GetMTime( ); + return( ( q < t )? q: t ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +void fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +SetInput( TInputImage* input ) +{ + this->Superclass::SetNthInput( 0, input ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +typename fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +TInputImage* fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +GetInput( ) +{ + return( dynamic_cast< TInputImage* >( this->Superclass::GetInput( 0 ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +const typename fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +TInputImage* fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +GetInput( ) const +{ + return( + dynamic_cast< const TInputImage* >( this->Superclass::GetInput( 0 ) ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +typename fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +TSkeleton* fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +GetOutput( ) +{ + return( dynamic_cast< TSkeleton* >( this->Superclass::GetOutput( 0 ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +const typename fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +TSkeleton* fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +GetOutput( ) const +{ + return( + dynamic_cast< const TSkeleton* >( this->Superclass::GetOutput( 0 ) ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +Skeleton( ) + : Superclass( ), + m_SeedFromMaximumDistance( false ) +{ + this->SetNumberOfRequiredInputs( 1 ); + this->SetNumberOfRequiredOutputs( 1 ); + this->SetNthOutput( 0, TSkeleton::New( ) ); + + this->m_DistanceMap = TDistanceMap::New( ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +~Skeleton( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +void fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +GenerateData( ) +{ + // Update distance map + this->m_DistanceMap->SetInput( this->GetInput( ) ); + this->m_DistanceMap->Update( ); + + // Correct seed + if( this->m_SeedFromMaximumDistance ) + { + typedef itk::MinimumMaximumImageCalculator< TOutputImage > _TMinMax; + typename _TMinMax::Pointer minmax = _TMinMax::New( ); + minmax->SetImage( this->m_DistanceMap->GetOutput( ) ); + minmax->Compute( ); + this->m_Seed = minmax->GetIndexOfMaximum( ); + + } // fi + + // Compute MST + typename _TDijkstra::Pointer dijkstra = _TDijkstra::New( ); + dijkstra->SetInput( this->m_DistanceMap->GetOutput( ) ); + dijkstra->AddSeed( this->m_Seed ); + dijkstra->Update( ); + + // Compute end-points + const _TMST* mst = dijkstra->GetMinimumSpanningTree( ); + std::vector< TIndex > end_points; + this->_EndPoints( + end_points, this->m_DistanceMap->GetOutput( ), + mst, dijkstra->GetSkeletonQueue( ) + ); + + // Compute symbolic branches + typedef std::map< TIndex, TIndex, typename TIndex::LexicographicCompare > _TTags; + _TTags tags, branches; + typename std::vector< TIndex >::const_iterator eIt = end_points.begin( ); + for( ; eIt != end_points.end( ); ++eIt ) + { + // Tag path + TIndex it = *eIt; + TIndex p = mst->GetParent( it ); + typename _TTags::iterator bIt = tags.end( ); + while( it != p && bIt == tags.end( ) ) + { + typename _TTags::iterator tIt = tags.find( it ); + if( tIt != tags.end( ) ) + { + // Ok, a bifurcation point has been found + // branch1: tIt->second <-> it (ok) + branches[ tIt->second ] = it; + + // branch2: *eit <-> it (ok) + branches[ *eIt ] = it; + + // branch3: it <-> until next bifurcation + bIt = tIt; + } + else + tags[ it ] = *eIt; + it = p; + p = mst->GetParent( it ); + + } // elihw + if( bIt != tags.end( ) ) + { + TIndex pTag = bIt->second; + TIndex nTag = bIt->first; + it = bIt->first; + p = it; + while( tags[ it ] == pTag ) + { + tags[ it ] = nTag; + p = it; + it = mst->GetParent( it ); + + } // elihw + tags[ it ] = nTag; + branches[ bIt->first ] = p; + } + else + { + tags[ it ] = *eIt; + branches[ *eIt ] = it; + + } // fi + + } // rof + + // Fill full branches + typedef typename _TMST::TVertices _TVertices; + typedef typename TSkeleton::TPath _TPath; + + TSkeleton* sk = this->GetOutput( ); + typename _TTags::const_iterator bIt = branches.begin( ); + for( ; bIt != branches.end( ); ++bIt ) + { + _TVertices v = mst->GetPath( bIt->first, bIt->second ); + typename _TPath::Pointer path = _TPath::New( ); + path->SetReferenceImage( this->GetInput( ) ); + typename _TVertices::const_reverse_iterator vIt = v.rbegin( ); + for( ; vIt != v.rend( ); ++vIt ) + path->AddVertex( *vIt ); + sk->AddBranch( path ); + + } // rof +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +template< class _TMarksPointer > +void fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +_MarkSphere( + _TMarksPointer& marks, const TOutputImage* dmap, const TIndex& center + ) +{ + typedef typename _TMarksPointer::ObjectType _TMarks; + typedef itk::ImageRegionIteratorWithIndex< _TMarks > _TMarksIt; + + static const double _eps = std::sqrt( double( Self::Dimension + 1 ) ); + typename _TMarks::SpacingType spac = dmap->GetSpacing( ); + typename _TMarks::RegionType region = dmap->GetRequestedRegion( ); + + typename _TMarks::PointType cnt; + dmap->TransformIndexToPhysicalPoint( center, cnt ); + double r = double( dmap->GetPixel( center ) ) * _eps; + + TIndex i0, i1; + for( unsigned int d = 0; d < Self::Dimension; ++d ) + { + long off = long( std::ceil( r / double( spac[ d ] ) ) ); + if( off < 3 ) + off = 3; + i0[ d ] = center[ d ] - off; + i1[ d ] = center[ d ] + off; + + if( i0[ d ] < region.GetIndex( )[ d ] ) + i0[ d ] = region.GetIndex( )[ d ]; + + if( i1[ d ] >= region.GetIndex( )[ d ] + region.GetSize( )[ d ] ) + i1[ d ] = region.GetIndex( )[ d ] + region.GetSize( )[ d ] - 1; + + } // rof + + typename _TMarks::SizeType size; + for( unsigned int d = 0; d < Self::Dimension; ++d ) + size[ d ] = i1[ d ] - i0[ d ] + 1; + + typename _TMarks::RegionType neighRegion; + neighRegion.SetIndex( i0 ); + neighRegion.SetSize( size ); + + _TMarksIt mIt( marks, neighRegion ); + for( mIt.GoToBegin( ); !mIt.IsAtEnd( ); ++mIt ) + mIt.Set( true ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +void fpa::Filters::Image::Skeleton< _TInputImage, _TDistanceMap >:: +_EndPoints( + std::vector< TIndex >& end_points, + const TOutputImage* dmap, + const _TMST* mst, + const _TSkeletonQueue& queue + ) +{ + typedef typename _TSkeletonQueue::value_type _TSkeletonQueueValue; + + // Some values + typedef itk::Image< bool, Self::Dimension > _TMarks; + typename _TMarks::Pointer marks = _TMarks::New( ); + marks->SetLargestPossibleRegion( mst->GetLargestPossibleRegion( ) ); + marks->SetRequestedRegion( mst->GetRequestedRegion( ) ); + marks->SetBufferedRegion( mst->GetBufferedRegion( ) ); + marks->SetSpacing( mst->GetSpacing( ) ); + marks->SetOrigin( mst->GetOrigin( ) ); + marks->SetDirection( mst->GetDirection( ) ); + marks->Allocate( ); + marks->FillBuffer( false ); + + // Get candidates in maximum to minimum iteration + typename _TSkeletonQueue::const_reverse_iterator nIt = queue.rbegin( ); + for( ; nIt != queue.rend( ); ++nIt ) + { + // Mark it and update end-points + if( !( marks->GetPixel( nIt->second ) ) ) + { + marks->SetPixel( nIt->second, true ); + end_points.push_back( nIt->second ); + + // Mark path + TIndex it = nIt->second; + TIndex p = mst->GetParent( it ); + while( it != p ) + { + this->_MarkSphere( marks, dmap, it ); + it = p; + p = mst->GetParent( it ); + + } // elihw + this->_MarkSphere( marks, dmap, it ); + + } // fi + + } // rof +} + +#endif // __fpa__Filters__Image__Skeleton__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/MarksInterface.h b/lib/fpa/Filters/MarksInterface.h new file mode 100644 index 0000000..71fc48a --- /dev/null +++ b/lib/fpa/Filters/MarksInterface.h @@ -0,0 +1,54 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__MarksInterface__h__ +#define __fpa__Filters__MarksInterface__h__ + +#include + +namespace fpa +{ + namespace Filters + { + /** + */ + template< class _TTraits > + class MarksInterface + { + public: + typedef MarksInterface Self; + typedef _TTraits TTraits; + fpaInternalTraitsMacro( typename, TTraits ); + + public: + MarksInterface( itk::ProcessObject* f ); + virtual ~MarksInterface( ); + + protected: + virtual void _InitCollisions( unsigned long nSeeds ); + virtual bool _Collisions( const TVertex& a, const TVertex& b ); + + virtual unsigned long _GetMark( const TNode& n ) const; + virtual unsigned long _GetMark( const TVertex& v ) const = 0; + + virtual bool _IsMarked( const TNode& n ) const; + virtual bool _IsMarked( const TVertex& v ) const = 0; + + virtual void _Mark( const TNode& n ); + virtual void _Mark( const TVertex& v, unsigned long m ) = 0; + + protected: + itk::ProcessObject::Pointer m_Filter; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Filters__MarksInterface__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/MarksInterface.hxx b/lib/fpa/Filters/MarksInterface.hxx new file mode 100644 index 0000000..c6e7d17 --- /dev/null +++ b/lib/fpa/Filters/MarksInterface.hxx @@ -0,0 +1,64 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__MarksInterface__hxx__ +#define __fpa__Filters__MarksInterface__hxx__ + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::MarksInterface< _TTraits >:: +MarksInterface( itk::ProcessObject* f ) + : m_Filter( f ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::MarksInterface< _TTraits >:: +~MarksInterface( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::MarksInterface< _TTraits >:: +_InitCollisions( unsigned long nSeeds ) +{ + // Do nothing +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +bool fpa::Filters::MarksInterface< _TTraits >:: +_Collisions( const TVertex& a, const TVertex& b ) +{ + return( false ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +unsigned long fpa::Filters::MarksInterface< _TTraits >:: +_GetMark( const TNode& n ) const +{ + return( this->_GetMark( n.Vertex ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +bool fpa::Filters::MarksInterface< _TTraits >:: +_IsMarked( const TNode& n ) const +{ + return( this->_IsMarked( n.Vertex ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::MarksInterface< _TTraits >:: +_Mark( const TNode& n ) +{ + this->_Mark( n.Vertex, ( unsigned long )( n.FrontId ) ); +} + +#endif // __fpa__Filters__MarksInterface__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/MarksWithCollisionsInterface.h b/lib/fpa/Filters/MarksWithCollisionsInterface.h new file mode 100644 index 0000000..18e1363 --- /dev/null +++ b/lib/fpa/Filters/MarksWithCollisionsInterface.h @@ -0,0 +1,62 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__MarksWithCollisionsInterface__h__ +#define __fpa__Filters__MarksWithCollisionsInterface__h__ + +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + /** + */ + template< class _TTraits > + class MarksWithCollisionsInterface + : public fpa::Filters::MarksInterface< _TTraits > + { + public: + typedef MarksWithCollisionsInterface Self; + typedef fpa::Filters::MarksInterface< _TTraits > Superclass; + typedef _TTraits TTraits; + fpaInternalTraitsMacro( typename, TTraits ); + + // Minigraph to represent collisions + typedef std::pair< TVertex, bool > TCollision; + typedef std::vector< TCollision > TCollisionsRow; + typedef std::vector< TCollisionsRow > TCollisions; + + public: + MarksWithCollisionsInterface( itk::ProcessObject* f ); + virtual ~MarksWithCollisionsInterface( ); + + bool StopAtOneFront( ) const; + void StopAtOneFrontOn( ); + void StopAtOneFrontOff( ); + void SetStopAtOneFront( bool v ); + + protected: + virtual void _InitCollisions( unsigned long nSeeds ) override; + virtual bool _Collisions( const TVertex& a, const TVertex& b ) override; + + protected: + bool m_StopAtOneFront; + TCollisions m_Collisions; + unsigned int m_NumberOfFronts; + unsigned int m_NumberOfSeeds; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Filters__MarksWithCollisionsInterface__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/MarksWithCollisionsInterface.hxx b/lib/fpa/Filters/MarksWithCollisionsInterface.hxx new file mode 100644 index 0000000..9a9852c --- /dev/null +++ b/lib/fpa/Filters/MarksWithCollisionsInterface.hxx @@ -0,0 +1,131 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__MarksWithCollisionsInterface__hxx__ +#define __fpa__Filters__MarksWithCollisionsInterface__hxx__ + +#include + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::MarksWithCollisionsInterface< _TTraits >:: +MarksWithCollisionsInterface( itk::ProcessObject* f ) + : Superclass( f ), + m_StopAtOneFront( false ), + m_NumberOfFronts( 0 ), + m_NumberOfSeeds( 0 ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::MarksWithCollisionsInterface< _TTraits >:: +~MarksWithCollisionsInterface( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +bool fpa::Filters::MarksWithCollisionsInterface< _TTraits >:: +StopAtOneFront( ) const +{ + return( this->m_StopAtOneFront ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::MarksWithCollisionsInterface< _TTraits >:: +StopAtOneFrontOn( ) +{ + this->SetStopAtOneFront( true ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::MarksWithCollisionsInterface< _TTraits >:: +StopAtOneFrontOff( ) +{ + this->SetStopAtOneFront( false ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::MarksWithCollisionsInterface< _TTraits >:: +SetStopAtOneFront( bool v ) +{ + if( this->m_StopAtOneFront != v ) + { + this->m_StopAtOneFront = v; + if( this->m_Filter != NULL ) + this->m_Filter->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::MarksWithCollisionsInterface< _TTraits >:: +_InitCollisions( unsigned long nSeeds ) +{ + this->m_NumberOfFronts = this->m_NumberOfSeeds = nSeeds; + TCollision coll( TVertex( ), false ); + TCollisionsRow row( this->m_NumberOfFronts, coll ); + this->m_Collisions.clear( ); + this->m_Collisions.resize( this->m_NumberOfFronts, row ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +bool fpa::Filters::MarksWithCollisionsInterface< _TTraits >:: +_Collisions( const TVertex& a, const TVertex& b ) +{ + unsigned long ma = this->_GetMark( a ); + unsigned long mb = this->_GetMark( b ); + if( ma == mb || ma == 0 || mb == 0 ) + return( false ); + + // Mark collision, if it is new + ma--; mb--; + bool ret = false; + bool exists = this->m_Collisions[ ma ][ mb ].second; + exists &= this->m_Collisions[ mb ][ ma ].second; + if( !exists ) + { + this->m_Collisions[ ma ][ mb ].first = a; + this->m_Collisions[ ma ][ mb ].second = true; + this->m_Collisions[ mb ][ ma ].first = b; + this->m_Collisions[ mb ][ ma ].second = true; + + // Update number of fronts + unsigned long count = 0; + std::vector< bool > m( this->m_NumberOfSeeds, false ); + std::queue< unsigned long > q; + q.push( 0 ); + while( !q.empty( ) ) + { + unsigned long f = q.front( ); + q.pop( ); + + if( m[ f ] ) + continue; + m[ f ] = true; + count++; + + for( unsigned int n = 0; n < this->m_NumberOfSeeds; ++n ) + if( this->m_Collisions[ f ][ n ].second && !m[ n ] ) + q.push( n ); + + } // elihw + this->m_NumberOfFronts = this->m_NumberOfSeeds - count + 1; + + } // fi + return( + this->m_StopAtOneFront && + this->m_NumberOfSeeds > 1 && + this->m_NumberOfFronts == 1 + ); +} + +#endif // __fpa__Filters__MarksWithCollisionsInterface__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Mori.h b/lib/fpa/Filters/Mori.h new file mode 100644 index 0000000..0bda0ff --- /dev/null +++ b/lib/fpa/Filters/Mori.h @@ -0,0 +1,124 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Mori__h__ +#define __fpa__Filters__Mori__h__ + +#include +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + /** + */ + template< class _TTraits > + class Mori + : public fpa::Filters::Algorithm< _TTraits > + { + public: + typedef _TTraits TTraits; + fpaTraitsMacro( typename, TTraits ); + + typedef fpa::Filters::Algorithm< TTraits > Superclass; + typedef Mori Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef std::deque< TNode > TQueue; + typedef std::set< TInputValue > TThresholds; + typedef fpa::Common::PeakDetector TPeakDetector; + typedef TPeakDetector::TPeak TPeak; + typedef fpa::Functors::RegionGrow::BinaryThreshold< TInputValue > TPredicate; + + protected: + itkConceptMacro( + Check_TOutputValue, + ( itk::Concept::IsUnsignedInteger< TOutputValue > ) + ); + + public: + itkTypeMacro( fpa::Filters::Image::Mori, fpa::Filters::Algorithm ); + + itkGetConstMacro( InsideValue, TOutputValue ); + itkSetMacro( InsideValue, TOutputValue ); + + itkGetConstMacro( MinimumThreshold, TInputValue ); + itkSetMacro( MinimumThreshold, TInputValue ); + + public: + TOutputValue GetOutsideValue( ) const; + void SetOutsideValue( const TOutputValue& v ); + + unsigned long GetSignalKernelSize( ) const; + void SetSignalKernelSize( unsigned long k ); + + double GetSignalThreshold( ) const; + void SetSignalThreshold( double t ); + + double GetSignalInfluence( ) const; + void SetSignalInfluence( double i ); + + void ClearThresholds( ); + void AddThreshold( const TInputValue& thr ); + void SetThresholds( + const TInputValue& lower, + const TInputValue& upper, + const TInputValue& delta + ); + const TThresholds& GetThresholds( ) const; + unsigned long GetNumberOfEvaluatedThresholds( ) const; + TInputValue GetOptimumThreshold( ) const; + void GetSignalValues( + unsigned long i, double& x, double& y, TPeak& p + ) const; + + protected: + Mori( ); + virtual ~Mori( ); + + virtual void _BeforeGenerateData( ); + virtual void _Reinitialize( ); + virtual void _UpdateOutputValue( TNode& n ) override; + virtual void _QueueClear( ) override; + virtual TNode _QueuePop( ) override; + virtual void _QueuePush( const TNode& n ) override; + virtual unsigned long _QueueSize( ) const override; + virtual void _ComputeOutputValue( TNode& n ) override; + + private: + // Purposely not implemented. + Mori( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TPredicate::Pointer m_Predicate; + + TOutputValue m_InsideValue; + TInputValue m_MinimumThreshold; + TThresholds m_Thresholds; + typename TThresholds::const_iterator m_CurrThr; + + TQueue m_Queues[ 2 ]; + unsigned int m_CurrQueue; + double m_CurrCount; + + TPeakDetector m_PeakDetector; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Filters__Mori__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/Mori.hxx b/lib/fpa/Filters/Mori.hxx new file mode 100644 index 0000000..a3969c8 --- /dev/null +++ b/lib/fpa/Filters/Mori.hxx @@ -0,0 +1,299 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__Mori__hxx__ +#define __fpa__Filters__Mori__hxx__ + +// ------------------------------------------------------------------------- +template< class _TTraits > +typename fpa::Filters::Mori< _TTraits >:: +TOutputValue fpa::Filters::Mori< _TTraits >:: +GetOutsideValue( ) const +{ + return( this->GetInitValue( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +SetOutsideValue( const TOutputValue& v ) +{ + this->SetInitValue( v ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +unsigned long fpa::Filters::Mori< _TTraits >:: +GetSignalKernelSize( ) const +{ + return( this->m_PeakDetector.GetKernelSize( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +SetSignalKernelSize( unsigned long k ) +{ + this->m_PeakDetector.SetKernelSize( k ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +double fpa::Filters::Mori< _TTraits >:: +GetSignalThreshold( ) const +{ + return( this->m_PeakDetector.GetThreshold( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +SetSignalThreshold( double t ) +{ + this->m_PeakDetector.SetThreshold( t ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +double fpa::Filters::Mori< _TTraits >:: +GetSignalInfluence( ) const +{ + return( this->m_PeakDetector.GetInfluence( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +SetSignalInfluence( double i ) +{ + this->m_PeakDetector.SetInfluence( i ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +ClearThresholds( ) +{ + this->m_Thresholds.clear( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +AddThreshold( const TInputValue& thr ) +{ + if( this->m_Thresholds.insert( thr ).second ) + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +const typename fpa::Filters::Mori< _TTraits >:: +TThresholds& fpa::Filters::Mori< _TTraits >:: +GetThresholds( ) const +{ + return( this->m_Thresholds ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +unsigned long fpa::Filters::Mori< _TTraits >:: +GetNumberOfEvaluatedThresholds( ) const +{ + return( this->m_PeakDetector.GetNumberOfSamples( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +typename fpa::Filters::Mori< _TTraits >:: +TInputValue fpa::Filters::Mori< _TTraits >:: +GetOptimumThreshold( ) const +{ + TInputValue thr = TInputValue( 0 ); + unsigned long n = this->m_PeakDetector.GetNumberOfSamples( ); + if( n > 1 ) + thr = TInputValue( this->m_PeakDetector.GetXValues( )[ n - 2 ] ); + return( thr ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +GetSignalValues( + unsigned long i, double& x, double& y, TPeak& p + ) const +{ + if( i < this->m_PeakDetector.GetNumberOfSamples( ) ) + { + x = this->m_PeakDetector.GetXValues( )[ i ]; + y = this->m_PeakDetector.GetYValues( )[ i ]; + p = this->m_PeakDetector.GetPeaks( )[ i ]; + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +SetThresholds( + const TInputValue& lower, + const TInputValue& upper, + const TInputValue& delta + ) +{ + for( TInputValue t = lower; t <= upper; t += delta ) + this->AddThreshold( t ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::Mori< _TTraits >:: +Mori( ) + : Superclass( ), + m_InsideValue( TOutputValue( 1 ) ) +{ + this->SetOutsideValue( 0 ); + this->m_Predicate = TPredicate::New( ); + this->m_Predicate->StrictOff( ); + if( std::numeric_limits< TInputValue >::is_integer ) + this->m_MinimumThreshold = std::numeric_limits< TInputValue >::min( ); + else + this->m_MinimumThreshold = -std::numeric_limits< TInputValue >::max( ); + this->m_PeakDetector.SetKernelSize( 20 ); + this->m_PeakDetector.SetThreshold( 500 ); + this->m_PeakDetector.SetInfluence( 0.5 ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::Mori< _TTraits >:: +~Mori( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +_BeforeGenerateData( ) +{ + this->Superclass::_BeforeGenerateData( ); + + // Prepare queues + this->_QueueClear( ); + this->m_CurrQueue = 0; + + // Prepare iteration over all thresholds + this->m_CurrThr = this->m_Thresholds.begin( ); + this->m_Predicate->SetLowerThreshold( *( this->m_CurrThr ) ); + this->m_CurrThr++; + this->m_Predicate->SetUpperThreshold( *( this->m_CurrThr ) ); + + // Prepare counting signal + this->m_CurrCount = double( 0 ); + this->m_PeakDetector.Clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +_Reinitialize( ) +{ + if( this->m_Queues[ this->m_CurrQueue ].size( ) == 0 ) + { + // Update peak detector + TPeak p = this->m_PeakDetector.AddValue( + *this->m_CurrThr, this->m_CurrCount + ); + this->m_CurrThr++; + this->m_CurrQueue = ( this->m_CurrQueue + 1 ) % 2; + if( this->m_CurrThr != this->m_Thresholds.end( ) ) + { + // Update predicate and counting value + this->m_Predicate->SetUpperThreshold( *( this->m_CurrThr ) ); + this->m_CurrCount = double( 0 ); + + // Peak detected? -> stop! + if( + p == TPeakDetector::PosPeak && + this->m_MinimumThreshold < *( this->m_CurrThr ) + ) + this->_QueueClear( ); + } + else + this->_QueueClear( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +_UpdateOutputValue( TNode& n ) +{ + TInputValue value = this->_GetInputValue( n.Vertex ); + bool inside = this->m_Predicate->Evaluate( value ); + if( !inside ) + { + n.Value = this->m_InitValue; + n.FrontId++; + this->m_Queues[ ( this->m_CurrQueue + 1 ) % 2 ].push_back( n ); + n.FrontId = 0; + } + else + { + n.Value = this->m_InsideValue; + this->m_CurrCount += double( 1 ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +_QueueClear( ) +{ + this->m_Queues[ 0 ].clear( ); + this->m_Queues[ 1 ].clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +typename fpa::Filters::Mori< _TTraits >:: +TNode fpa::Filters::Mori< _TTraits >:: +_QueuePop( ) +{ + TNode n = this->m_Queues[ this->m_CurrQueue ].front( ); + this->m_Queues[ this->m_CurrQueue ].pop_front( ); + return( n ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +_QueuePush( const TNode& n ) +{ + this->m_Queues[ this->m_CurrQueue ].push_back( n ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +unsigned long fpa::Filters::Mori< _TTraits >:: +_QueueSize( ) const +{ + return( this->m_Queues[ this->m_CurrQueue ].size( ) ); +} +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::Mori< _TTraits >:: +_ComputeOutputValue( TNode& n ) +{ + // Do nothing +} + +#endif // __fpa__Filters__Mori__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/RegionGrow.h b/lib/fpa/Filters/RegionGrow.h new file mode 100644 index 0000000..edf77cf --- /dev/null +++ b/lib/fpa/Filters/RegionGrow.h @@ -0,0 +1,95 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__RegionGrow__h__ +#define __fpa__Filters__RegionGrow__h__ + +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + /** + */ + template< class _TTraits > + class RegionGrow + : public fpa::Filters::Algorithm< _TTraits > + { + public: + typedef _TTraits TTraits; + fpaTraitsMacro( typename, TTraits ); + + typedef fpa::Filters::Algorithm< TTraits > Superclass; + typedef RegionGrow Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef std::deque< TNode > TQueue; + typedef itk::FunctionBase< TInputValue, bool > TScalarPredicate; + typedef fpa::Functors::BaseVertexFunction< TVertex, bool > TVertexPredicate; + + protected: + itkConceptMacro( + Check_TOutputValue, + ( itk::Concept::IsUnsignedInteger< TOutputValue > ) + ); + + public: + itkTypeMacro( fpa::Filters::RegionGrow, fpa::Filters::Algorithm ); + + itkGetConstObjectMacro( ScalarPredicate, TScalarPredicate ); + itkGetObjectMacro( ScalarPredicate, TScalarPredicate ); + + itkGetConstObjectMacro( VertexPredicate, TVertexPredicate ); + itkGetObjectMacro( VertexPredicate, TVertexPredicate ); + + itkGetConstMacro( InsideValue, TOutputValue ); + itkSetMacro( InsideValue, TOutputValue ); + + public: + void SetPredicate( TScalarPredicate* p ); + void SetPredicate( TVertexPredicate* p ); + + TOutputValue GetOutsideValue( ) const; + void SetOutsideValue( const TOutputValue& v ); + + protected: + RegionGrow( ); + virtual ~RegionGrow( ); + + virtual void _UpdateOutputValue( TNode& n ) override; + virtual void _QueueClear( ) override; + virtual TNode _QueuePop( ) override; + virtual void _QueuePush( const TNode& n ) override; + virtual unsigned long _QueueSize( ) const override; + virtual void _ComputeOutputValue( TNode& n ) override; + + private: + // Purposely not implemented. + RegionGrow( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TScalarPredicate::Pointer m_ScalarPredicate; + typename TVertexPredicate::Pointer m_VertexPredicate; + + TOutputValue m_InsideValue; + TQueue m_Queue; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Filters__RegionGrow__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/RegionGrow.hxx b/lib/fpa/Filters/RegionGrow.hxx new file mode 100644 index 0000000..b7167e6 --- /dev/null +++ b/lib/fpa/Filters/RegionGrow.hxx @@ -0,0 +1,136 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__RegionGrow__hxx__ +#define __fpa__Filters__RegionGrow__hxx__ + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::RegionGrow< _TTraits >:: +SetPredicate( TScalarPredicate* p ) +{ + if( this->m_ScalarPredicate.GetPointer( ) != p ) + { + this->_Deassociate( this->m_ScalarPredicate ); + this->m_ScalarPredicate = p; + this->_Associate( this->m_ScalarPredicate ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::RegionGrow< _TTraits >:: +SetPredicate( TVertexPredicate* p ) +{ + if( this->m_VertexPredicate.GetPointer( ) != p ) + { + this->_Deassociate( this->m_VertexPredicate ); + this->m_VertexPredicate = p; + this->_Associate( this->m_VertexPredicate ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +typename fpa::Filters::RegionGrow< _TTraits >:: +TOutputValue fpa::Filters::RegionGrow< _TTraits >:: +GetOutsideValue( ) const +{ + return( this->GetInitValue( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::RegionGrow< _TTraits >:: +SetOutsideValue( const TOutputValue& v ) +{ + this->SetInitValue( v ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::RegionGrow< _TTraits >:: +RegionGrow( ) + : Superclass( ), + m_InsideValue( TOutputValue( 1 ) ) +{ + this->SetOutsideValue( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::RegionGrow< _TTraits >:: +~RegionGrow( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::RegionGrow< _TTraits >:: +_UpdateOutputValue( TNode& n ) +{ + TInputValue value = this->_GetInputValue( n ); + bool inside = false; + if( this->m_ScalarPredicate.IsNotNull( ) ) + inside = this->m_ScalarPredicate->Evaluate( value ); + if( this->m_VertexPredicate.IsNotNull( ) ) + inside &= this->m_VertexPredicate->Evaluate( n.Vertex, n.Parent ); + if( !inside ) + { + n.Value = this->GetOutsideValue( ); + n.FrontId = 0; + } + else + n.Value = this->GetInsideValue( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::RegionGrow< _TTraits >:: +_QueueClear( ) +{ + this->m_Queue.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +typename fpa::Filters::RegionGrow< _TTraits >:: +TNode fpa::Filters::RegionGrow< _TTraits >:: +_QueuePop( ) +{ + TNode n = this->m_Queue.front( ); + this->m_Queue.pop_front( ); + return( n ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::RegionGrow< _TTraits >:: +_QueuePush( const TNode& n ) +{ + this->m_Queue.push_back( n ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +unsigned long fpa::Filters::RegionGrow< _TTraits >:: +_QueueSize( ) const +{ + return( this->m_Queue.size( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::RegionGrow< _TTraits >:: +_ComputeOutputValue( TNode& n ) +{ + // Do nothing +} + +#endif // __fpa__Filters__RegionGrow__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/SeedsInterface.h b/lib/fpa/Filters/SeedsInterface.h new file mode 100644 index 0000000..ffcaf25 --- /dev/null +++ b/lib/fpa/Filters/SeedsInterface.h @@ -0,0 +1,55 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__SeedsInterface__h__ +#define __fpa__Filters__SeedsInterface__h__ + +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + /** + */ + template< class _TTraits > + class SeedsInterface + { + public: + typedef SeedsInterface Self; + typedef _TTraits TTraits; + fpaInternalTraitsMacro( typename, TTraits ); + + public: + SeedsInterface( itk::ProcessObject* f ); + virtual ~SeedsInterface( ); + + void AddSeed( const TPoint& s ); + void AddSeed( const TVertex& s ); + void ClearSeeds( ); + unsigned long GetNumberOfSeeds( ) const; + + const TNodes& GetSeeds( ) const; + + protected: + virtual void _PrepareSeeds( const itk::DataObject* input ); + + protected: + TSeeds m_InputSeeds; + TNodes m_UnifiedSeeds; + itk::ProcessObject::Pointer m_Filter; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Filters__SeedsInterface__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/SeedsInterface.hxx b/lib/fpa/Filters/SeedsInterface.hxx new file mode 100644 index 0000000..43175b4 --- /dev/null +++ b/lib/fpa/Filters/SeedsInterface.hxx @@ -0,0 +1,98 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__SeedsInterface__hxx__ +#define __fpa__Filters__SeedsInterface__hxx__ + +#include + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::SeedsInterface< _TTraits >:: +SeedsInterface( itk::ProcessObject* f ) + : m_Filter( f ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::SeedsInterface< _TTraits >:: +~SeedsInterface( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::SeedsInterface< _TTraits >:: +AddSeed( const TPoint& s ) +{ + TSeed seed( this->m_InputSeeds.size( ) + 1 ); + seed.Point = s; + seed.IsPoint = true; + this->m_InputSeeds.push_back( seed ); + if( this->m_Filter.IsNotNull( ) ) + this->m_Filter->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::SeedsInterface< _TTraits >:: +AddSeed( const TVertex& s ) +{ + TSeed seed( this->m_InputSeeds.size( ) + 1 ); + seed.Vertex = s; + seed.IsPoint = false; + this->m_InputSeeds.push_back( seed ); + if( this->m_Filter.IsNotNull( ) ) + this->m_Filter->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::SeedsInterface< _TTraits >:: +ClearSeeds( ) +{ + this->m_InputSeeds.clear( ); + this->m_UnifiedSeeds.clear( ); + if( this->m_Filter.IsNotNull( ) ) + this->m_Filter->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +const typename fpa::Filters::SeedsInterface< _TTraits >:: +TNodes& fpa::Filters::SeedsInterface< _TTraits >:: +GetSeeds( ) const +{ + return( this->m_UnifiedSeeds ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::SeedsInterface< _TTraits >:: +_PrepareSeeds( const itk::DataObject* input ) +{ + // Input object is an image? + typedef itk::ImageBase< Self::Dimension > _TImageBase; + const _TImageBase* image = dynamic_cast< const _TImageBase* >( input ); + if( image != NULL ) + { + this->m_UnifiedSeeds.clear( ); + for( TSeed iSeed: this->m_InputSeeds ) + { + if( iSeed.IsPoint ) + image->TransformPhysicalPointToIndex( iSeed.Point, iSeed.Vertex ); + TNode node; + node.Vertex = iSeed.Vertex; + node.Parent = iSeed.Vertex; + node.FrontId = iSeed.FrontId; + this->m_UnifiedSeeds.insert( node ); + + } // rof + + } // fi +} + +#endif // __fpa__Filters__SeedsInterface__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/SingleSeedInterface.h b/lib/fpa/Filters/SingleSeedInterface.h new file mode 100644 index 0000000..1e80117 --- /dev/null +++ b/lib/fpa/Filters/SingleSeedInterface.h @@ -0,0 +1,53 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__SingleSeedInterface__h__ +#define __fpa__Filters__SingleSeedInterface__h__ + +#include +#include +#include + +namespace fpa +{ + namespace Filters + { + /** + */ + template< class _TTraits > + class SingleSeedInterface + { + public: + typedef SingleSeedInterface Self; + typedef _TTraits TTraits; + fpaInternalTraitsMacro( typename, TTraits ); + + public: + SingleSeedInterface( itk::ProcessObject* f ); + virtual ~SingleSeedInterface( ); + + void SetSeed( const TPoint& s ); + void SetSeed( const TVertex& s ); + + const TNodes& GetSeeds( ) const; + + protected: + virtual void _PrepareSeeds( const itk::DataObject* input ); + + protected: + TSeed m_InputSeed; + TNodes m_UnifiedSeed; + itk::ProcessObject::Pointer m_Filter; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Filters__SingleSeedInterface__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Filters/SingleSeedInterface.hxx b/lib/fpa/Filters/SingleSeedInterface.hxx new file mode 100644 index 0000000..c82b6b4 --- /dev/null +++ b/lib/fpa/Filters/SingleSeedInterface.hxx @@ -0,0 +1,78 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Filters__SingleSeedInterface__hxx__ +#define __fpa__Filters__SingleSeedInterface__hxx__ + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::SingleSeedInterface< _TTraits >:: +SingleSeedInterface( itk::ProcessObject* f ) + : m_Filter( f ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +fpa::Filters::SingleSeedInterface< _TTraits >:: +~SingleSeedInterface( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::SingleSeedInterface< _TTraits >:: +SetSeed( const TPoint& s ) +{ + this->m_InputSeed.Point = s; + this->m_InputSeed.IsPoint = true; + if( this->m_Filter.IsNotNull( ) ) + this->m_Filter->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::SingleSeedInterface< _TTraits >:: +SetSeed( const TVertex& s ) +{ + this->m_InputSeed.Vertex = s; + this->m_InputSeed.IsPoint = false; + if( this->m_Filter.IsNotNull( ) ) + this->m_Filter->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +const typename fpa::Filters::SingleSeedInterface< _TTraits >:: +TNodes& fpa::Filters::SingleSeedInterface< _TTraits >:: +GetSeeds( ) const +{ + return( this->m_UnifiedSeed ); +} + +// ------------------------------------------------------------------------- +template< class _TTraits > +void fpa::Filters::SingleSeedInterface< _TTraits >:: +_PrepareSeeds( const itk::DataObject* input ) +{ + // Input object is an image? + typedef itk::ImageBase< Self::Dimension > _TImageBase; + const _TImageBase* image = dynamic_cast< const _TImageBase* >( input ); + if( image != NULL ) + { + this->m_UnifiedSeed.clear( ); + TSeed iSeed = this->m_InputSeed; + if( iSeed.IsPoint ) + image->TransformPhysicalPointToIndex( iSeed.Point, iSeed.Vertex ); + TNode node; + node.Vertex = iSeed.Vertex; + node.Parent = iSeed.Vertex; + node.FrontId = iSeed.FrontId; + this->m_UnifiedSeed.insert( node ); + + } // fi +} + +#endif // __fpa__Filters__SingleSeedInterface__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Functors/BaseVertexFunction.h b/lib/fpa/Functors/BaseVertexFunction.h new file mode 100644 index 0000000..a29fc4d --- /dev/null +++ b/lib/fpa/Functors/BaseVertexFunction.h @@ -0,0 +1,110 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Functors__BaseVertexFunction__h__ +#define __fpa__Functors__BaseVertexFunction__h__ + +#include +#include + +namespace fpa +{ + namespace Functors + { + /** + */ + template< class _TVertex > + class LightBaseVertexFunction + : public itk::Object + { + public: + typedef _TVertex TVertex; + typedef itk::Object Superclass; + typedef LightBaseVertexFunction Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkTypeMacro( fpa::Functors::LightBaseVertexFunction, itk::Object ); + + itkSetConstObjectMacro( DataObject, itk::DataObject ); + + public: + template< class _TDataObject = itk::DataObject > + const _TDataObject* GetDataObject( ) const + { + return( + dynamic_cast< const _TDataObject* >( + this->m_DataObject.GetPointer( ) + ) + ); + } + + protected: + LightBaseVertexFunction( ) + : Superclass( ), + m_DataObject( NULL ) + { + } + + virtual ~LightBaseVertexFunction( ) + { + } + + private: + // Purposely not implemented. + LightBaseVertexFunction( const Self& other ); + Self& operator=( const Self& other ); + + protected: + itk::DataObject::ConstPointer m_DataObject; + }; + + /** + */ + template< class _TVertex, class _TValue > + class BaseVertexFunction + : public LightBaseVertexFunction< _TVertex > + { + public: + typedef _TVertex TVertex; + typedef _TValue TValue; + typedef LightBaseVertexFunction< _TVertex > Superclass; + typedef BaseVertexFunction Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkTypeMacro( + fpa::Functors::RegionGrow::BaseVertexFunction, + fpa::Functors::RegionGrow::LightBaseVertexFunction + ); + + public: + virtual TValue Evaluate( + const TVertex& vertex, const TVertex& parent + ) const = 0; + + protected: + BaseVertexFunction( ) + : Superclass( ) + { + } + + virtual ~BaseVertexFunction( ) + { + } + + private: + // Purposely not implemented. + BaseVertexFunction( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Functors__BaseVertexFunction__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Functors/Dijkstra/Image/Gaussian.h b/lib/fpa/Functors/Dijkstra/Image/Gaussian.h new file mode 100644 index 0000000..6cf78c5 --- /dev/null +++ b/lib/fpa/Functors/Dijkstra/Image/Gaussian.h @@ -0,0 +1,96 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Functors__Dijkstra__Image__Gaussian__h__ +#define __fpa__Functors__Dijkstra__Image__Gaussian__h__ + +#include +#include + +namespace fpa +{ + namespace Functors + { + namespace Dijkstra + { + namespace Image + { + /** + */ + template< class _TImage, class _TValue > + class Gaussian + : public fpa::Functors::BaseVertexFunction< typename _TImage::IndexType, _TValue > + { + public: + typedef _TImage TImage; + typedef _TValue TValue; + typedef typename TImage::IndexType TVertex; + typedef fpa::Functors::BaseVertexFunction< TVertex, TValue > Superclass; + typedef Gaussian Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Functors::Dijkstra::Image::Gaussian, + fpa::Functors::BaseVertexFunction + ); + + itkGetConstMacro( Alpha, double ); + itkSetMacro( Alpha, double ); + + itkGetConstMacro( Beta, double ); + itkSetMacro( Beta, double ); + + public: + virtual TValue Evaluate( const TVertex& v, const TVertex& p ) const override + { + const TImage* image = + dynamic_cast< const TImage* >( + this->m_DataObject.GetPointer( ) + ); + if( image != NULL ) + { + double d = double( image->GetPixel( v ) ); + d -= double( image->GetPixel( p ) ); + d /= this->m_Beta; + d = std::exp( d * d ) - double( 1 ); + return( TValue( std::pow( d, this->m_Alpha ) ) ); + } + else + return( TValue( -1 ) ); + } + + protected: + Gaussian( ) + : Superclass( ), + m_Alpha( double( 1 ) ), + m_Beta( double( 1 ) ) + { + } + virtual ~Gaussian( ) + { + } + + private: + // Purposely not implemented. + Gaussian( const Self& other ); + Self& operator=( const Self& other ); + + protected: + double m_Alpha; + double m_Beta; + }; + + } // ecapseman + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Functors__Dijkstra__Gaussian__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Functors/Dijkstra/Image/Identity.h b/lib/fpa/Functors/Dijkstra/Image/Identity.h new file mode 100644 index 0000000..f699486 --- /dev/null +++ b/lib/fpa/Functors/Dijkstra/Image/Identity.h @@ -0,0 +1,77 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Functors__Dijkstra__Image__Identity__h__ +#define __fpa__Functors__Dijkstra__Image__Identity__h__ + +#include + +namespace fpa +{ + namespace Functors + { + namespace Dijkstra + { + namespace Image + { + /** + */ + template< class _TImage, class _TValue > + class Identity + : public fpa::Functors::BaseVertexFunction< typename _TImage::IndexType, _TValue > + { + public: + typedef _TImage TImage; + typedef _TValue TValue; + typedef typename TImage::IndexType TVertex; + typedef fpa::Functors::BaseVertexFunction< TVertex, TValue > Superclass; + typedef Identity Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Functors::Dijkstra::Image::Identity, + fpa::Functors::BaseVertexFunction + ); + + public: + virtual TValue Evaluate( const TVertex& v, const TVertex& p ) const override + { + const TImage* image = + dynamic_cast< const TImage* >( + this->m_DataObject.GetPointer( ) + ); + if( image != NULL ) + return( TValue( image->GetPixel( v ) ) ); + else + return( TValue( -1 ) ); + } + + protected: + Identity( ) + : Superclass( ) + { + } + virtual ~Identity( ) + { + } + + private: + // Purposely not implemented. + Identity( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Functors__Dijkstra__Identity__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Functors/Dijkstra/Invert.h b/lib/fpa/Functors/Dijkstra/Invert.h new file mode 100644 index 0000000..af9bbe7 --- /dev/null +++ b/lib/fpa/Functors/Dijkstra/Invert.h @@ -0,0 +1,81 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Functors__Dijkstra__Invert__h__ +#define __fpa__Functors__Dijkstra__Invert__h__ + +#include + +namespace fpa +{ + namespace Functors + { + namespace Dijkstra + { + /** + */ + template< class _TValue > + class Invert + : public itk::FunctionBase< _TValue, _TValue > + { + public: + typedef _TValue TValue; + typedef itk::FunctionBase< _TValue, _TValue > Superclass; + typedef Invert Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( fpa::Functors::Dijkstra::Invert, itk::FunctionBase ); + + itkGetConstMacro( Alpha, double ); + itkSetMacro( Alpha, double ); + + itkGetConstMacro( Beta, double ); + itkSetMacro( Beta, double ); + + public: + virtual TValue Evaluate( const TValue& v ) const override + { + double a = double( v ); + double d = this->m_Alpha; + d += std::pow( double( a ), this->m_Beta ); + double x = -1; + if( std::fabs( d ) > double( 0 ) ) + x = + double( 1 ) / + ( this->m_Alpha + std::pow( double( a ), this->m_Beta ) ); + return( TValue( x ) ); + } + + protected: + Invert( ) + : Superclass( ), + m_Alpha( double( 1 ) ), + m_Beta( double( 1 ) ) + { + } + virtual ~Invert( ) + { + } + + private: + // Purposely not implemented. + Invert( const Self& other ); + Self& operator=( const Self& other ); + + protected: + double m_Alpha; + double m_Beta; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Functors__Dijkstra__Invert__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Functors/RegionGrow/BinaryThreshold.h b/lib/fpa/Functors/RegionGrow/BinaryThreshold.h new file mode 100644 index 0000000..b0fe54c --- /dev/null +++ b/lib/fpa/Functors/RegionGrow/BinaryThreshold.h @@ -0,0 +1,78 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Functors__RegionGrow__BinaryThreshold__h__ +#define __fpa__Functors__RegionGrow__BinaryThreshold__h__ + +#include + +namespace fpa +{ + namespace Functors + { + namespace RegionGrow + { + /** + */ + template< class _TValue > + class BinaryThreshold + : public itk::FunctionBase< _TValue, bool > + { + public: + typedef _TValue TValue; + typedef itk::FunctionBase< TValue, bool > Superclass; + typedef BinaryThreshold Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Functors::RegionGrow::BinaryThreshold, itk::FunctionBase + ); + + itkGetConstMacro( LowerThreshold, TValue ); + itkSetMacro( LowerThreshold, TValue ); + + itkGetConstMacro( UpperThreshold, TValue ); + itkSetMacro( UpperThreshold, TValue ); + + itkBooleanMacro( Strict ); + itkGetConstMacro( Strict, bool ); + itkSetMacro( Strict, bool ); + + public: + void ThresholdAbove( const TValue& a ); + void ThresholdBetween( const TValue& a, const TValue& b ); + void ThresholdBelow( const TValue& a ); + + virtual bool Evaluate( const TValue& v ) const override; + + protected: + BinaryThreshold( ); + virtual ~BinaryThreshold( ); + + private: + // Purposely not implemented. + BinaryThreshold( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TValue m_LowerThreshold; + TValue m_UpperThreshold; + bool m_Strict; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Functors__RegionGrow__BinaryThreshold__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/Functors/RegionGrow/BinaryThreshold.hxx b/lib/fpa/Functors/RegionGrow/BinaryThreshold.hxx new file mode 100644 index 0000000..f7ad48f --- /dev/null +++ b/lib/fpa/Functors/RegionGrow/BinaryThreshold.hxx @@ -0,0 +1,73 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Functors__RegionGrow__BinaryThreshold__hxx__ +#define __fpa__Functors__RegionGrow__BinaryThreshold__hxx__ + +#include + +// ------------------------------------------------------------------------- +template< class _TValue > +void fpa::Functors::RegionGrow::BinaryThreshold< _TValue >:: +ThresholdAbove( const TValue& a ) +{ + this->SetLowerThreshold( a ); + this->SetUpperThreshold( std::numeric_limits< _TValue >::max( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TValue > +void fpa::Functors::RegionGrow::BinaryThreshold< _TValue >:: +ThresholdBetween( const TValue& a, const TValue& b ) +{ + this->SetLowerThreshold( ( a < b )? a: b ); + this->SetUpperThreshold( ( b < a )? a: b ); +} + +// ------------------------------------------------------------------------- +template< class _TValue > +void fpa::Functors::RegionGrow::BinaryThreshold< _TValue >:: +ThresholdBelow( const TValue& a ) +{ + if( std::numeric_limits< _TValue >::is_integer ) + this->SetLowerThreshold( std::numeric_limits< _TValue >::min( ) ); + else + this->SetLowerThreshold( -std::numeric_limits< _TValue >::max( ) ); + this->SetUpperThreshold( a ); +} + +// ------------------------------------------------------------------------- +template< class _TValue > +bool fpa::Functors::RegionGrow::BinaryThreshold< _TValue >:: +Evaluate( const TValue& v ) const +{ + if( this->m_Strict ) + return( this->m_LowerThreshold < v && v < this->m_UpperThreshold ); + else + return( this->m_LowerThreshold <= v && v <= this->m_UpperThreshold ); +} + +// ------------------------------------------------------------------------- +template< class _TValue > +fpa::Functors::RegionGrow::BinaryThreshold< _TValue >:: +BinaryThreshold( ) + : Superclass( ), + m_Strict( true ) +{ + this->m_UpperThreshold = std::numeric_limits< _TValue >::max( ); + if( std::numeric_limits< _TValue >::is_integer ) + this->m_LowerThreshold = std::numeric_limits< _TValue >::min( ); + else + this->m_LowerThreshold = -this->m_UpperThreshold; +} + +// ------------------------------------------------------------------------- +template< class _TValue > +fpa::Functors::RegionGrow::BinaryThreshold< _TValue >:: +~BinaryThreshold( ) +{ +} + +#endif // __fpa__Functors__RegionGrow__BinaryThreshold__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Functors/RegionGrow/Tautology.h b/lib/fpa/Functors/RegionGrow/Tautology.h new file mode 100644 index 0000000..94fc0db --- /dev/null +++ b/lib/fpa/Functors/RegionGrow/Tautology.h @@ -0,0 +1,63 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__Functors__RegionGrow__Tautology__h__ +#define __fpa__Functors__RegionGrow__Tautology__h__ + +#include + +namespace fpa +{ + namespace Functors + { + namespace RegionGrow + { + /** + */ + template< class _TValue > + class Tautology + : public itk::FunctionBase< _TValue, bool > + { + public: + typedef _TValue TValue; + typedef itk::FunctionBase< TValue, bool > Superclass; + typedef Tautology Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Functors::RegionGrow::Tautology, itk::FunctionBase + ); + + public: + virtual bool Evaluate( const TValue& v ) const override + { + return( true ); + } + + protected: + Tautology( ) + : Superclass( ) + { + } + virtual ~Tautology( ) + { + } + + private: + // Purposely not implemented. + Tautology( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Functors__RegionGrow__Tautology__h__ +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image/PolyLineParametricPathToPolyDataFilter.h b/lib/fpa/VTK/Image/PolyLineParametricPathToPolyDataFilter.h new file mode 100644 index 0000000..a8b9ea0 --- /dev/null +++ b/lib/fpa/VTK/Image/PolyLineParametricPathToPolyDataFilter.h @@ -0,0 +1,73 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__VTK__Image__PolyLineParametricPathToPolyDataFilter__h__ +#define __fpa__VTK__Image__PolyLineParametricPathToPolyDataFilter__h__ + +#include + +namespace fpa +{ + namespace VTK + { + namespace Image + { + /** + */ + template< class _TPath > + class PolyLineParametricPathToPolyDataFilter + : public vtkPolyDataAlgorithm + { + public: + typedef PolyLineParametricPathToPolyDataFilter Self; + typedef _TPath TPath; + + public: + vtkTypeMacro( + PolyLineParametricPathToPolyDataFilter, + vtkPolyDataAlgorithm + ); + + public: + static Self* New( ); + + const TPath* GetInput( ) const; + void SetInput( const TPath* path ); + + protected: + PolyLineParametricPathToPolyDataFilter( ); + virtual ~PolyLineParametricPathToPolyDataFilter( ); + + int RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + int RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + + private: + // Purposely not implemented + PolyLineParametricPathToPolyDataFilter( const Self& ); + void operator=( const Self& ); + + protected: + const TPath* m_PolyLineParametricPath; + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION +#endif // __fpa__VTK__Image__PolyLineParametricPathToPolyDataFilter__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image/PolyLineParametricPathToPolyDataFilter.hxx b/lib/fpa/VTK/Image/PolyLineParametricPathToPolyDataFilter.hxx new file mode 100644 index 0000000..ad995aa --- /dev/null +++ b/lib/fpa/VTK/Image/PolyLineParametricPathToPolyDataFilter.hxx @@ -0,0 +1,133 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__VTK__Image__PolyLineParametricPathToPolyDataFilter__hxx__ +#define __fpa__VTK__Image__PolyLineParametricPathToPolyDataFilter__hxx__ + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TPath > +typename fpa::VTK::Image::PolyLineParametricPathToPolyDataFilter< _TPath >:: +Self* fpa::VTK::Image::PolyLineParametricPathToPolyDataFilter< _TPath >:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +const typename +fpa::VTK::Image::PolyLineParametricPathToPolyDataFilter< _TPath >:: +TPath* fpa::VTK::Image::PolyLineParametricPathToPolyDataFilter< _TPath >:: +GetInput( ) const +{ + return( this->m_PolyLineParametricPath ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +void fpa::VTK::Image::PolyLineParametricPathToPolyDataFilter< _TPath >:: +SetInput( const TPath* path ) +{ + if( this->m_PolyLineParametricPath != path ) + { + this->m_PolyLineParametricPath = path; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TPath > +fpa::VTK::Image::PolyLineParametricPathToPolyDataFilter< _TPath >:: +PolyLineParametricPathToPolyDataFilter( ) + : vtkPolyDataAlgorithm( ), + m_PolyLineParametricPath( NULL ) +{ + this->SetNumberOfInputPorts( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +fpa::VTK::Image::PolyLineParametricPathToPolyDataFilter< _TPath >:: +~PolyLineParametricPathToPolyDataFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TPath > +int fpa::VTK::Image::PolyLineParametricPathToPolyDataFilter< _TPath >:: +RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + static const unsigned int dim = TPath::PathDimension; + if( this->m_PolyLineParametricPath == NULL ) + return( 0 ); + + // Get output + vtkInformation* info = output->GetInformationObject( 0 ); + vtkPolyData* out = vtkPolyData::SafeDownCast( + info->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + + // Prepare data + out->SetPoints( vtkSmartPointer< vtkPoints >::New( ) ); + out->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetLines( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) ); + vtkSmartPointer< vtkUnsignedIntArray > darray = + vtkSmartPointer< vtkUnsignedIntArray >::New( ); + darray->SetNumberOfComponents( 1 ); + out->GetPointData( )->SetScalars( darray ); + vtkPoints* points = out->GetPoints( ); + vtkCellArray* lines = out->GetLines( ); + + // Assign all data + const TPath* path = this->GetInput( ); + for( unsigned long i = 0; i < path->GetSize( ); ++i ) + { + auto pnt = path->GetPoint( i ); + 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 ] ); + darray->InsertNextTuple1( double( i ) ); + if( i > 0 ) + { + lines->InsertNextCell( 2 ); + lines->InsertCellPoint( points->GetNumberOfPoints( ) - 2 ); + lines->InsertCellPoint( points->GetNumberOfPoints( ) - 1 ); + + } // fi + + } // rof + return( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TPath > +int fpa::VTK::Image::PolyLineParametricPathToPolyDataFilter< _TPath >:: +RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + return( 1 ); +} + +#endif // __fpa__VTK__Image__PolyLineParametricPathToPolyDataFilterFilter__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image/SkeletonToPolyDataFilter.h b/lib/fpa/VTK/Image/SkeletonToPolyDataFilter.h new file mode 100644 index 0000000..f34ae2e --- /dev/null +++ b/lib/fpa/VTK/Image/SkeletonToPolyDataFilter.h @@ -0,0 +1,71 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__VTK__Image__SkeletonToPolyDataFilter__h__ +#define __fpa__VTK__Image__SkeletonToPolyDataFilter__h__ + +#include + +namespace fpa +{ + namespace VTK + { + namespace Image + { + /** + */ + template< class _TSkeleton > + class SkeletonToPolyDataFilter + : public vtkPolyDataAlgorithm + { + public: + typedef SkeletonToPolyDataFilter Self; + typedef _TSkeleton TSkeleton; + + public: + vtkTypeMacro( SkeletonToPolyDataFilter, vtkPolyDataAlgorithm ); + + public: + static Self* New( ); + + const TSkeleton* GetInput( ) const; + void SetInput( const TSkeleton* sk ); + + protected: + SkeletonToPolyDataFilter( ); + virtual ~SkeletonToPolyDataFilter( ); + + int RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + int RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ); + + private: + // Purposely not implemented + SkeletonToPolyDataFilter( 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__Image__SkeletonToPolyDataFilter__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/VTK/Image/SkeletonToPolyDataFilter.hxx b/lib/fpa/VTK/Image/SkeletonToPolyDataFilter.hxx new file mode 100644 index 0000000..6b1aeef --- /dev/null +++ b/lib/fpa/VTK/Image/SkeletonToPolyDataFilter.hxx @@ -0,0 +1,154 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= +#ifndef __fpa__VTK__Image__SkeletonToPolyDataFilter__hxx__ +#define __fpa__VTK__Image__SkeletonToPolyDataFilter__hxx__ + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +typename fpa::VTK::Image::SkeletonToPolyDataFilter< _TSkeleton >:: +Self* fpa::VTK::Image::SkeletonToPolyDataFilter< _TSkeleton >:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +const typename +fpa::VTK::Image::SkeletonToPolyDataFilter< _TSkeleton >:: +TSkeleton* fpa::VTK::Image::SkeletonToPolyDataFilter< _TSkeleton >:: +GetInput( ) const +{ + return( this->m_Skeleton ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +void fpa::VTK::Image::SkeletonToPolyDataFilter< _TSkeleton >:: +SetInput( const TSkeleton* sk ) +{ + if( this->m_Skeleton != sk ) + { + this->m_Skeleton = sk; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +fpa::VTK::Image::SkeletonToPolyDataFilter< _TSkeleton >:: +SkeletonToPolyDataFilter( ) + : vtkPolyDataAlgorithm( ), + m_Skeleton( NULL ) +{ + this->SetNumberOfInputPorts( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +fpa::VTK::Image::SkeletonToPolyDataFilter< _TSkeleton >:: +~SkeletonToPolyDataFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +int fpa::VTK::Image::SkeletonToPolyDataFilter< _TSkeleton >:: +RequestData( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + typedef typename _TSkeleton::TPath _TPath; + static const unsigned int dim = _TPath::PathDimension; + + if( this->m_Skeleton == NULL ) + return( 0 ); + + // Get output + vtkInformation* info = output->GetInformationObject( 0 ); + vtkPolyData* out = vtkPolyData::SafeDownCast( + info->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + + // Prepare data + out->SetPoints( vtkSmartPointer< vtkPoints >::New( ) ); + out->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetLines( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) ); + out->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) ); + vtkSmartPointer< vtkUnsignedIntArray > darray = + vtkSmartPointer< vtkUnsignedIntArray >::New( ); + darray->SetNumberOfComponents( 1 ); + out->GetPointData( )->SetScalars( darray ); + vtkPoints* points = out->GetPoints( ); + vtkCellArray* lines = out->GetLines( ); + + // Assign all data + unsigned int dcount = 0; + typename TSkeleton::TMatrix::const_iterator mIt = this->m_Skeleton->BeginEdgesRows( ); + for( ; mIt != this->m_Skeleton->EndEdgesRows( ); ++mIt ) + { + // TODO: mIt->first; --> this is the row index. <-- + typename TSkeleton::TMatrixRow::const_iterator rIt = mIt->second.begin( ); + for( ; rIt != mIt->second.end( ); ++rIt ) + { + // TODO: rIt->first; --> this is the column index. + typename TSkeleton::TEdges::const_iterator eIt = rIt->second.begin( ); + for( ; eIt != rIt->second.end( ); ++eIt ) + { + _TPath* path = *eIt; + for( unsigned long i = 0; i < path->GetSize( ); ++i ) + { + auto pnt = path->GetPoint( i ); + 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 ] ); + darray->InsertNextTuple1( double( dcount ) ); + if( i > 0 ) + { + lines->InsertNextCell( 2 ); + lines->InsertCellPoint( points->GetNumberOfPoints( ) - 2 ); + lines->InsertCellPoint( points->GetNumberOfPoints( ) - 1 ); + + } // fi + + } // rof + dcount++; + + } // rof + + } // rof + + } // rof + return( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TSkeleton > +int fpa::VTK::Image::SkeletonToPolyDataFilter< _TSkeleton >:: +RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + return( 1 ); +} + +#endif // __fpa__VTK__Image__SkeletonToPolyDataFilterFilter__hxx__ +// eof - $RCSfile$ diff --git a/lib/fpa/Version.cxx.in b/lib/fpa/Version.cxx.in new file mode 100644 index 0000000..38f8172 --- /dev/null +++ b/lib/fpa/Version.cxx.in @@ -0,0 +1,11 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include + +std::string FPA_EXPORT version( ) { return( "@prj_VER@" ); } + +// eof - $RCSfile$ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..d769819 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,8 @@ +## ========================================================================= +## @author Leonardo Florez Valencia +## @email florez-l@javeriana.edu.co +## ========================================================================= + +subdirs(image) + +## eof - $RCSfile$ diff --git a/tests/image/CMakeLists.txt b/tests/image/CMakeLists.txt new file mode 100644 index 0000000..633fb98 --- /dev/null +++ b/tests/image/CMakeLists.txt @@ -0,0 +1,8 @@ +## ========================================================================= +## @author Leonardo Florez Valencia +## @email florez-l@javeriana.edu.co +## ========================================================================= + +subdirs(Dijkstra RandomWalker RegionGrow VTK) + +## eof - $RCSfile$ diff --git a/tests/image/Dijkstra/CMakeLists.txt b/tests/image/Dijkstra/CMakeLists.txt new file mode 100644 index 0000000..a68b3cc --- /dev/null +++ b/tests/image/Dijkstra/CMakeLists.txt @@ -0,0 +1,22 @@ +## ========================================================================= +## @author Leonardo Florez Valencia +## @email florez-l@javeriana.edu.co +## ========================================================================= + +set(_pfx test_fpa_Image_Dijkstra_) +set( + _tests + Identity + Invert + Gaussian + ExtractAxis + Skeleton + ) +include_directories(${PROJECT_SOURCE_DIR}/lib ${PROJECT_BINARY_DIR}/lib) + +foreach(_t ${_tests}) + add_executable(${_pfx}${_t} ${_t}.cxx) + target_link_libraries(${_pfx}${_t} fpa) +endforeach(_t) + +## eof - $RCSfile$ diff --git a/tests/image/Dijkstra/ExtractAxis.cxx b/tests/image/Dijkstra/ExtractAxis.cxx new file mode 100644 index 0000000..d9eb7ad --- /dev/null +++ b/tests/image/Dijkstra/ExtractAxis.cxx @@ -0,0 +1,80 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TPixel; +typedef float TScalar; +typedef itk::Image< TPixel, Dim > TImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 3 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image output_axis [seeds]" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_filename = argv[ 1 ]; + std::string output_path_filename = argv[ 2 ]; + + // Read image + typedef itk::ImageFileReader< TImage > TImageReader; + TImageReader::Pointer input_image_reader = TImageReader::New( ); + input_image_reader->SetFileName( input_image_filename ); + + // Prepare filter + typedef fpa::Filters::Image::ExtractAxis< TImage, TScalar > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( input_image_reader->GetOutput( ) ); + + // Get all seeds + for( int i = 3; i < argc; i += Dim ) + { + TImage::IndexType seed; + for( int j = 0; j < Dim; ++j ) + if( i + j < argc ) + seed[ j ] = std::atoi( argv[ i + j ] ); + filter->AddSeed( seed ); + if( i == 3 ) + filter->SetStartIndex( seed ); + else if( i == 4 ) + filter->SetEndIndex( seed ); + + } // rof + + // Execute filter + filter->Update( ); + + // Save results + typedef fpa::Common::Image::PolyLineParametricPathWriter< TFilter::TPath > TPathWriter; + TPathWriter::Pointer path_writer = TPathWriter::New( ); + path_writer->SetInput( filter->GetOutput( ) ); + path_writer->SetFileName( output_path_filename ); + + try + { + path_writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/Dijkstra/Gaussian.cxx b/tests/image/Dijkstra/Gaussian.cxx new file mode 100644 index 0000000..3139e83 --- /dev/null +++ b/tests/image/Dijkstra/Gaussian.cxx @@ -0,0 +1,102 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TInputPixel; +typedef float TOutputPixel; +typedef itk::Image< TInputPixel, Dim > TInputImage; +typedef itk::Image< TOutputPixel, Dim > TOutputImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 7 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image output_image output_marks output_mst alpha beta [seeds]" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_filename = argv[ 1 ]; + std::string output_image_filename = argv[ 2 ]; + std::string output_marks_filename = argv[ 3 ]; + std::string output_mst_filename = argv[ 4 ]; + double alpha = std::atof( argv[ 5 ] ); + double beta = std::atof( argv[ 6 ] ); + + // Read image + typedef itk::ImageFileReader< TInputImage > TInputImageReader; + TInputImageReader::Pointer input_image_reader = TInputImageReader::New( ); + input_image_reader->SetFileName( input_image_filename ); + + // Prepare weight functor + typedef fpa::Functors::Dijkstra::Image::Gaussian< TInputImage, TOutputPixel > TWeight; + TWeight::Pointer weight = TWeight::New( ); + weight->SetAlpha( alpha ); + weight->SetBeta( beta ); + + // Prepare filter + typedef fpa::Filters::Image::Dijkstra< TInputImage, TOutputImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( input_image_reader->GetOutput( ) ); + filter->SetWeightFunction( weight ); + + // Get all seeds + for( int i = 7; i < argc; i += Dim ) + { + TInputImage::IndexType seed; + for( int j = 0; j < Dim; ++j ) + if( i + j < argc ) + seed[ j ] = std::atoi( argv[ i + j ] ); + filter->AddSeed( seed ); + + } // rof + + // Execute filter + filter->Update( ); + + // Save results + typedef itk::ImageFileWriter< TFilter::TOutputImage > TOutputWriter; + TOutputWriter::Pointer output_writer = TOutputWriter::New( ); + output_writer->SetInput( filter->GetOutput( ) ); + output_writer->SetFileName( output_image_filename ); + + typedef itk::ImageFileWriter< TFilter::TMarksImage > TMarksWriter; + TMarksWriter::Pointer marks_writer = TMarksWriter::New( ); + marks_writer->SetInput( filter->GetMarks( ) ); + marks_writer->SetFileName( output_marks_filename ); + + typedef itk::ImageFileWriter< TFilter::TMST > TMSTWriter; + TMSTWriter::Pointer mst_writer = TMSTWriter::New( ); + mst_writer->SetInput( filter->GetMinimumSpanningTree( ) ); + mst_writer->SetFileName( output_mst_filename ); + + try + { + output_writer->Update( ); + marks_writer->Update( ); + mst_writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/Dijkstra/Identity.cxx b/tests/image/Dijkstra/Identity.cxx new file mode 100644 index 0000000..223283a --- /dev/null +++ b/tests/image/Dijkstra/Identity.cxx @@ -0,0 +1,93 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TInputPixel; +typedef float TOutputPixel; +typedef itk::Image< TInputPixel, Dim > TInputImage; +typedef itk::Image< TOutputPixel, Dim > TOutputImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 5 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " output_image output_marks output_mst size [seeds]" + << std::endl; + return( 1 ); + + } // fi + std::string output_image_filename = argv[ 1 ]; + std::string output_marks_filename = argv[ 2 ]; + std::string output_mst_filename = argv[ 3 ]; + TInputImage::SizeType size; + size.Fill( std::atoi( argv[ 4 ] ) ); + + // Create image + TInputImage::Pointer image = TInputImage::New( ); + image->SetRegions( size ); + image->Allocate( ); + image->FillBuffer( TInputPixel( 1 ) ); + + // Prepare filter + typedef fpa::Filters::Image::Dijkstra< TInputImage, TOutputImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( image ); + + // Get all seeds + for( int i = 5; i < argc; i += Dim ) + { + TInputImage::IndexType seed; + for( int j = 0; j < Dim; ++j ) + if( i + j < argc ) + seed[ j ] = std::atoi( argv[ i + j ] ); + filter->AddSeed( seed ); + + } // rof + + // Execute filter + filter->Update( ); + + // Save results + typedef itk::ImageFileWriter< TFilter::TOutputImage > TOutputWriter; + TOutputWriter::Pointer output_writer = TOutputWriter::New( ); + output_writer->SetInput( filter->GetOutput( ) ); + output_writer->SetFileName( output_image_filename ); + + typedef itk::ImageFileWriter< TFilter::TMarksImage > TMarksWriter; + TMarksWriter::Pointer marks_writer = TMarksWriter::New( ); + marks_writer->SetInput( filter->GetMarks( ) ); + marks_writer->SetFileName( output_marks_filename ); + + typedef itk::ImageFileWriter< TFilter::TMST > TMSTWriter; + TMSTWriter::Pointer mst_writer = TMSTWriter::New( ); + mst_writer->SetInput( filter->GetMinimumSpanningTree( ) ); + mst_writer->SetFileName( output_mst_filename ); + + try + { + output_writer->Update( ); + marks_writer->Update( ); + mst_writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/Dijkstra/Invert.cxx b/tests/image/Dijkstra/Invert.cxx new file mode 100644 index 0000000..fc0ace7 --- /dev/null +++ b/tests/image/Dijkstra/Invert.cxx @@ -0,0 +1,102 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TInputPixel; +typedef float TOutputPixel; +typedef itk::Image< TInputPixel, Dim > TInputImage; +typedef itk::Image< TOutputPixel, Dim > TOutputImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 7 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image output_image output_marks output_mst alpha beta [seeds]" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_filename = argv[ 1 ]; + std::string output_image_filename = argv[ 2 ]; + std::string output_marks_filename = argv[ 3 ]; + std::string output_mst_filename = argv[ 4 ]; + double alpha = std::atof( argv[ 5 ] ); + double beta = std::atof( argv[ 6 ] ); + + // Read image + typedef itk::ImageFileReader< TInputImage > TInputImageReader; + TInputImageReader::Pointer input_image_reader = TInputImageReader::New( ); + input_image_reader->SetFileName( input_image_filename ); + + // Prepare weight functor + typedef fpa::Functors::Dijkstra::Invert< TOutputPixel > TWeight; + TWeight::Pointer weight = TWeight::New( ); + weight->SetAlpha( alpha ); + weight->SetBeta( beta ); + + // Prepare filter + typedef fpa::Filters::Image::Dijkstra< TInputImage, TOutputImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( input_image_reader->GetOutput( ) ); + filter->SetWeightFunction( weight ); + + // Get all seeds + for( int i = 7; i < argc; i += Dim ) + { + TInputImage::IndexType seed; + for( int j = 0; j < Dim; ++j ) + if( i + j < argc ) + seed[ j ] = std::atoi( argv[ i + j ] ); + filter->AddSeed( seed ); + + } // rof + + // Execute filter + filter->Update( ); + + // Save results + typedef itk::ImageFileWriter< TFilter::TOutputImage > TOutputWriter; + TOutputWriter::Pointer output_writer = TOutputWriter::New( ); + output_writer->SetInput( filter->GetOutput( ) ); + output_writer->SetFileName( output_image_filename ); + + typedef itk::ImageFileWriter< TFilter::TMarksImage > TMarksWriter; + TMarksWriter::Pointer marks_writer = TMarksWriter::New( ); + marks_writer->SetInput( filter->GetMarks( ) ); + marks_writer->SetFileName( output_marks_filename ); + + typedef itk::ImageFileWriter< TFilter::TMST > TMSTWriter; + TMSTWriter::Pointer mst_writer = TMSTWriter::New( ); + mst_writer->SetInput( filter->GetMinimumSpanningTree( ) ); + mst_writer->SetFileName( output_mst_filename ); + + try + { + output_writer->Update( ); + marks_writer->Update( ); + mst_writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/Dijkstra/Skeleton.cxx b/tests/image/Dijkstra/Skeleton.cxx new file mode 100644 index 0000000..b792d39 --- /dev/null +++ b/tests/image/Dijkstra/Skeleton.cxx @@ -0,0 +1,82 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TPixel; +typedef itk::Image< TPixel, Dim > TImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 3 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image output_skeleton [seed]" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_filename = argv[ 1 ]; + std::string output_skeleton_filename = argv[ 2 ]; + + // Read image + typedef itk::ImageFileReader< TImage > TImageReader; + TImageReader::Pointer input_image_reader = TImageReader::New( ); + input_image_reader->SetFileName( input_image_filename ); + + // Prepare filter + typedef fpa::Filters::Image::Skeleton< TImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( input_image_reader->GetOutput( ) ); + + // Get seed + if( argc >= Dim + 3 ) + { + TImage::IndexType seed; + for( int j = 0; j < Dim; ++j ) + if( 3 + j < argc ) + seed[ j ] = std::atoi( argv[ 3 + j ] ); + filter->SeedFromMaximumDistanceOff( ); + filter->SetSeed( seed ); + } + else + filter->SeedFromMaximumDistanceOn( ); + + // Configure distance map + filter->GetDistanceMap( )->InsideIsPositiveOn( ); + filter->GetDistanceMap( )->SquaredDistanceOff( ); + filter->GetDistanceMap( )->UseImageSpacingOn( ); + + // Execute filter + filter->Update( ); + + // Save results + typedef fpa::Common::Image::SkeletonWriter< TFilter::TSkeleton > TSkeletonWriter; + TSkeletonWriter::Pointer skeleton_writer = TSkeletonWriter::New( ); + skeleton_writer->SetInput( filter->GetOutput( ) ); + skeleton_writer->SetFileName( output_skeleton_filename ); + + try + { + skeleton_writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/RandomWalker/CMakeLists.txt b/tests/image/RandomWalker/CMakeLists.txt new file mode 100644 index 0000000..e4bd49a --- /dev/null +++ b/tests/image/RandomWalker/CMakeLists.txt @@ -0,0 +1,18 @@ +## ========================================================================= +## @author Leonardo Florez Valencia +## @email florez-l@javeriana.edu.co +## ========================================================================= + +set(_pfx test_fpa_Image_RandomWalker_) +set( + _tests + Gaussian + ) +include_directories(${PROJECT_SOURCE_DIR}/lib ${PROJECT_BINARY_DIR}/lib) + +foreach(_t ${_tests}) + add_executable(${_pfx}${_t} ${_t}.cxx) + target_link_libraries(${_pfx}${_t} fpa) +endforeach(_t) + +## eof - $RCSfile$ diff --git a/tests/image/RandomWalker/Gaussian.cxx b/tests/image/RandomWalker/Gaussian.cxx new file mode 100644 index 0000000..be6016e --- /dev/null +++ b/tests/image/RandomWalker/Gaussian.cxx @@ -0,0 +1,94 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TInputPixel; +typedef unsigned char TInputLabel; +typedef float TOutputPixel; +typedef itk::Image< TInputPixel, Dim > TInputImage; +typedef itk::Image< TInputLabel, Dim > TInputLabelImage; +typedef itk::Image< TOutputPixel, Dim > TOutputImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 7 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image input_labels output_image output_costs alpha beta" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_filename = argv[ 1 ]; + std::string input_labels_filename = argv[ 2 ]; + std::string output_image_filename = argv[ 3 ]; + std::string output_costs_filename = argv[ 4 ]; + double alpha = std::atof( argv[ 5 ] ); + double beta = std::atof( argv[ 6 ] ); + + // Read image + typedef itk::ImageFileReader< TInputImage > TInputImageReader; + TInputImageReader::Pointer input_image_reader = TInputImageReader::New( ); + input_image_reader->SetFileName( input_image_filename ); + + // Read labels + typedef itk::ImageFileReader< TInputLabelImage > TInputLabelImageReader; + TInputLabelImageReader::Pointer input_labels_reader = + TInputLabelImageReader::New( ); + input_labels_reader->SetFileName( input_labels_filename ); + + // Prepare weight functor + typedef fpa::Functors::Dijkstra::Image::Gaussian< TInputImage, TOutputPixel > TWeight; + TWeight::Pointer weight = TWeight::New( ); + weight->SetAlpha( alpha ); + weight->SetBeta( beta ); + + // Prepare filter + typedef fpa::Filters::Image::RandomWalker< TInputImage, TInputLabelImage, TOutputImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInputImage( input_image_reader->GetOutput( ) ); + filter->SetInputLabels( input_labels_reader->GetOutput( ) ); + filter->SetWeightFunction( weight ); + + // Execute filter + filter->Update( ); + + // Save results + typedef itk::ImageFileWriter< TFilter::TOutputLabels > TOutputWriter; + TOutputWriter::Pointer output_writer = TOutputWriter::New( ); + output_writer->SetInput( filter->GetOutputLabels( ) ); + output_writer->SetFileName( output_image_filename ); + + typedef itk::ImageFileWriter< TFilter::TCostsImage > TCostsWriter; + TCostsWriter::Pointer costs_writer = TCostsWriter::New( ); + costs_writer->SetInput( filter->GetOutputCosts( ) ); + costs_writer->SetFileName( output_costs_filename ); + + try + { + output_writer->Update( ); + costs_writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/RegionGrow/BinaryThreshold.cxx b/tests/image/RegionGrow/BinaryThreshold.cxx new file mode 100644 index 0000000..3e15d36 --- /dev/null +++ b/tests/image/RegionGrow/BinaryThreshold.cxx @@ -0,0 +1,95 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TPixel; +typedef itk::Image< TPixel, Dim > TImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 6 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image output_image output_marks lower upper [seeds]" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_filename = argv[ 1 ]; + std::string output_image_filename = argv[ 2 ]; + std::string output_marks_filename = argv[ 3 ]; + TPixel lower = TPixel( std::atof( argv[ 4 ] ) ); + TPixel upper = TPixel( std::atof( argv[ 5 ] ) ); + + // Read image + typedef itk::ImageFileReader< TImage > TImageReader; + TImageReader::Pointer input_image_reader = TImageReader::New( ); + input_image_reader->SetFileName( input_image_filename ); + + // Prepare predicate + typedef fpa::Functors::RegionGrow::BinaryThreshold< TPixel > TPredicate; + TPredicate::Pointer predicate = TPredicate::New( ); + predicate->SetLowerThreshold( lower ); + predicate->SetUpperThreshold( upper ); + + // Prepare filter + typedef fpa::Filters::Image::RegionGrow< TImage, TImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( input_image_reader->GetOutput( ) ); + filter->SetPredicate( predicate ); + filter->SetInsideValue( std::numeric_limits< TPixel >::max( ) ); + filter->SetOutsideValue( TPixel( 0 ) ); + + // Get all seeds + for( int i = 6; i < argc; i += Dim ) + { + TImage::IndexType seed; + for( int j = 0; j < Dim; ++j ) + if( i + j < argc ) + seed[ j ] = std::atoi( argv[ i + j ] ); + filter->AddSeed( seed ); + + } // rof + + // Execute filter + filter->Update( ); + + // Save results + typedef itk::ImageFileWriter< TFilter::TOutputImage > TOutputWriter; + TOutputWriter::Pointer output_writer = TOutputWriter::New( ); + output_writer->SetInput( filter->GetOutput( ) ); + output_writer->SetFileName( output_image_filename ); + + typedef itk::ImageFileWriter< TFilter::TMarksImage > TMarksWriter; + TMarksWriter::Pointer marks_writer = TMarksWriter::New( ); + marks_writer->SetInput( filter->GetMarks( ) ); + marks_writer->SetFileName( output_marks_filename ); + + try + { + output_writer->Update( ); + marks_writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/RegionGrow/CMakeLists.txt b/tests/image/RegionGrow/CMakeLists.txt new file mode 100644 index 0000000..e5c55b5 --- /dev/null +++ b/tests/image/RegionGrow/CMakeLists.txt @@ -0,0 +1,20 @@ +## ========================================================================= +## @author Leonardo Florez Valencia +## @email florez-l@javeriana.edu.co +## ========================================================================= + +set(_pfx test_fpa_Image_RegionGrow_) +set( + _tests + Tautology + BinaryThreshold + Mori + ) +include_directories(${PROJECT_SOURCE_DIR}/lib ${PROJECT_BINARY_DIR}/lib) + +foreach(_t ${_tests}) + add_executable(${_pfx}${_t} ${_t}.cxx) + target_link_libraries(${_pfx}${_t} fpa) +endforeach(_t) + +## eof - $RCSfile$ diff --git a/tests/image/RegionGrow/Mori.cxx b/tests/image/RegionGrow/Mori.cxx new file mode 100644 index 0000000..8d11ac2 --- /dev/null +++ b/tests/image/RegionGrow/Mori.cxx @@ -0,0 +1,82 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TPixel; +typedef itk::Image< TPixel, Dim > TImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 9 + Dim ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image output_image lower upper delta seed" + << std::endl; + return( 1 ); + + } // fi + std::string input_image_filename = argv[ 1 ]; + std::string output_image_filename = argv[ 2 ]; + TPixel lower = TPixel( std::atof( argv[ 3 ] ) ); + TPixel upper = TPixel( std::atof( argv[ 4 ] ) ); + TPixel delta = TPixel( std::atof( argv[ 5 ] ) ); + unsigned long signal_kernel_size = std::atoi( argv[ 6 ] ); + double signal_threshold = std::atof( argv[ 7 ] ); + double signal_influence = std::atof( argv[ 8 ] ); + + // Read image + typedef itk::ImageFileReader< TImage > TImageReader; + TImageReader::Pointer input_image_reader = TImageReader::New( ); + input_image_reader->SetFileName( input_image_filename ); + + // Prepare filter + typedef fpa::Filters::Image::Mori< TImage, TImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( input_image_reader->GetOutput( ) ); + filter->SetInsideValue( std::numeric_limits< TPixel >::max( ) ); + filter->SetOutsideValue( TPixel( 0 ) ); + filter->SetThresholds( lower, upper, delta ); + filter->SetSignalKernelSize( signal_kernel_size ); + filter->SetSignalThreshold( signal_threshold ); + filter->SetSignalInfluence( signal_influence ); + + // Configure seed + TImage::IndexType seed; + for( int j = 0; j < Dim; ++j ) + seed[ j ] = std::atoi( argv[ 9 + j ] ); + filter->SetSeed( seed ); + + // Execute filter + filter->Update( ); + + // Save results + typedef itk::ImageFileWriter< TFilter::TOutputImage > TOutputWriter; + TOutputWriter::Pointer output_writer = TOutputWriter::New( ); + output_writer->SetInput( filter->GetOutput( ) ); + output_writer->SetFileName( output_image_filename ); + try + { + output_writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/RegionGrow/Tautology.cxx b/tests/image/RegionGrow/Tautology.cxx new file mode 100644 index 0000000..0bbdc45 --- /dev/null +++ b/tests/image/RegionGrow/Tautology.cxx @@ -0,0 +1,92 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TPixel; +typedef itk::Image< TPixel, Dim > TImage; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 4 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " output_image output_marks size [seeds]" + << std::endl; + return( 1 ); + + } // fi + std::string output_image_filename = argv[ 1 ]; + std::string output_marks_filename = argv[ 2 ]; + TImage::SizeType size; + size.Fill( std::atoi( argv[ 3 ] ) ); + + // Create image + TImage::Pointer image = TImage::New( ); + image->SetRegions( size ); + image->Allocate( ); + image->FillBuffer( TPixel( 0 ) ); + + // Prepare predicate + typedef fpa::Functors::RegionGrow::Tautology< TPixel > TPredicate; + TPredicate::Pointer predicate = TPredicate::New( ); + + // Prepare filter + typedef fpa::Filters::Image::RegionGrow< TImage, TImage > TFilter; + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( image ); + filter->SetPredicate( predicate ); + filter->SetInsideValue( std::numeric_limits< TPixel >::max( ) ); + filter->SetOutsideValue( TPixel( 0 ) ); + + // Get all seeds + for( int i = 4; i < argc; i += Dim ) + { + TImage::IndexType seed; + for( int j = 0; j < Dim; ++j ) + if( i + j < argc ) + seed[ j ] = std::atoi( argv[ i + j ] ); + filter->AddSeed( seed ); + + } // rof + + // Execute filter + filter->Update( ); + + // Save results + typedef itk::ImageFileWriter< TFilter::TOutputImage > TOutputWriter; + TOutputWriter::Pointer output_writer = TOutputWriter::New( ); + output_writer->SetInput( filter->GetOutput( ) ); + output_writer->SetFileName( output_image_filename ); + + typedef itk::ImageFileWriter< TFilter::TMarksImage > TMarksWriter; + TMarksWriter::Pointer marks_writer = TMarksWriter::New( ); + marks_writer->SetInput( filter->GetMarks( ) ); + marks_writer->SetFileName( output_marks_filename ); + + try + { + output_writer->Update( ); + marks_writer->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/VTK/CMakeLists.txt b/tests/image/VTK/CMakeLists.txt new file mode 100644 index 0000000..3328b46 --- /dev/null +++ b/tests/image/VTK/CMakeLists.txt @@ -0,0 +1,21 @@ +## ========================================================================= +## @author Leonardo Florez Valencia +## @email florez-l@javeriana.edu.co +## ========================================================================= + +if(VTK_FOUND) + set(_pfx test_fpa_Image_VTK_) + set( + _tests + PolyLineParametricPathToPolyData + SkeletonToPolyData + ) + include_directories(${PROJECT_SOURCE_DIR}/lib ${PROJECT_BINARY_DIR}/lib) + + foreach(_t ${_tests}) + add_executable(${_pfx}${_t} ${_t}.cxx) + target_link_libraries(${_pfx}${_t} fpa ${VTK_LIBRARIES}) + endforeach(_t) +endif(VTK_FOUND) + +## eof - $RCSfile$ diff --git a/tests/image/VTK/PolyLineParametricPathToPolyData.cxx b/tests/image/VTK/PolyLineParametricPathToPolyData.cxx new file mode 100644 index 0000000..e92af29 --- /dev/null +++ b/tests/image/VTK/PolyLineParametricPathToPolyData.cxx @@ -0,0 +1,54 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef fpa::DataStructures::Image::PolyLineParametricPath< Dim > TPath; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 3 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_path output_vtk" + << std::endl; + return( 1 ); + + } // fi + std::string input_path_filename = argv[ 1 ]; + std::string output_vtk_filename = argv[ 2 ]; + + // Read image + typedef fpa::Common::Image::PolyLineParametricPathReader< TPath > TReader; + TReader::Pointer input_path_reader = TReader::New( ); + input_path_reader->SetFileName( input_path_filename ); + input_path_reader->Update( ); + + // Execute filter + typedef fpa::VTK::Image::PolyLineParametricPathToPolyDataFilter< TPath > TFilter; + vtkSmartPointer< TFilter > filter = vtkSmartPointer< TFilter >::New( ); + filter->SetInput( input_path_reader->GetOutput( ) ); + filter->Update( ); + + // Save results + vtkSmartPointer< vtkPolyDataWriter > output_vtk_writer = + vtkSmartPointer< vtkPolyDataWriter >::New( ); + output_vtk_writer->SetFileName( output_vtk_filename.c_str( ) ); + output_vtk_writer->SetInputConnection( filter->GetOutputPort( ) ); + output_vtk_writer->Update( ); + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/VTK/SkeletonToPolyData.cxx b/tests/image/VTK/SkeletonToPolyData.cxx new file mode 100644 index 0000000..0c58d56 --- /dev/null +++ b/tests/image/VTK/SkeletonToPolyData.cxx @@ -0,0 +1,54 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef fpa::DataStructures::Image::Skeleton< Dim > TSkeleton; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 3 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_skeleton output_vtk" + << std::endl; + return( 1 ); + + } // fi + std::string input_skeleton_filename = argv[ 1 ]; + std::string output_vtk_filename = argv[ 2 ]; + + // Read image + typedef fpa::Common::Image::SkeletonReader< TSkeleton > TReader; + TReader::Pointer input_skeleton_reader = TReader::New( ); + input_skeleton_reader->SetFileName( input_skeleton_filename ); + input_skeleton_reader->Update( ); + + // Execute filter + typedef fpa::VTK::Image::SkeletonToPolyDataFilter< TSkeleton > TFilter; + vtkSmartPointer< TFilter > filter = vtkSmartPointer< TFilter >::New( ); + filter->SetInput( input_skeleton_reader->GetOutput( ) ); + filter->Update( ); + + // Save results + vtkSmartPointer< vtkPolyDataWriter > output_vtk_writer = + vtkSmartPointer< vtkPolyDataWriter >::New( ); + output_vtk_writer->SetFileName( output_vtk_filename.c_str( ) ); + output_vtk_writer->SetInputConnection( filter->GetOutputPort( ) ); + output_vtk_writer->Update( ); + + return( 0 ); +} + +// eof - $RCSfile$