]> Creatis software - FrontAlgorithms.git/commitdiff
...
authorLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Mon, 28 Aug 2017 20:46:40 +0000 (15:46 -0500)
committerLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Mon, 28 Aug 2017 20:46:40 +0000 (15:46 -0500)
94 files changed:
lib/CMakeLists.txt [new file with mode: 0644]
lib/fpa/CMakeLists.txt [new file with mode: 0644]
lib/fpa/Common/Image/PathReader.h [new file with mode: 0644]
lib/fpa/Common/Image/PathReader.hxx [new file with mode: 0644]
lib/fpa/Common/Image/PathWriter.h [new file with mode: 0644]
lib/fpa/Common/Image/PathWriter.hxx [new file with mode: 0644]
lib/fpa/Common/Image/SkeletonReader.h [new file with mode: 0644]
lib/fpa/Common/Image/SkeletonReader.hxx [new file with mode: 0644]
lib/fpa/Common/Image/SkeletonWriter.h [new file with mode: 0644]
lib/fpa/Common/Image/SkeletonWriter.hxx [new file with mode: 0644]
lib/fpa/Common/IncrementalMeanAndVariance.cxx [new file with mode: 0644]
lib/fpa/Common/IncrementalMeanAndVariance.h [new file with mode: 0644]
lib/fpa/Common/PeakDetector.cxx [new file with mode: 0644]
lib/fpa/Common/PeakDetector.h [new file with mode: 0644]
lib/fpa/Config.h.in [new file with mode: 0644]
lib/fpa/DataStructures/Graph.h [new file with mode: 0644]
lib/fpa/DataStructures/Graph.hxx [new file with mode: 0644]
lib/fpa/DataStructures/Image/MinimumSpanningTree.h [new file with mode: 0644]
lib/fpa/DataStructures/Image/MinimumSpanningTree.hxx [new file with mode: 0644]
lib/fpa/DataStructures/Image/Path.h [new file with mode: 0644]
lib/fpa/DataStructures/Image/Path.hxx [new file with mode: 0644]
lib/fpa/DataStructures/Image/Skeleton.h [new file with mode: 0644]
lib/fpa/DataStructures/Image/Skeleton.hxx [new file with mode: 0644]
lib/fpa/DataStructures/MinimumSpanningTree.h [new file with mode: 0644]
lib/fpa/DataStructures/MinimumSpanningTree.hxx [new file with mode: 0644]
lib/fpa/Filters/Algorithm.h [new file with mode: 0644]
lib/fpa/Filters/Algorithm.hxx [new file with mode: 0644]
lib/fpa/Filters/BaseMarksInterface.h [new file with mode: 0644]
lib/fpa/Filters/BaseSeedsInterface.h [new file with mode: 0644]
lib/fpa/Filters/CollisionMarksInterface.h [new file with mode: 0644]
lib/fpa/Filters/CollisionMarksInterface.hxx [new file with mode: 0644]
lib/fpa/Filters/Dijkstra.h [new file with mode: 0644]
lib/fpa/Filters/Dijkstra.hxx [new file with mode: 0644]
lib/fpa/Filters/Event.h [new file with mode: 0644]
lib/fpa/Filters/Event.hxx [new file with mode: 0644]
lib/fpa/Filters/Image/DefaultTraits.h [new file with mode: 0644]
lib/fpa/Filters/Image/Dijkstra.h [new file with mode: 0644]
lib/fpa/Filters/Image/Dijkstra.hxx [new file with mode: 0644]
lib/fpa/Filters/Image/ExtractAxis.h [new file with mode: 0644]
lib/fpa/Filters/Image/ExtractAxis.hxx [new file with mode: 0644]
lib/fpa/Filters/Image/ExtractSkeleton.h [new file with mode: 0644]
lib/fpa/Filters/Image/ExtractSkeleton.hxx [new file with mode: 0644]
lib/fpa/Filters/Image/Interface.h [new file with mode: 0644]
lib/fpa/Filters/Image/Interface.hxx [new file with mode: 0644]
lib/fpa/Filters/Image/Mori.h [new file with mode: 0644]
lib/fpa/Filters/Image/Mori.hxx [new file with mode: 0644]
lib/fpa/Filters/Image/MoriTraits.h [new file with mode: 0644]
lib/fpa/Filters/Image/RandomWalker.h [new file with mode: 0644]
lib/fpa/Filters/Image/RandomWalker.hxx [new file with mode: 0644]
lib/fpa/Filters/Image/RandomWalkerTraits.h [new file with mode: 0644]
lib/fpa/Filters/Image/RegionGrow.h [new file with mode: 0644]
lib/fpa/Filters/Image/SeedsFromLabelsInterface.h [new file with mode: 0644]
lib/fpa/Filters/Image/SeedsFromLabelsInterface.hxx [new file with mode: 0644]
lib/fpa/Filters/Mori.h [new file with mode: 0644]
lib/fpa/Filters/Mori.hxx [new file with mode: 0644]
lib/fpa/Filters/MultipleSeedsInterface.h [new file with mode: 0644]
lib/fpa/Filters/MultipleSeedsInterface.hxx [new file with mode: 0644]
lib/fpa/Filters/PriorityQueueAlgorithm.h [new file with mode: 0644]
lib/fpa/Filters/PriorityQueueAlgorithm.hxx [new file with mode: 0644]
lib/fpa/Filters/QueueAlgorithm.h [new file with mode: 0644]
lib/fpa/Filters/QueueAlgorithm.hxx [new file with mode: 0644]
lib/fpa/Filters/RandomWalker.h [new file with mode: 0644]
lib/fpa/Filters/RandomWalker.hxx [new file with mode: 0644]
lib/fpa/Filters/RegionGrow.h [new file with mode: 0644]
lib/fpa/Filters/RegionGrow.hxx [new file with mode: 0644]
lib/fpa/Filters/SingleSeedInterface.h [new file with mode: 0644]
lib/fpa/Filters/SingleSeedInterface.hxx [new file with mode: 0644]
lib/fpa/Functors/BaseVertexFunction.h [new file with mode: 0644]
lib/fpa/Functors/Dijkstra/Image/Gaussian.h [new file with mode: 0644]
lib/fpa/Functors/Dijkstra/Image/Identity.h [new file with mode: 0644]
lib/fpa/Functors/Dijkstra/Invert.h [new file with mode: 0644]
lib/fpa/Functors/RegionGrow/BinaryThreshold.h [new file with mode: 0644]
lib/fpa/Functors/RegionGrow/BinaryThreshold.hxx [new file with mode: 0644]
lib/fpa/Functors/RegionGrow/Tautology.h [new file with mode: 0644]
lib/fpa/Functors/VertexFunction.h [new file with mode: 0644]
lib/fpa/VTK/Image/PathToPolyDataFilter.h [new file with mode: 0644]
lib/fpa/VTK/Image/PathToPolyDataFilter.hxx [new file with mode: 0644]
lib/fpa/VTK/Image/SkeletonToPolyDataFilter.h [new file with mode: 0644]
lib/fpa/VTK/Image/SkeletonToPolyDataFilter.hxx [new file with mode: 0644]
lib/fpa/Version.cxx.in [new file with mode: 0644]
tests/CMakeLists.txt [new file with mode: 0644]
tests/image/CMakeLists.txt [new file with mode: 0644]
tests/image/Dijkstra/CMakeLists.txt [new file with mode: 0644]
tests/image/Dijkstra/ExtractAxis.cxx [new file with mode: 0644]
tests/image/Dijkstra/ExtractSkeleton.cxx [new file with mode: 0644]
tests/image/Dijkstra/Gaussian.cxx [new file with mode: 0644]
tests/image/Dijkstra/Identity.cxx [new file with mode: 0644]
tests/image/Dijkstra/Invert.cxx [new file with mode: 0644]
tests/image/RandomWalker/CMakeLists.txt [new file with mode: 0644]
tests/image/RandomWalker/Gaussian.cxx [new file with mode: 0644]
tests/image/RegionGrow/BinaryThreshold.cxx [new file with mode: 0644]
tests/image/RegionGrow/CMakeLists.txt [new file with mode: 0644]
tests/image/RegionGrow/Mori.cxx [new file with mode: 0644]
tests/image/RegionGrow/Tautology.cxx [new file with mode: 0644]

diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d7d1948
--- /dev/null
@@ -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 (file)
index 0000000..1ac13cd
--- /dev/null
@@ -0,0 +1,76 @@
+## =========================================================================
+## @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)
+set(_dirs Common DataStructures Filters Functors)
+if(VTK_FOUND)
+  list(APPEND _dirs VTK)
+endif(VTK_FOUND)
+set(_src)
+set(_hdr)
+set(_hrc)
+foreach(_d ${_dirs})
+  file(GLOB_RECURSE _s "${CMAKE_CURRENT_SOURCE_DIR}/${_d}/*.cxx")
+  file(GLOB_RECURSE _h "${CMAKE_CURRENT_SOURCE_DIR}/${_d}/*.h")
+  file(GLOB_RECURSE _t "${CMAKE_CURRENT_SOURCE_DIR}/${_d}/*.hxx")
+  list(APPEND _src ${_s})
+  list(APPEND _hdr ${_h})
+  list(APPEND _hrc ${_t})
+endforeach(_d)
+
+## =====================
+## == Compile library ==
+## =====================
+
+add_library(
+  fpa SHARED
+  "${CMAKE_CURRENT_BINARY_DIR}/Version.cxx"
+  "${CMAKE_CURRENT_BINARY_DIR}/Config.h"
+  ${_src} ${_hdr} ${_hrc}
+  )
+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} ${VTK_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/PathReader.h b/lib/fpa/Common/Image/PathReader.h
new file mode 100644 (file)
index 0000000..4ae4d0a
--- /dev/null
@@ -0,0 +1,85 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Common__Image__PathReader__h__
+#define __fpa__Common__Image__PathReader__h__
+
+#include <itkProcessObject.h>
+
+namespace fpa
+{
+  namespace Common
+  {
+    namespace Image
+    {
+      /**
+       */
+      template< class _TPath >
+      class PathReader
+        : public itk::ProcessObject
+      {
+      public:
+        // Basic types
+        typedef PathReader    Self;
+        typedef itk::ProcessObject              Superclass;
+        typedef itk::SmartPointer< Self >       Pointer;
+        typedef itk::SmartPointer< const Self > ConstPointer;
+
+        typedef _TPath TPath;
+
+      public:
+        itkNewMacro( Self );
+        itkTypeMacro( PathReader, 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:
+        PathReader( );
+        virtual ~PathReader( );
+
+        virtual void GenerateData( ) override;
+
+        // Do nothing
+        virtual void GenerateOutputInformation( ) override
+          { }
+
+      private:
+        // Purposely not implemented
+        PathReader( const Self& );
+        void operator=( const Self& );
+
+      protected:
+        std::string m_FileName;
+      };
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Common/Image/PathReader.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+#endif // __fpa__Common__Image__PathReader__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Common/Image/PathReader.hxx b/lib/fpa/Common/Image/PathReader.hxx
new file mode 100644 (file)
index 0000000..e66af4f
--- /dev/null
@@ -0,0 +1,172 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Common__Image__PathReader__hxx__
+#define __fpa__Common__Image__PathReader__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+_TPath* fpa::Common::Image::PathReader< _TPath >::
+GetOutput( )
+{
+  return(
+    itkDynamicCastInDebugMode< TPath* >( this->GetPrimaryOutput( ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+_TPath* fpa::Common::Image::PathReader< _TPath >::
+GetOutput( unsigned int i )
+{
+  return(
+    itkDynamicCastInDebugMode< TPath* >(
+      this->itk::ProcessObject::GetOutput( i )
+      )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+void fpa::Common::Image::PathReader< _TPath >::
+GraftOutput( itk::DataObject* out )
+{
+  this->GraftNthOutput( 0, out );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+void fpa::Common::Image::PathReader< _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::PathReader< _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::PathReader< _TPath >::
+MakeOutput( itk::ProcessObject::DataObjectPointerArraySizeType i )
+{
+  return( TPath::New( ).GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+fpa::Common::Image::PathReader< _TPath >::
+PathReader( )
+  : 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::PathReader< _TPath >::
+~PathReader( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+void fpa::Common::Image::PathReader< _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__PathReader__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Common/Image/PathWriter.h b/lib/fpa/Common/Image/PathWriter.h
new file mode 100644 (file)
index 0000000..621161e
--- /dev/null
@@ -0,0 +1,69 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Common__Image__PathWriter__h__
+#define __fpa__Common__Image__PathWriter__h__
+
+#include <itkProcessObject.h>
+
+namespace fpa
+{
+  namespace Common
+  {
+    namespace Image
+    {
+      /**
+       */
+      template< class _TPath >
+      class PathWriter
+        : public itk::ProcessObject
+      {
+      public:
+        // Basic types
+        typedef PathWriter    Self;
+        typedef itk::ProcessObject              Superclass;
+        typedef itk::SmartPointer< Self >       Pointer;
+        typedef itk::SmartPointer< const Self > ConstPointer;
+
+        typedef _TPath TPath;
+
+      public:
+        itkNewMacro( Self );
+        itkTypeMacro( PathWriter, 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:
+        PathWriter( );
+        virtual ~PathWriter( );
+
+        virtual void GenerateData( ) override;
+
+      private:
+        // Purposely not implemented
+        PathWriter( const Self& );
+        void operator=( const Self& );
+
+      protected:
+        std::string m_FileName;
+      };
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Common/Image/PathWriter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+#endif // __fpa__Common__Image__PathWriter__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Common/Image/PathWriter.hxx b/lib/fpa/Common/Image/PathWriter.hxx
new file mode 100644 (file)
index 0000000..fc3d840
--- /dev/null
@@ -0,0 +1,111 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Common__Image__PathWriter__hxx__
+#define __fpa__Common__Image__PathWriter__hxx__
+
+#include <fstream>
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+const _TPath* fpa::Common::Image::PathWriter< _TPath >::
+GetInput( ) const
+{
+  return(
+    dynamic_cast< const TPath* >(
+      this->itk::ProcessObject::GetInput( 0 )
+      )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+void fpa::Common::Image::PathWriter< _TPath >::
+SetInput( const _TPath* path )
+{
+  this->itk::ProcessObject::SetNthInput( 0, const_cast< TPath* >( path ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+void fpa::Common::Image::PathWriter< _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::PathWriter< _TPath >::
+PathWriter( )
+  : Superclass( ),
+    m_FileName( "" )
+{
+  this->SetNumberOfRequiredInputs( 1 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+fpa::Common::Image::PathWriter< _TPath >::
+~PathWriter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+void fpa::Common::Image::PathWriter< _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__PathWriter__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Common/Image/SkeletonReader.h b/lib/fpa/Common/Image/SkeletonReader.h
new file mode 100644 (file)
index 0000000..cc64aae
--- /dev/null
@@ -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 <itkProcessObject.h>
+
+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 <fpa/Common/Image/SkeletonReader.hxx>
+#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 (file)
index 0000000..ee886c5
--- /dev/null
@@ -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 (file)
index 0000000..6348daf
--- /dev/null
@@ -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 <itkProcessObject.h>
+
+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 <fpa/Common/Image/SkeletonWriter.hxx>
+#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 (file)
index 0000000..4f392ed
--- /dev/null
@@ -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 <fstream>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..ea88f03
--- /dev/null
@@ -0,0 +1,74 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#include <fpa/Common/IncrementalMeanAndVariance.h>
+#include <cmath>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..83383c3
--- /dev/null
@@ -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 <fpa/fpa_export.h>
+
+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 (file)
index 0000000..0a53e1e
--- /dev/null
@@ -0,0 +1,187 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#include <fpa/Common/PeakDetector.h>
+#include <cmath>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..8796cc3
--- /dev/null
@@ -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 <vector>
+#include <fpa/fpa_export.h>
+#include <fpa/Common/IncrementalMeanAndVariance.h>
+
+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 (file)
index 0000000..831fb72
--- /dev/null
@@ -0,0 +1,87 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Config__h__
+#define __fpa__Config__h__
+
+#include <itkMacro.h>
+
+// -------------------------------------------------------------------------
+#define fpaTraitsMacro( __t__ )                                 \
+  typedef __t__::TInternalTraits::TInputValue   TInputValue;    \
+  typedef __t__::TInternalTraits::TNeighborhood TNeighborhood;  \
+  typedef __t__::TInternalTraits::TMark         TMark;          \
+  typedef __t__::TInternalTraits::TNode         TNode;          \
+  typedef __t__::TInternalTraits::TNodes        TNodes;         \
+  typedef __t__::TInternalTraits::TOutputValue  TOutputValue;   \
+  typedef __t__::TInternalTraits::TPoint        TPoint;         \
+  typedef __t__::TInternalTraits::TSeed         TSeed;          \
+  typedef __t__::TInternalTraits::TSeeds        TSeeds;         \
+  typedef __t__::TInternalTraits::TVertex       TVertex
+
+// -------------------------------------------------------------------------
+#define fpaFilterInputMacro( __n__, __t__ )                             \
+  private:                                                              \
+  unsigned int m_##__n__##Idx;                                          \
+  public:                                                               \
+  __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__ )    \
+  private:                                      \
+  unsigned int m_##__n__##Idx;                  \
+  public:                                       \
+  __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 (file)
index 0000000..76a617a
--- /dev/null
@@ -0,0 +1,167 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__DataStructures__Graph__h__
+#define __fpa__DataStructures__Graph__h__
+
+#include <map>
+#include <set>
+#include <vector>
+#include <itkDataObject.h>
+#include <itkObjectFactory.h>
+
+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 <fpa/DataStructures/Graph.hxx>
+#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 (file)
index 0000000..4d348d5
--- /dev/null
@@ -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 (file)
index 0000000..5adcbad
--- /dev/null
@@ -0,0 +1,77 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__DataStructures__Image__MinimumSpanningTree__h__
+#define __fpa__DataStructures__Image__MinimumSpanningTree__h__
+
+#include <itkImage.h>
+#include <fpa/DataStructures/MinimumSpanningTree.h>
+#include <fpa/DataStructures/Image/Path.h>
+
+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::Path< _VDim > TPath;
+
+      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 GetPath( typename TPath::Pointer& path, const TVertex& a ) const;
+        void GetPath(
+          typename TPath::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 <fpa/DataStructures/Image/MinimumSpanningTree.hxx>
+#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 (file)
index 0000000..29a547c
--- /dev/null
@@ -0,0 +1,71 @@
+// =========================================================================
+// @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 >::
+GetPath( typename TPath::Pointer& path, const TVertex& a ) const
+{
+  TVertices v = this->GetAxis( a );
+  if( path.IsNull( ) )
+    path = TPath::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 >::
+GetPath(
+  typename TPath::Pointer& path, const TVertex& a, const TVertex& b
+  ) const
+{
+  TVertices v = this->GetAxis( a, b );
+  if( path.IsNull( ) )
+    path = TPath::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/Path.h b/lib/fpa/DataStructures/Image/Path.h
new file mode 100644 (file)
index 0000000..3194f90
--- /dev/null
@@ -0,0 +1,104 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__DataStructures__Image__Path__h__
+#define __fpa__DataStructures__Image__Path__h__
+
+#include <itkPolyLineParametricPath.h>
+#include <itkImageBase.h>
+
+namespace fpa
+{
+  namespace DataStructures
+  {
+    namespace Image
+    {
+      /**
+       */
+      template< unsigned int _VDim >
+      class Path
+        : public itk::PolyLineParametricPath< _VDim >
+      {
+      public:
+        typedef Path                                 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( Path, 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:
+        Path( );
+        virtual ~Path( );
+
+        virtual void _ComputeIndexToPhysicalPointMatrices( );
+
+      private:
+        // Purposely not implemented
+        Path( 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 <fpa/DataStructures/Image/Path.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__DataStructures__Image__Path__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/DataStructures/Image/Path.hxx b/lib/fpa/DataStructures/Image/Path.hxx
new file mode 100644 (file)
index 0000000..7fc32cf
--- /dev/null
@@ -0,0 +1,215 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#ifndef __fpa__DataStructures__Image__Path__hxx__
+#define __fpa__DataStructures__Image__Path__hxx__
+
+#include <itkMath.h>
+#include <itkNumericTraits.h>
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+unsigned long fpa::DataStructures::Image::Path< _VDim >::
+GetSize( ) const
+{
+  return( this->GetVertexList( )->Size( ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+typename fpa::DataStructures::Image::Path< _VDim >::
+TContinuousIndex fpa::DataStructures::Image::Path< _VDim >::
+GetContinuousVertex( unsigned long i ) const
+{
+  return( this->GetVertexList( )->GetElement( i ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+typename fpa::DataStructures::Image::Path< _VDim >::
+TIndex fpa::DataStructures::Image::Path< _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::Path< _VDim >::
+TPoint fpa::DataStructures::Image::Path< _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::Path< _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::Path< _VDim >::
+SetSpacing( const double spac[ _VDim ] )
+{
+  this->SetSpacing( TSpacing( spac ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::DataStructures::Image::Path< _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::Path< _VDim >::
+SetOrigin( const double ori[ _VDim ] )
+{
+  this->SetOrigin( TPoint( ori ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::DataStructures::Image::Path< _VDim >::
+SetOrigin( const float ori[ _VDim ] )
+{
+  this->SetOrigin( TPoint( ori ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::DataStructures::Image::Path< _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::Path< _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::Path< _VDim >::
+Path( )
+  : 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::Path< _VDim >::
+~Path( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void fpa::DataStructures::Image::Path< _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__Path__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/DataStructures/Image/Skeleton.h b/lib/fpa/DataStructures/Image/Skeleton.h
new file mode 100644 (file)
index 0000000..f51295a
--- /dev/null
@@ -0,0 +1,68 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__DataStructures__Image__Skeleton__h__
+#define __fpa__DataStructures__Image__Skeleton__h__
+
+#include <vector>
+#include <fpa/DataStructures/Graph.h>
+#include <fpa/DataStructures/Image/Path.h>
+
+namespace fpa
+{
+  namespace DataStructures
+  {
+    namespace Image
+    {
+      /**
+       */
+      template< unsigned int _VDim >
+      class Skeleton
+        : public fpa::DataStructures::Graph< typename fpa::DataStructures::Image::Path< _VDim >::TIndex, typename fpa::DataStructures::Image::Path< _VDim >::Pointer, typename fpa::DataStructures::Image::Path< _VDim >::TIndex, typename fpa::DataStructures::Image::Path< _VDim >::TIndex::LexicographicCompare >
+      {
+      public:
+        typedef fpa::DataStructures::Image::Path< _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 <fpa/DataStructures/Image/Skeleton.hxx>
+#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 (file)
index 0000000..c3316da
--- /dev/null
@@ -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 (file)
index 0000000..aa5c89a
--- /dev/null
@@ -0,0 +1,74 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__DataStructures__MinimumSpanningTree__h__
+#define __fpa__DataStructures__MinimumSpanningTree__h__
+
+#include <vector>
+
+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 GetAxis( const TVertex& a ) const;
+      virtual TVertices GetAxis( 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 <fpa/DataStructures/MinimumSpanningTree.hxx>
+#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 (file)
index 0000000..2d6a906
--- /dev/null
@@ -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 >::
+GetAxis( 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 >::
+GetAxis( const _TVertex& a, const _TVertex& b ) const
+{
+  static const unsigned long _inf =
+    std::numeric_limits< unsigned long >::max( );
+
+  TVertices vertices;
+  TVertices pa = this->GetAxis( a );
+  TVertices pb = this->GetAxis( 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->GetAxis(
+          a, this->m_Collisions[ fpath[ 0 ] ][ fpath[ 1 ] ].first
+          );
+
+        // Intermediary paths
+        for( unsigned int i = 1; i < N - 1; ++i )
+        {
+          TVertices ipath =
+            this->GetAxis(
+              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->GetAxis(
+            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 (file)
index 0000000..bf0a44f
--- /dev/null
@@ -0,0 +1,114 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Algorithm__h__
+#define __fpa__Filters__Algorithm__h__
+
+#include <set>
+#include <itkDataObject.h>
+#include <fpa/Config.h>
+#include <fpa/Filters/Event.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    /**
+     */
+    template< class _TTraits >
+    class Algorithm
+      : public _TTraits::TFilterInterface,
+        public _TTraits::TMarksInterface,
+        public _TTraits::TSeedsInterface
+    {
+    public:
+      typedef _TTraits TTraits;
+      fpaTraitsMacro( typename TTraits );
+
+      typedef typename TTraits::TFilterInterface Superclass;
+      typedef Algorithm                          Self;
+      typedef itk::SmartPointer< Self >          Pointer;
+      typedef itk::SmartPointer< const Self >    ConstPointer;
+
+      typedef fpa::Filters::Event< TVertex > TEvent;
+
+    public:
+      itkTypeMacro( fpa::Filters::Algorithm, TTraits::TFilterInterface );
+
+      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( );
+
+      // Main algorithm method
+      virtual void GenerateData( ) override;
+
+      // Object association
+      void _Associate( itk::Object* o );
+      void _Deassociate( itk::Object* o );
+      void _DeassociateAll( );
+
+      // Pipeline related methods
+      virtual void _BeforeGenerateData( );
+      virtual void _AfterGenerateData( );
+
+      // Filter related methods
+      virtual void _AssignOutputValue( const TNode& n ) = 0;
+      virtual void _ConfigureOutputs( ) = 0;
+      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 TNeighborhood _GetNeighbors( const TNode& n ) const;
+      virtual const itk::DataObject* _GetReferenceInput( ) const;
+
+      // Marks related methods
+      virtual bool _IsMarked( const TVertex& v ) const = 0;
+      virtual bool _IsMarked( const TNode& n ) const;
+      virtual bool _IsNotMarked( const TVertex& v ) const;
+      virtual bool _IsNotMarked( const TNode& n ) const;
+      virtual void _Mark( const TNode& n ) = 0;
+
+      // Queue related methods
+      virtual void _QueueClear( ) = 0;
+      virtual TNode _QueuePop( ) = 0;
+      virtual void _QueuePush( const TNode& n ) = 0;
+      virtual unsigned long _QueueSize( ) const = 0;
+
+      // Algoritm related methods
+      virtual void _PostComputeOutputValue( TNode& n ) = 0;
+      virtual void _PreComputeOutputValue( TNode& n ) = 0;
+      virtual void _Reinitialize( );
+
+    private:
+      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 <fpa/Filters/Algorithm.hxx>
+#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 (file)
index 0000000..be4eacc
--- /dev/null
@@ -0,0 +1,285 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Algorithm__hxx__
+#define __fpa__Filters__Algorithm__hxx__
+
+#include <fpa/Functors/BaseVertexFunction.h>
+
+// -------------------------------------------------------------------------
+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( ),
+    TTraits::TMarksInterface( this ),
+    TTraits::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->_IsNotMarked( node ) )
+    {
+      // Update output value and mark vertex
+      this->_PostComputeOutputValue( node );
+      this->_AssignOutputValue( 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->_PreComputeOutputValue( 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::BaseVertexFunction< TVertex > _TFunction;
+  const itk::DataObject* input = this->GetInput( );
+  for( itk::Object* o: this->m_AssociatedObjects )
+  {
+    _TFunction* f = dynamic_cast< _TFunction* >( o );
+    if( f != NULL )
+      f->SetDataObject( input );
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::Algorithm< _TTraits >::
+_AfterGenerateData( )
+{
+  // Nothing to do at this level
+}
+
+// -------------------------------------------------------------------------
+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 ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+typename fpa::Filters::Algorithm< _TTraits >::
+TNeighborhood fpa::Filters::Algorithm< _TTraits >::
+_GetNeighbors( const TNode& n ) const
+{
+  return( this->_GetNeighbors( n.Vertex )  );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+const itk::DataObject* fpa::Filters::Algorithm< _TTraits >::
+_GetReferenceInput( ) const
+{
+  return( this->GetInput( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+bool fpa::Filters::Algorithm< _TTraits >::
+_IsMarked( const TNode& n ) const
+{
+  return( this->_IsMarked( n.Vertex ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+bool fpa::Filters::Algorithm< _TTraits >::
+_IsNotMarked( const TVertex& v ) const
+{
+  return( !( this->_IsMarked( v ) ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+bool fpa::Filters::Algorithm< _TTraits >::
+_IsNotMarked( const TNode& n ) const
+{
+  return( this->_IsNotMarked( n.Vertex ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::Algorithm< _TTraits >::
+_Reinitialize( )
+{
+  // Nothing to do at this level
+}
+
+#endif // __fpa__Filters__Algorithm__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/BaseMarksInterface.h b/lib/fpa/Filters/BaseMarksInterface.h
new file mode 100644 (file)
index 0000000..df6557d
--- /dev/null
@@ -0,0 +1,53 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__BaseMarksInterface__h__
+#define __fpa__Filters__BaseMarksInterface__h__
+
+#include <itkProcessObject.h>
+#include <fpa/Config.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    /**
+     */
+    template< class _TTraits >
+    class BaseMarksInterface
+    {
+    public:
+      typedef BaseMarksInterface Self;
+      typedef _TTraits           TTraits;
+      fpaTraitsMacro( typename TTraits );
+
+    protected:
+      BaseMarksInterface( itk::ProcessObject* f )
+        : m_Filter( f )
+        {
+        }
+      virtual ~BaseMarksInterface( )
+        {
+        }
+
+      virtual unsigned long _GetMark( const TVertex& v ) const = 0;
+      virtual bool _Collisions( const TVertex& a, const TVertex& b )
+        {
+          return( false );
+        }
+      virtual void _InitCollisions( unsigned long nSeeds )
+        {
+          // Nothing to do at this level
+        }
+
+    protected:
+      itk::ProcessObject::Pointer m_Filter;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Filters__BaseMarksInterface__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/BaseSeedsInterface.h b/lib/fpa/Filters/BaseSeedsInterface.h
new file mode 100644 (file)
index 0000000..89b054f
--- /dev/null
@@ -0,0 +1,53 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__BaseSeedsInterface__h__
+#define __fpa__Filters__BaseSeedsInterface__h__
+
+#include <itkDataObject.h>
+#include <itkProcessObject.h>
+#include <fpa/Config.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    /**
+     */
+    template< class _TTraits >
+    class BaseSeedsInterface
+    {
+    public:
+      typedef BaseSeedsInterface Self;
+      typedef _TTraits           TTraits;
+      fpaTraitsMacro( typename TTraits );
+
+    public:
+      const TNodes& GetSeeds( ) const
+        {
+          return( this->m_UnifiedSeeds );
+        }
+
+    protected:
+      BaseSeedsInterface( itk::ProcessObject* f )
+        : m_Filter( f )
+        {
+        }
+      virtual ~BaseSeedsInterface( )
+        {
+        }
+
+      virtual void _PrepareSeeds( const itk::DataObject* reference ) = 0;
+
+    protected:
+      TNodes m_UnifiedSeeds;
+      itk::ProcessObject::Pointer m_Filter;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Filters__BaseSeedsInterface__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/CollisionMarksInterface.h b/lib/fpa/Filters/CollisionMarksInterface.h
new file mode 100644 (file)
index 0000000..e748c46
--- /dev/null
@@ -0,0 +1,61 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__CollisionMarksInterface__h__
+#define __fpa__Filters__CollisionMarksInterface__h__
+
+#include <utility>
+#include <vector>
+#include <fpa/Filters/BaseMarksInterface.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    /**
+     */
+    template< class _TTraits >
+    class CollisionMarksInterface
+      : public fpa::Filters::BaseMarksInterface< _TTraits >
+    {
+    public:
+      typedef fpa::Filters::BaseMarksInterface< _TTraits > Superclass;
+      typedef CollisionMarksInterface                      Self;
+      typedef _TTraits TTraits;
+      fpaTraitsMacro( typename TTraits );
+
+      // Minigraph to represent collisions
+      typedef std::pair< TVertex, bool >    TCollision;
+      typedef std::vector< TCollision >     TCollisionsRow;
+      typedef std::vector< TCollisionsRow > TCollisions;
+
+    public:
+      bool StopAtOneFront( ) const;
+      void StopAtOneFrontOn( );
+      void StopAtOneFrontOff( );
+      void SetStopAtOneFront( bool v );
+
+    protected:
+      CollisionMarksInterface( itk::ProcessObject* f );
+      virtual ~CollisionMarksInterface( );
+
+      virtual bool _Collisions( const TVertex& a, const TVertex& b ) override;
+      virtual void _InitCollisions( unsigned long nSeeds ) override;
+
+    protected:
+      bool         m_StopAtOneFront;
+      TCollisions  m_Collisions;
+      unsigned int m_NumberOfFronts;
+      unsigned int m_NumberOfSeeds;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/CollisionMarksInterface.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+#endif // __fpa__Filters__CollisionMarksInterface__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/CollisionMarksInterface.hxx b/lib/fpa/Filters/CollisionMarksInterface.hxx
new file mode 100644 (file)
index 0000000..ace11e5
--- /dev/null
@@ -0,0 +1,131 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__CollisionMarksInterface__hxx__
+#define __fpa__Filters__CollisionMarksInterface__hxx__
+
+#include <queue>
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+bool fpa::Filters::CollisionMarksInterface< _TTraits >::
+StopAtOneFront( ) const
+{
+  return( this->m_StopAtOneFront );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::CollisionMarksInterface< _TTraits >::
+StopAtOneFrontOn( )
+{
+  this->SetStopAtOneFront( true );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::CollisionMarksInterface< _TTraits >::
+StopAtOneFrontOff( )
+{
+  this->SetStopAtOneFront( false );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::CollisionMarksInterface< _TTraits >::
+SetStopAtOneFront( bool v )
+{
+  if( this->m_StopAtOneFront != v )
+  {
+    this->m_StopAtOneFront = v;
+    if( this->m_Filter.IsNotNull(  ) )
+      this->m_Filter->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+fpa::Filters::CollisionMarksInterface< _TTraits >::
+CollisionMarksInterface( itk::ProcessObject* f )
+  : Superclass( f ),
+    m_StopAtOneFront( false ),
+    m_NumberOfFronts( 0 ),
+    m_NumberOfSeeds( 0 )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+fpa::Filters::CollisionMarksInterface< _TTraits >::
+~CollisionMarksInterface( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+bool fpa::Filters::CollisionMarksInterface< _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
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::CollisionMarksInterface< _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 );
+}
+
+#endif // __fpa__Filters__CollisionMarksInterface__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Dijkstra.h b/lib/fpa/Filters/Dijkstra.h
new file mode 100644 (file)
index 0000000..37cb17e
--- /dev/null
@@ -0,0 +1,60 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Dijkstra__h__
+#define __fpa__Filters__Dijkstra__h__
+
+#include <fpa/Filters/RandomWalker.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    /**
+     */
+    template< class _TDataInterface, class _TMST >
+    class Dijkstra
+      : public fpa::Filters::RandomWalker< _TDataInterface >
+    {
+    public:
+      typedef _TDataInterface TDataInterface;
+      typedef _TMST TMST;
+      typedef fpa::Filters::RandomWalker< TDataInterface > Superclass;
+      typedef Dijkstra                                     Self;
+      typedef itk::SmartPointer< Self >                    Pointer;
+      typedef itk::SmartPointer< const Self >              ConstPointer;
+
+      typedef typename Superclass::TTraits TTraits;
+      fpaTraitsMacro( typename TTraits );
+      typedef typename Superclass::TCost  TCost;
+      typedef typename Superclass::TLabel TLabel;
+
+      typedef typename Superclass::TScalarWeight TScalarWeight;
+      typedef typename Superclass::TVertexWeight TVertexWeight;
+
+    public:
+      itkTypeMacro( fpa::Filters::Dijkstra, fpa::Filters::RandomWalker );
+
+      fpaFilterOutputMacro( MinimumSpanningTree, TMST );
+
+    protected:
+      Dijkstra( );
+      virtual ~Dijkstra( );
+
+      virtual void _PostComputeOutputValue( TNode& n ) override;
+
+    private:
+      Dijkstra( const Self& other );
+      Self& operator=( const Self& other );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/Dijkstra.hxx>
+#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 (file)
index 0000000..38ed116
--- /dev/null
@@ -0,0 +1,33 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Dijkstra__hxx__
+#define __fpa__Filters__Dijkstra__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface, class _TMST >
+fpa::Filters::Dijkstra< _TDataInterface, _TMST >::
+Dijkstra( )
+{
+  fpaFilterOutputConfigureMacro( MinimumSpanningTree, TMST );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface, class _TMST >
+fpa::Filters::Dijkstra< _TDataInterface, _TMST >::
+~Dijkstra( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface, class _TMST >
+void fpa::Filters::Dijkstra< _TDataInterface, _TMST >::
+_PostComputeOutputValue( TNode& n )
+{
+  this->Superclass::_PostComputeOutputValue( n );
+  this->GetMinimumSpanningTree( )->SetParent( n.Vertex, n.Parent );
+}
+
+#endif // __fpa__Filters__Dijkstra__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Event.h b/lib/fpa/Filters/Event.h
new file mode 100644 (file)
index 0000000..ee81d7c
--- /dev/null
@@ -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 <itkEventObject.h>
+
+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 <fpa/Filters/Event.hxx>
+#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 (file)
index 0000000..105c603
--- /dev/null
@@ -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/DefaultTraits.h b/lib/fpa/Filters/Image/DefaultTraits.h
new file mode 100644 (file)
index 0000000..27aaa3a
--- /dev/null
@@ -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 <set>
+#include <vector>
+#include <itkImage.h>
+#include <itkImageToImageFilter.h>
+#include <fpa/Filters/CollisionMarksInterface.h>
+#include <fpa/Filters/MultipleSeedsInterface.h>
+
+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 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;
+
+          struct TSeed
+          {
+            TVertex Vertex;
+            TPoint  Point;
+            bool    IsPoint;
+            TMark   FrontId;
+            TSeed( const TMark& fid = 0 )
+              : FrontId( fid )
+              { }
+          };
+          typedef std::vector< TSeed > TSeeds;
+        };
+        itkStaticConstMacro(
+          Dimension, unsigned int, TInternalTraits::Dimension
+          );
+
+        typedef itk::Image< _TMark, TInternalTraits::Dimension >         TMarksImage;
+        typedef itk::ImageToImageFilter< TInputImage, TOutputImage >     TFilterInterface;
+        typedef fpa::Filters::CollisionMarksInterface< TInternalTraits > TMarksInterface;
+        typedef fpa::Filters::MultipleSeedsInterface< TInternalTraits >  TSeedsInterface;
+      };
+
+    } // 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 (file)
index 0000000..c4d3497
--- /dev/null
@@ -0,0 +1,59 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__Dijkstra__h__
+#define __fpa__Filters__Image__Dijkstra__h__
+
+#include <fpa/Filters/Dijkstra.h>
+#include <fpa/Filters/Image/DefaultTraits.h>
+#include <fpa/Filters/Image/Interface.h>
+#include <fpa/DataStructures/Image/MinimumSpanningTree.h>
+
+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 Dijkstra
+        : public fpa::Filters::Dijkstra< fpa::Filters::Image::Interface< _TTraits >, fpa::DataStructures::Image::MinimumSpanningTree< _TTraits::Dimension > >
+      {
+      public:
+        typedef _TTraits TTraits;
+        typedef fpa::DataStructures::Image::MinimumSpanningTree< _TTraits::Dimension > TMST;
+
+        typedef fpa::Filters::Image::Interface< TTraits >  TInterface;
+        typedef fpa::Filters::Dijkstra< TInterface, TMST > Superclass;
+        typedef Dijkstra                                   Self;
+        typedef itk::SmartPointer< Self >                  Pointer;
+        typedef itk::SmartPointer< const Self >            ConstPointer;
+
+      public:
+        itkNewMacro( Self );
+
+      protected:
+        Dijkstra( );
+        virtual ~Dijkstra( );
+
+        virtual void _ConfigureOutputs( ) override;
+
+      private:
+        Dijkstra( const Self& other );
+        Self& operator=( const Self& other );
+      };
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/Image/Dijkstra.hxx>
+#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 (file)
index 0000000..955443b
--- /dev/null
@@ -0,0 +1,50 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__Dijkstra__hxx__
+#define __fpa__Filters__Image__Dijkstra__hxx__
+
+#include <fpa/Functors/Dijkstra/Image/Identity.h>
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMark, class _TTraits >
+fpa::Filters::Image::Dijkstra< _TInputImage, _TOutputImage, _TMark, _TTraits >::
+Dijkstra( )
+  : Superclass( )
+{
+  this->SetWeightFunction(
+    fpa::Functors::Dijkstra::Image::Identity< _TInputImage, typename _TOutputImage::PixelType >::New( )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMark, class _TTraits >
+fpa::Filters::Image::Dijkstra< _TInputImage, _TOutputImage, _TMark, _TTraits >::
+~Dijkstra( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage, class _TMark, class _TTraits >
+void fpa::Filters::Image::Dijkstra< _TInputImage, _TOutputImage, _TMark, _TTraits >::
+_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 _TInputImage::IndexType::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 (file)
index 0000000..cced4a3
--- /dev/null
@@ -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 <itkProcessObject.h>
+#include <itkImageToImageFilter.h>
+#include <fpa/DataStructures/Image/Path.h>
+#include <fpa/Filters/Image/Dijkstra.h>
+
+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::Path< 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 <fpa/Filters/Image/ExtractAxis.hxx>
+#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 (file)
index 0000000..5277ccd
--- /dev/null
@@ -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 <itkSignedMaurerDistanceMapImageFilter.h>
+#include <fpa/Functors/Dijkstra/Invert.h>
+
+// -------------------------------------------------------------------------
+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( )->GetPath(
+    out, this->m_StartIndex, this->m_EndIndex
+    );
+}
+
+#endif // __fpa__Filters__Image__ExtractAxis__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Image/ExtractSkeleton.h b/lib/fpa/Filters/Image/ExtractSkeleton.h
new file mode 100644 (file)
index 0000000..5f4e9b8
--- /dev/null
@@ -0,0 +1,153 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__ExtractSkeleton__h__
+#define __fpa__Filters__Image__ExtractSkeleton__h__
+
+#include <map>
+#include <itkProcessObject.h>
+#include <itkSignedMaurerDistanceMapImageFilter.h>
+#include <fpa/Filters/Image/Dijkstra.h>
+#include <fpa/DataStructures/Image/Skeleton.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    namespace Image
+    {
+      /**
+       */
+      template< class _TInputImage, class _TDistanceMap = itk::SignedMaurerDistanceMapImageFilter< _TInputImage, itk::Image< double, _TInputImage::ImageDimension > > >
+      class ExtractSkeleton
+        : public itk::ProcessObject
+      {
+      public:
+        typedef ExtractSkeleton                 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 _PostComputeOutputValue( 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::ExtractSkeleton, 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:
+        ExtractSkeleton( );
+        virtual ~ExtractSkeleton( );
+
+        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.
+        ExtractSkeleton( 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 <fpa/Filters/Image/ExtractSkeleton.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __fpa__Filters__Image__ExtractSkeleton__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Image/ExtractSkeleton.hxx b/lib/fpa/Filters/Image/ExtractSkeleton.hxx
new file mode 100644 (file)
index 0000000..38b3df4
--- /dev/null
@@ -0,0 +1,353 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__ExtractSkeleton__hxx__
+#define __fpa__Filters__Image__ExtractSkeleton__hxx__
+
+#include <itkImage.h>
+#include <itkImageRegionIteratorWithIndex.h>
+#include <itkMinimumMaximumImageCalculator.h>
+#include <fpa/Functors/Dijkstra/Invert.h>
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+fpa::Filters::Image::ExtractSkeleton< _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::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+_TDijkstra::~_TDijkstra( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+void fpa::Filters::Image::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+_TDijkstra::_BeforeGenerateData( )
+{
+  this->Superclass::_BeforeGenerateData( );
+  this->m_SkeletonQueue.clear( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+void fpa::Filters::Image::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+_TDijkstra::_PostComputeOutputValue( TNode& n )
+{
+  typedef typename _TSkeletonQueue::value_type _TSkeletonQueueValue;
+
+  this->Superclass::_PostComputeOutputValue( 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::ExtractSkeleton< _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::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+SetInput( TInputImage* input )
+{
+  this->Superclass::SetNthInput( 0, input );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+typename fpa::Filters::Image::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+TInputImage* fpa::Filters::Image::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+GetInput( )
+{
+  return( dynamic_cast< TInputImage* >( this->Superclass::GetInput( 0 ) ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+const typename fpa::Filters::Image::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+TInputImage* fpa::Filters::Image::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+GetInput( ) const
+{
+  return(
+    dynamic_cast< const TInputImage* >( this->Superclass::GetInput( 0 ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+typename fpa::Filters::Image::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+TSkeleton* fpa::Filters::Image::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+GetOutput( )
+{
+  return( dynamic_cast< TSkeleton* >( this->Superclass::GetOutput( 0 ) ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+const typename fpa::Filters::Image::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+TSkeleton* fpa::Filters::Image::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+GetOutput( ) const
+{
+  return(
+    dynamic_cast< const TSkeleton* >( this->Superclass::GetOutput( 0 ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+fpa::Filters::Image::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+ExtractSkeleton( )
+  : 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::ExtractSkeleton< _TInputImage, _TDistanceMap >::
+~ExtractSkeleton( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TDistanceMap >
+void fpa::Filters::Image::ExtractSkeleton< _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->GetAxis( 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::ExtractSkeleton< _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::ExtractSkeleton< _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__ExtractSkeleton__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Image/Interface.h b/lib/fpa/Filters/Image/Interface.h
new file mode 100644 (file)
index 0000000..d0df734
--- /dev/null
@@ -0,0 +1,74 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__Interface__h__
+#define __fpa__Filters__Image__Interface__h__
+
+#include <fpa/Filters/Algorithm.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    namespace Image
+    {
+      /**
+       */
+      template< class _TTraits >
+      class Interface
+        : public fpa::Filters::Algorithm< _TTraits >
+      {
+      public:
+        typedef _TTraits TTraits;
+        typedef typename TTraits::TInputImage  TInputImage;
+        typedef typename TTraits::TOutputImage TOutputImage;
+        typedef typename TTraits::TMarksImage  TMarksImage;
+        fpaTraitsMacro( typename TTraits );
+
+        typedef fpa::Filters::Algorithm< _TTraits > Superclass;
+        typedef Interface                           Self;
+        typedef itk::SmartPointer< Self >           Pointer;
+        typedef itk::SmartPointer< const Self >     ConstPointer;
+
+      public:
+        fpaFilterOutputMacro( Marks, TMarksImage );
+
+        itkGetConstMacro( NeighborhoodOrder, unsigned int );
+        itkSetMacro( NeighborhoodOrder, unsigned int );
+
+      protected:
+        Interface( );
+        virtual ~Interface( );
+
+        // Filter related methods
+        virtual void _AssignOutputValue( const TNode& n ) override;
+        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;
+
+        // Marks related methods
+        virtual unsigned long _GetMark( const TVertex& v ) const override;
+        virtual bool _IsMarked( const TVertex& v ) const override;
+        virtual void _Mark( const TNode& n ) override;
+
+      private:
+        Interface( const Self& other );
+        Self& operator=( const Self& other );
+
+      protected:
+        unsigned int m_NeighborhoodOrder;
+      };
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/Image/Interface.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+#endif // __fpa__Filters__Image__Interface__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Image/Interface.hxx b/lib/fpa/Filters/Image/Interface.hxx
new file mode 100644 (file)
index 0000000..2ea6e03
--- /dev/null
@@ -0,0 +1,136 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__Interface__hxx__
+#define __fpa__Filters__Image__Interface__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+fpa::Filters::Image::Interface< _TTraits >::
+Interface( )
+  : Superclass( ),
+    m_NeighborhoodOrder( 1 )
+{
+  fpaFilterOutputConfigureMacro( Marks, TMarksImage );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+fpa::Filters::Image::Interface< _TTraits >::
+~Interface( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::Image::Interface< _TTraits >::
+_AssignOutputValue( const TNode& n )
+{
+  this->GetOutput( )->SetPixel( n.Vertex, n.Value );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::Image::Interface< _TTraits >::
+_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 _TTraits >
+typename fpa::Filters::Image::Interface< _TTraits >::
+TInputValue fpa::Filters::Image::Interface< _TTraits >::
+_GetInputValue( const TVertex& v ) const
+{
+  return( this->GetInput( )->GetPixel( v ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+typename fpa::Filters::Image::Interface< _TTraits >::
+TOutputValue fpa::Filters::Image::Interface< _TTraits >::
+_GetOutputValue( const TVertex& v ) const
+{
+  return( this->GetOutput( )->GetPixel( v ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+typename fpa::Filters::Image::Interface< _TTraits >::
+TNeighborhood fpa::Filters::Image::Interface< _TTraits >::
+_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 < TTraits::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 _TTraits >
+unsigned long fpa::Filters::Image::Interface< _TTraits >::
+_GetMark( const TVertex& v ) const
+{
+  return( this->GetMarks( )->GetPixel( v ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+bool fpa::Filters::Image::Interface< _TTraits >::
+_IsMarked( const TVertex& v ) const
+{
+  return( this->GetMarks( )->GetPixel( v ) != TMark( 0 ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::Image::Interface< _TTraits >::
+_Mark( const TNode& n )
+{
+  this->GetMarks( )->SetPixel( n.Vertex, TMark( n.FrontId ) );
+}
+
+#endif // __fpa__Filters__Image__Interface__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Image/Mori.h b/lib/fpa/Filters/Image/Mori.h
new file mode 100644 (file)
index 0000000..3c1cf2a
--- /dev/null
@@ -0,0 +1,58 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__Mori__h__
+#define __fpa__Filters__Image__Mori__h__
+
+#include <fpa/Filters/Mori.h>
+#include <fpa/Filters/Image/MoriTraits.h>
+#include <fpa/Filters/Image/Interface.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    namespace Image
+    {
+      /**
+       */
+      template< class _TInputImage, class _TOutputImage >
+      class Mori
+        : public fpa::Filters::Mori< fpa::Filters::Image::Interface< fpa::Filters::Image::MoriTraits< _TInputImage, _TOutputImage > > >
+      {
+      public:
+        typedef fpa::Filters::Image::MoriTraits< _TInputImage, _TOutputImage > TTraits;
+
+        typedef fpa::Filters::Image::Interface< TTraits > TInterface;
+        typedef fpa::Filters::Mori< TInterface >          Superclass;
+        typedef Mori                                      Self;
+        typedef itk::SmartPointer< Self >                 Pointer;
+        typedef itk::SmartPointer< const Self >           ConstPointer;
+
+      public:
+        itkNewMacro( Self );
+
+      protected:
+        Mori( );
+        virtual ~Mori( );
+
+        // Pipeline related methods
+        virtual void _AfterGenerateData( );
+
+      private:
+        Mori( const Self& other );
+        Self& operator=( const Self& other );
+      };
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/Image/Mori.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+#endif // __fpa__Filters__Image__Mori__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Image/Mori.hxx b/lib/fpa/Filters/Image/Mori.hxx
new file mode 100644 (file)
index 0000000..af9d967
--- /dev/null
@@ -0,0 +1,46 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__Mori__hxx__
+#define __fpa__Filters__Image__Mori__hxx__
+
+#include <itkBinaryThresholdImageFilter.h>
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage >
+fpa::Filters::Image::Mori< _TInputImage, _TOutputImage >::
+Mori( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage >
+fpa::Filters::Image::Mori< _TInputImage, _TOutputImage >::
+~Mori( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TOutputImage >
+void fpa::Filters::Image::Mori< _TInputImage, _TOutputImage >::
+_AfterGenerateData( )
+{
+  this->Superclass::_AfterGenerateData( );
+
+  // Extract correct mark
+  typedef typename Superclass::TMarksImage _TMarks;
+  typedef itk::BinaryThresholdImageFilter< _TMarks, _TOutputImage > _TFilter;
+  typename _TFilter::Pointer filter = _TFilter::New( );
+  filter->SetInput( this->GetMarks( ) );
+  filter->SetLowerThreshold( 1 );
+  filter->SetUpperThreshold( this->m_PeakDetector.GetNumberOfSamples( ) - 2 );
+  filter->SetInsideValue( this->GetInsideValue( ) );
+  filter->SetOutsideValue( this->GetOutsideValue( ) );
+  filter->Update( );
+  this->GraftOutput( filter->GetOutput( ) );
+}
+
+#endif // __fpa__Filters__Image__Mori__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Image/MoriTraits.h b/lib/fpa/Filters/Image/MoriTraits.h
new file mode 100644 (file)
index 0000000..2b23f12
--- /dev/null
@@ -0,0 +1,44 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__MoriTraits__h__
+#define __fpa__Filters__Image__MoriTraits__h__
+
+#include <fpa/Filters/BaseMarksInterface.h>
+#include <fpa/Filters/SingleSeedInterface.h>
+#include <fpa/Filters/Image/DefaultTraits.h>
+
+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::TMarksImage      TMarksImage;
+        typedef typename Superclass::TFilterInterface TFilterInterface;
+
+        typedef fpa::Filters::BaseMarksInterface< TInternalTraits >  TMarksInterface;
+        typedef fpa::Filters::SingleSeedInterface< TInternalTraits > TSeedsInterface;
+      };
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Filters__Image__MoriTraits__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Image/RandomWalker.h b/lib/fpa/Filters/Image/RandomWalker.h
new file mode 100644 (file)
index 0000000..32b84ac
--- /dev/null
@@ -0,0 +1,77 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__RandomWalker__h__
+#define __fpa__Filters__Image__RandomWalker__h__
+
+#include <fpa/Filters/RandomWalker.h>
+#include <fpa/Filters/Image/Interface.h>
+#include <fpa/Filters/Image/RandomWalkerTraits.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    namespace Image
+    {
+      /**
+       */
+      template< class _TInputImage, class _TLabelImage, class _TCost = float, class _TTraits = fpa::Filters::Image::RandomWalkerTraits< _TInputImage, _TLabelImage, _TCost > >
+      class RandomWalker
+        : public fpa::Filters::RandomWalker< fpa::Filters::Image::Interface< _TTraits > >
+      {
+      public:
+        typedef _TTraits TTraits;
+        typedef typename TTraits::TInputImage TInputImage;
+        typedef typename TTraits::TLabelImage TLabelImage;
+        typedef typename TTraits::TCost TCost;
+        typedef typename TTraits::TLabel TLabel;
+        typedef typename TTraits::TOutputImage TOutputImage;
+        typedef TOutputImage TCostsImage;
+
+        typedef fpa::Filters::Image::Interface< TTraits > TInterface;
+        typedef fpa::Filters::RandomWalker< TInterface >  Superclass;
+        typedef RandomWalker                              Self;
+        typedef itk::SmartPointer< Self >                 Pointer;
+        typedef itk::SmartPointer< const Self >           ConstPointer;
+
+      public:
+        itkNewMacro( Self );
+
+        fpaFilterInputMacro( InputLabels, _TLabelImage );
+
+      public:
+        TInputImage* GetInputImage( );
+        const TInputImage* GetInputImage( ) const;
+        void SetInputImage( TInputImage* i );
+
+        TCostsImage* GetOutputCosts( );
+        const TCostsImage* GetOutputCosts( ) const;
+
+        TLabelImage* GetOutputLabels( );
+        const TLabelImage* GetOutputLabels( ) const;
+
+      protected:
+        RandomWalker( );
+        virtual ~RandomWalker( );
+
+        // Filter related methods
+        virtual const itk::DataObject* _GetReferenceInput( ) const override;
+
+      private:
+        RandomWalker( const Self& other );
+        Self& operator=( const Self& other );
+      };
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/Image/RandomWalker.hxx>
+#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 (file)
index 0000000..0756229
--- /dev/null
@@ -0,0 +1,109 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__RandomWalker__hxx__
+#define __fpa__Filters__Image__RandomWalker__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TCost, class _TTraits >
+typename
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+TInputImage*
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+GetInputImage( )
+{
+  return( this->GetInput( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TCost, class _TTraits >
+const typename
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+TInputImage*
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+GetInputImage( ) const
+{
+  return( this->GetInput( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TCost, class _TTraits >
+void
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+SetInputImage( TInputImage* i )
+{
+  this->SetInput( i );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TCost, class _TTraits >
+typename
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+TCostsImage* 
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+GetOutputCosts( )
+{
+  return( this->GetOutput( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TCost, class _TTraits >
+const typename
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+TCostsImage*
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+GetOutputCosts( ) const
+{
+  return( this->GetOutput( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TCost, class _TTraits >
+typename
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+TLabelImage*
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+GetOutputLabels( )
+{
+  return( this->GetMarks( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TCost, class _TTraits >
+const typename
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+TLabelImage*
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+GetOutputLabels( ) const
+{
+  return( this->GetMarks( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TCost, class _TTraits >
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+RandomWalker( )
+  : Superclass( )
+{
+  fpaFilterInputConfigureMacro( InputLabels, _TLabelImage );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TCost, class _TTraits >
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+~RandomWalker( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInputImage, class _TLabelImage, class _TCost, class _TTraits >
+const itk::DataObject*
+fpa::Filters::Image::RandomWalker< _TInputImage, _TLabelImage, _TCost, _TTraits >::
+_GetReferenceInput( ) const
+{
+  return( this->GetInputLabels( ) );
+}
+
+#endif // __fpa__Filters__Image__RandomWalker__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Image/RandomWalkerTraits.h b/lib/fpa/Filters/Image/RandomWalkerTraits.h
new file mode 100644 (file)
index 0000000..f95f590
--- /dev/null
@@ -0,0 +1,48 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__RandomWalkerTraits__h__
+#define __fpa__Filters__Image__RandomWalkerTraits__h__
+
+#include <itkImage.h>
+#include <fpa/Filters/BaseMarksInterface.h>
+#include <fpa/Filters/Image/SeedsFromLabelsInterface.h>
+#include <fpa/Filters/Image/DefaultTraits.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    namespace Image
+    {
+      /**
+       */
+      template< class _TInputImage, class _TLabelImage, class _TCost >
+      class RandomWalkerTraits
+        : public fpa::Filters::Image::DefaultTraits< _TInputImage, itk::Image< _TCost, _TInputImage::ImageDimension >, typename _TLabelImage::PixelType >
+      {
+      public:
+        typedef _TInputImage TInputImage;
+        typedef _TLabelImage TLabelImage;
+        typedef _TCost       TCost;
+        typedef typename TLabelImage::PixelType TLabel;
+        typedef itk::Image< TCost, _TInputImage::ImageDimension > TOutputImage;
+        typedef fpa::Filters::Image::DefaultTraits< TInputImage, TOutputImage, TLabel > Superclass;
+
+        typedef typename Superclass::TInternalTraits  TInternalTraits;
+        typedef typename Superclass::TMarksImage      TMarksImage;
+        typedef typename Superclass::TFilterInterface TFilterInterface;
+
+        typedef fpa::Filters::BaseMarksInterface< TInternalTraits >  TMarksInterface;
+        typedef fpa::Filters::Image::SeedsFromLabelsInterface< TInternalTraits > TSeedsInterface;
+      };
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Filters__Image__RandomWalkerTraits__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Image/RegionGrow.h b/lib/fpa/Filters/Image/RegionGrow.h
new file mode 100644 (file)
index 0000000..0d3a6b4
--- /dev/null
@@ -0,0 +1,57 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__RegionGrow__h__
+#define __fpa__Filters__Image__RegionGrow__h__
+
+#include <fpa/Filters/RegionGrow.h>
+#include <fpa/Filters/Image/DefaultTraits.h>
+#include <fpa/Filters/Image/Interface.h>
+
+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::RegionGrow< fpa::Filters::Image::Interface< _TTraits > >
+      {
+      public:
+        typedef _TTraits TTraits;
+
+        typedef fpa::Filters::Image::Interface< TTraits > TInterface;
+        typedef fpa::Filters::RegionGrow< TInterface >    Superclass;
+        typedef RegionGrow                                Self;
+        typedef itk::SmartPointer< Self >                 Pointer;
+        typedef itk::SmartPointer< const Self >           ConstPointer;
+
+      public:
+        itkNewMacro( Self );
+
+      protected:
+        RegionGrow( )
+          : Superclass( )
+          {
+          }
+        virtual ~RegionGrow( )
+          {
+          }
+
+      private:
+        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/SeedsFromLabelsInterface.h b/lib/fpa/Filters/Image/SeedsFromLabelsInterface.h
new file mode 100644 (file)
index 0000000..f9833fe
--- /dev/null
@@ -0,0 +1,52 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__SeedsFromLabelsInterface__h__
+#define __fpa__Filters__Image__SeedsFromLabelsInterface__h__
+
+#include <fpa/Filters/BaseSeedsInterface.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    namespace Image
+    {
+      /**
+       */
+      template< class _TTraits >
+      class SeedsFromLabelsInterface
+        : public fpa::Filters::BaseSeedsInterface< _TTraits >
+      {
+      public:
+        typedef fpa::Filters::BaseSeedsInterface< _TTraits > Superclass;
+        typedef SeedsFromLabelsInterface                       Self;
+        typedef _TTraits TTraits;
+        fpaTraitsMacro( typename TTraits );
+
+      protected:
+        SeedsFromLabelsInterface( itk::ProcessObject* f );
+        virtual ~SeedsFromLabelsInterface( );
+
+        // Filter related methods
+        virtual void _AssignOutputValue( const TNode& n ) = 0;
+
+        // Marks related methods
+        virtual void _Mark( const TNode& n ) = 0;
+
+        // Main method
+        virtual void _PrepareSeeds( const itk::DataObject* reference ) override;
+      };
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/Image/SeedsFromLabelsInterface.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+#endif // __fpa__Filters__Image__SeedsFromLabelsInterface__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Image/SeedsFromLabelsInterface.hxx b/lib/fpa/Filters/Image/SeedsFromLabelsInterface.hxx
new file mode 100644 (file)
index 0000000..8f58ba4
--- /dev/null
@@ -0,0 +1,84 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Image__SeedsFromLabelsInterface__hxx__
+#define __fpa__Filters__Image__SeedsFromLabelsInterface__hxx__
+
+#include <itkImage.h>
+#include <itkImageRegionConstIteratorWithIndex.h>
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+fpa::Filters::Image::SeedsFromLabelsInterface< _TTraits >::
+SeedsFromLabelsInterface( itk::ProcessObject* f )
+  : Superclass( f )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+fpa::Filters::Image::SeedsFromLabelsInterface< _TTraits >::
+~SeedsFromLabelsInterface( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::Image::SeedsFromLabelsInterface< _TTraits >::
+_PrepareSeeds( const itk::DataObject* reference )
+{
+  // Input object is a labelled image?
+  typedef typename _TTraits::TMark _TMark;
+  typedef itk::Image< _TMark, _TTraits::Dimension > _TLabelImage;
+  const _TLabelImage* labels =
+    dynamic_cast< const _TLabelImage* >( reference );
+  if( labels != NULL )
+  {
+    this->m_UnifiedSeeds.clear( );
+
+    // Iterate over labels
+    typedef itk::ImageRegionConstIteratorWithIndex< _TLabelImage > _TIt;
+    typename _TLabelImage::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 < _TTraits::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->_AssignOutputValue( node );
+          this->_Mark( node );
+        }
+        else
+          this->m_UnifiedSeeds.insert( node );
+
+      } // fi
+
+    } // rof
+
+  } // fi
+}
+
+#endif // __fpa__Filters__Image__SeedsFromLabelsInterface__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/Mori.h b/lib/fpa/Filters/Mori.h
new file mode 100644 (file)
index 0000000..14e8c53
--- /dev/null
@@ -0,0 +1,110 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Mori__h__
+#define __fpa__Filters__Mori__h__
+
+#include <fpa/Config.h>
+#include <fpa/Common/PeakDetector.h>
+#include <fpa/Filters/QueueAlgorithm.h>
+#include <fpa/Functors/RegionGrow/BinaryThreshold.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    /**
+     */
+    template< class _TDataInterface >
+    class Mori
+      : public fpa::Filters::QueueAlgorithm< _TDataInterface >
+    {
+    public:
+      typedef _TDataInterface TDataInterface;
+      typedef fpa::Filters::QueueAlgorithm< TDataInterface > Superclass;
+      typedef Mori                                           Self;
+      typedef itk::SmartPointer< Self >                      Pointer;
+      typedef itk::SmartPointer< const Self >                ConstPointer;
+
+      typedef typename TDataInterface::TTraits TTraits;
+      fpaTraitsMacro( typename TTraits );
+
+      typedef std::set< TInputValue >   TThresholds;
+      typedef fpa::Common::PeakDetector TPeakDetector;
+      typedef TPeakDetector::TPeak      TPeak;
+      typedef fpa::Functors::RegionGrow::BinaryThreshold< TInputValue > TPredicate;
+
+    public:
+      itkTypeMacro( fpa::Filters::Mori, fpa::Filters::QueueAlgorithm );
+
+      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( );
+
+      // Pipeline related methods
+      virtual void _BeforeGenerateData( ) override;
+
+      // Algoritm related methods
+      virtual void _PostComputeOutputValue( TNode& n ) override;
+      virtual void _PreComputeOutputValue( TNode& n ) override;
+      virtual void _Reinitialize( ) override;
+
+    private:
+      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;
+      double m_CurrCount;
+
+      TPeakDetector m_PeakDetector;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/Mori.hxx>
+#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 (file)
index 0000000..68048f1
--- /dev/null
@@ -0,0 +1,265 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__Mori__hxx__
+#define __fpa__Filters__Mori__hxx__
+
+#include <limits>
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+typename fpa::Filters::Mori< _TDataInterface >::
+TOutputValue fpa::Filters::Mori< _TDataInterface >::
+GetOutsideValue( ) const
+{
+  return( this->GetInitValue( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+SetOutsideValue( const TOutputValue& v )
+{
+  this->SetInitValue( v );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+unsigned long fpa::Filters::Mori< _TDataInterface >::
+GetSignalKernelSize( ) const
+{
+  return( this->m_PeakDetector.GetKernelSize( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+SetSignalKernelSize( unsigned long k )
+{
+  this->m_PeakDetector.SetKernelSize( k );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+double fpa::Filters::Mori< _TDataInterface >::
+GetSignalThreshold( ) const
+{
+  return( this->m_PeakDetector.GetThreshold( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+SetSignalThreshold( double t )
+{
+  this->m_PeakDetector.SetThreshold( t );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+double fpa::Filters::Mori< _TDataInterface >::
+GetSignalInfluence( ) const
+{
+  return( this->m_PeakDetector.GetInfluence( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+SetSignalInfluence( double i )
+{
+  this->m_PeakDetector.SetInfluence( i );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+ClearThresholds( )
+{
+  this->m_Thresholds.clear( );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+AddThreshold( const TInputValue& thr )
+{
+  if( this->m_Thresholds.insert( thr ).second )
+    this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+SetThresholds(
+  const TInputValue& lower,
+  const TInputValue& upper,
+  const TInputValue& delta
+  )
+{
+  for( TInputValue t = lower; t <= upper; t += delta )
+    this->AddThreshold( t );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+const typename fpa::Filters::Mori< _TDataInterface >::
+TThresholds& fpa::Filters::Mori< _TDataInterface >::
+GetThresholds( ) const
+{
+  return( this->m_Thresholds );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+unsigned long fpa::Filters::Mori< _TDataInterface >::
+GetNumberOfEvaluatedThresholds( ) const
+{
+  return( this->m_PeakDetector.GetNumberOfSamples( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+typename fpa::Filters::Mori< _TDataInterface >::
+TInputValue fpa::Filters::Mori< _TDataInterface >::
+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 _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+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 _TDataInterface >
+fpa::Filters::Mori< _TDataInterface >::
+Mori( )
+  : Superclass( true )
+{
+  this->SetOutsideValue( TOutputValue( 0 ) );
+  this->m_InsideValue = std::numeric_limits< TOutputValue >::max( );
+  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 _TDataInterface >
+fpa::Filters::Mori< _TDataInterface >::
+~Mori( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+_BeforeGenerateData( )
+{
+  this->Superclass::_BeforeGenerateData( );
+
+  // Prepare queues
+  this->_QueueClear( );
+
+  // 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 _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+_PostComputeOutputValue( 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->_QueueSwap( );
+    this->_QueuePush( n );
+    this->_QueueSwap( );
+    n.FrontId = 0;
+  }
+  else
+  {
+    n.Value = this->m_InsideValue;
+    this->m_CurrCount += double( 1 );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+_PreComputeOutputValue( TNode& n )
+{
+  // Nothing to do with this algorithm
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::Mori< _TDataInterface >::
+_Reinitialize( )
+{
+  if( this->_QueueSize( ) == 0 )
+  {
+    // Update peak detector
+    TPeak p = this->m_PeakDetector.AddValue(
+      *this->m_CurrThr, this->m_CurrCount
+      );
+    this->m_CurrThr++;
+    this->_QueueSwap( );
+    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
+}
+
+#endif // __fpa__Filters__Mori__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/MultipleSeedsInterface.h b/lib/fpa/Filters/MultipleSeedsInterface.h
new file mode 100644 (file)
index 0000000..9a26e2b
--- /dev/null
@@ -0,0 +1,50 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__MultipleSeedsInterface__h__
+#define __fpa__Filters__MultipleSeedsInterface__h__
+
+#include <fpa/Filters/BaseSeedsInterface.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    /**
+     */
+    template< class _TTraits >
+    class MultipleSeedsInterface
+      : public fpa::Filters::BaseSeedsInterface< _TTraits >
+    {
+    public:
+      typedef fpa::Filters::BaseSeedsInterface< _TTraits > Superclass;
+      typedef MultipleSeedsInterface                       Self;
+      typedef _TTraits TTraits;
+      fpaTraitsMacro( typename TTraits );
+
+    public:
+      void AddSeed( const TPoint& s );
+      void AddSeed( const TVertex& s );
+      void ClearSeeds( );
+      unsigned long GetNumberOfSeeds( ) const;
+
+    protected:
+      MultipleSeedsInterface( itk::ProcessObject* f );
+      virtual ~MultipleSeedsInterface( );
+
+      virtual void _PrepareSeeds( const itk::DataObject* reference ) override;
+
+    protected:
+      TSeeds m_InputSeeds;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/MultipleSeedsInterface.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+#endif // __fpa__Filters__MultipleSeedsInterface__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/MultipleSeedsInterface.hxx b/lib/fpa/Filters/MultipleSeedsInterface.hxx
new file mode 100644 (file)
index 0000000..3803113
--- /dev/null
@@ -0,0 +1,98 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__MultipleSeedsInterface__hxx__
+#define __fpa__Filters__MultipleSeedsInterface__hxx__
+
+#include <itkImageBase.h>
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::MultipleSeedsInterface< _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::MultipleSeedsInterface< _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::MultipleSeedsInterface< _TTraits >::
+ClearSeeds( )
+{
+  this->m_InputSeeds.clear( );
+  this->m_UnifiedSeeds.clear( );
+  if( this->m_Filter.IsNotNull( ) )
+    this->m_Filter->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+unsigned long fpa::Filters::MultipleSeedsInterface< _TTraits >::
+GetNumberOfSeeds( ) const
+{
+  return( this->m_InputSeeds.size( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+fpa::Filters::MultipleSeedsInterface< _TTraits >::
+MultipleSeedsInterface( itk::ProcessObject* f )
+  : Superclass( f )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+fpa::Filters::MultipleSeedsInterface< _TTraits >::
+~MultipleSeedsInterface( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::MultipleSeedsInterface< _TTraits >::
+_PrepareSeeds( const itk::DataObject* reference )
+{
+  // Input object is an image?
+  typedef itk::ImageBase< TTraits::Dimension > _TImageBase;
+  const _TImageBase* image =
+    dynamic_cast< const _TImageBase* >( reference );
+  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__MultipleSeedsInterface__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/PriorityQueueAlgorithm.h b/lib/fpa/Filters/PriorityQueueAlgorithm.h
new file mode 100644 (file)
index 0000000..780e4d2
--- /dev/null
@@ -0,0 +1,71 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__PriorityQueueAlgorithm__h__
+#define __fpa__Filters__PriorityQueueAlgorithm__h__
+
+#include <vector>
+#include <fpa/Config.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    /**
+     */
+    template< class _TDataInterface >
+    class PriorityQueueAlgorithm
+      : public _TDataInterface
+    {
+    public:
+      typedef _TDataInterface                 Superclass;
+      typedef PriorityQueueAlgorithm                  Self;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename Superclass::TTraits TTraits;
+      fpaTraitsMacro( typename TTraits );
+
+      typedef std::vector< TNode > TQueue;
+      struct TQueueOrder
+      {
+        bool operator()( const TNode& a, const TNode& b ) const
+          {
+            return( b.Value < a.Value );
+          }
+      };
+
+    public:
+      itkTypeMacro( fpa::Filters::PriorityQueueAlgorithm, TDataInterface );
+
+    protected:
+      PriorityQueueAlgorithm( bool double_buffer );
+      virtual ~PriorityQueueAlgorithm( );
+
+      virtual void _QueueSwap( );
+      virtual void _QueueClear( ) override;
+      virtual TNode _QueuePop( ) override;
+      virtual void _QueuePush( const TNode& n ) override;
+      virtual unsigned long _QueueSize( ) const override;
+
+    private:
+      PriorityQueueAlgorithm( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      TQueue       m_Queues[ 2 ];
+      TQueueOrder  m_QueueOrder;
+      unsigned int m_CurrQueue;
+      bool         m_DoubleBuffer;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/PriorityQueueAlgorithm.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+#endif // __fpa__Filters__PriorityQueueAlgorithm__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/PriorityQueueAlgorithm.hxx b/lib/fpa/Filters/PriorityQueueAlgorithm.hxx
new file mode 100644 (file)
index 0000000..2d7a0d3
--- /dev/null
@@ -0,0 +1,90 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__PriorityQueueAlgorithm__hxx__
+#define __fpa__Filters__PriorityQueueAlgorithm__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+fpa::Filters::PriorityQueueAlgorithm< _TDataInterface >::
+PriorityQueueAlgorithm( bool double_buffer )
+  : Superclass( ),
+    m_CurrQueue( 0 ),
+    m_DoubleBuffer( double_buffer )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+fpa::Filters::PriorityQueueAlgorithm< _TDataInterface >::
+~PriorityQueueAlgorithm( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::PriorityQueueAlgorithm< _TDataInterface >::
+_QueueSwap( )
+{
+  if( this->m_DoubleBuffer )
+    this->m_CurrQueue = ( this->m_CurrQueue + 1 ) % 2;
+  else
+    this->m_CurrQueue = 0;
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::PriorityQueueAlgorithm< _TDataInterface >::
+_QueueClear( )
+{
+  this->m_Queues[ 0 ].clear( );
+  this->m_Queues[ 1 ].clear( );
+  this->m_CurrQueue = 0;
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+typename fpa::Filters::PriorityQueueAlgorithm< _TDataInterface >::
+TNode fpa::Filters::PriorityQueueAlgorithm< _TDataInterface >::
+_QueuePop( )
+{
+  std::pop_heap(
+    this->m_Queues[ this->m_CurrQueue ].begin( ),
+    this->m_Queues[ this->m_CurrQueue ].end( ),
+    this->m_QueueOrder
+    );
+  TNode n = this->m_Queues[ this->m_CurrQueue ].back( );
+  this->m_Queues[ this->m_CurrQueue ].pop_back( );
+  return( n );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::PriorityQueueAlgorithm< _TDataInterface >::
+_QueuePush( const TNode& n )
+{
+  bool push_needed =  ( n.Parent == n.Vertex );
+  push_needed     |= !( n.Value < this->_GetOutputValue( n.Parent ) );
+  if( push_needed )
+  {
+    this->m_Queues[ this->m_CurrQueue ].push_back( n );
+    std::push_heap(
+      this->m_Queues[ this->m_CurrQueue ].begin( ),
+      this->m_Queues[ this->m_CurrQueue ].end( ),
+      this->m_QueueOrder
+      );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+unsigned long fpa::Filters::PriorityQueueAlgorithm< _TDataInterface >::
+_QueueSize( ) const
+{
+  return( this->m_Queues[ this->m_CurrQueue ].size( ) );
+}
+
+#endif // __fpa__Filters__PriorityQueueAlgorithm__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/QueueAlgorithm.h b/lib/fpa/Filters/QueueAlgorithm.h
new file mode 100644 (file)
index 0000000..ba3e458
--- /dev/null
@@ -0,0 +1,63 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__QueueAlgorithm__h__
+#define __fpa__Filters__QueueAlgorithm__h__
+
+#include <deque>
+#include <fpa/Config.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+      /**
+       */
+      template< class _TDataInterface >
+      class QueueAlgorithm
+        : public _TDataInterface
+      {
+      public:
+        typedef _TDataInterface                 Superclass;
+        typedef QueueAlgorithm                  Self;
+        typedef itk::SmartPointer< Self >       Pointer;
+        typedef itk::SmartPointer< const Self > ConstPointer;
+
+        typedef typename Superclass::TTraits TTraits;
+        fpaTraitsMacro( typename TTraits );
+
+        typedef std::deque< TNode > TQueue;
+
+      public:
+        itkTypeMacro( fpa::Filters::QueueAlgorithm, TDataInterface );
+
+      protected:
+        QueueAlgorithm( bool double_buffer );
+        virtual ~QueueAlgorithm( );
+
+        virtual void _QueueSwap( );
+        virtual void _QueueClear( ) override;
+        virtual TNode _QueuePop( ) override;
+        virtual void _QueuePush( const TNode& n ) override;
+        virtual unsigned long _QueueSize( ) const override;
+
+      private:
+        QueueAlgorithm( const Self& other );
+        Self& operator=( const Self& other );
+
+      protected:
+        TQueue       m_Queues[ 2 ];
+        unsigned int m_CurrQueue;
+        bool         m_DoubleBuffer;
+      };
+
+    } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/QueueAlgorithm.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+#endif // __fpa__Filters__QueueAlgorithm__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/QueueAlgorithm.hxx b/lib/fpa/Filters/QueueAlgorithm.hxx
new file mode 100644 (file)
index 0000000..aa51d5d
--- /dev/null
@@ -0,0 +1,74 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__QueueAlgorithm__hxx__
+#define __fpa__Filters__QueueAlgorithm__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+fpa::Filters::QueueAlgorithm< _TDataInterface >::
+QueueAlgorithm( bool double_buffer )
+  : Superclass( ),
+    m_CurrQueue( 0 ),
+    m_DoubleBuffer( double_buffer )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+fpa::Filters::QueueAlgorithm< _TDataInterface >::
+~QueueAlgorithm( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::QueueAlgorithm< _TDataInterface >::
+_QueueSwap( )
+{
+  if( this->m_DoubleBuffer )
+    this->m_CurrQueue = ( this->m_CurrQueue + 1 ) % 2;
+  else
+    this->m_CurrQueue = 0;
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::QueueAlgorithm< _TDataInterface >::
+_QueueClear( )
+{
+  this->m_Queues[ 0 ].clear( );
+  this->m_Queues[ 1 ].clear( );
+  this->m_CurrQueue = 0;
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+typename fpa::Filters::QueueAlgorithm< _TDataInterface >::
+TNode fpa::Filters::QueueAlgorithm< _TDataInterface >::
+_QueuePop( )
+{
+  TNode n = this->m_Queues[ this->m_CurrQueue ].front( );
+  this->m_Queues[ this->m_CurrQueue ].pop_front( );
+  return( n );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::QueueAlgorithm< _TDataInterface >::
+_QueuePush( const TNode& n )
+{
+  this->m_Queues[ this->m_CurrQueue ].push_back( n );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+unsigned long fpa::Filters::QueueAlgorithm< _TDataInterface >::
+_QueueSize( ) const
+{
+  return( this->m_Queues[ this->m_CurrQueue ].size( ) );
+}
+
+#endif // __fpa__Filters__QueueAlgorithm__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/RandomWalker.h b/lib/fpa/Filters/RandomWalker.h
new file mode 100644 (file)
index 0000000..5da8e7a
--- /dev/null
@@ -0,0 +1,77 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__RandomWalker__h__
+#define __fpa__Filters__RandomWalker__h__
+
+#include <itkFunctionBase.h>
+#include <fpa/Config.h>
+#include <fpa/Filters/PriorityQueueAlgorithm.h>
+#include <fpa/Functors/VertexFunction.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    /**
+     */
+    template< class _TDataInterface >
+    class RandomWalker
+      : public fpa::Filters::PriorityQueueAlgorithm< _TDataInterface >
+    {
+    public:
+      typedef _TDataInterface TDataInterface;
+      typedef fpa::Filters::PriorityQueueAlgorithm< TDataInterface > Superclass;
+      typedef RandomWalker                    Self;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename TDataInterface::TTraits TTraits;
+      fpaTraitsMacro( typename TTraits );
+      typedef TOutputValue TCost;
+      typedef TMark        TLabel;
+
+      typedef itk::FunctionBase< TCost, TCost >               TScalarWeight;
+      typedef fpa::Functors::VertexFunction< TVertex, TCost > TVertexWeight;
+
+    public:
+      itkTypeMacro(
+        fpa::Filters::RandomWalker, fpa::Filters::PriorityQueueAlgorithm
+        );
+
+      itkGetConstObjectMacro( ScalarWeight, TScalarWeight );
+      itkGetObjectMacro( ScalarWeight, TScalarWeight );
+
+      itkGetConstObjectMacro( VertexWeight, TVertexWeight );
+      itkGetObjectMacro( VertexWeight, TVertexWeight );
+
+    public:
+      void SetWeightFunction( TScalarWeight* p );
+      void SetWeightFunction( TVertexWeight* p );
+
+    protected:
+      RandomWalker( );
+      virtual ~RandomWalker( );
+
+      virtual void _PostComputeOutputValue( TNode& n ) override;
+      virtual void _PreComputeOutputValue( TNode& n ) override;
+
+    private:
+      RandomWalker( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      typename TScalarWeight::Pointer m_ScalarWeight;
+      typename TVertexWeight::Pointer m_VertexWeight;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/RandomWalker.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+#endif // __fpa__Filters__RandomWalker__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/RandomWalker.hxx b/lib/fpa/Filters/RandomWalker.hxx
new file mode 100644 (file)
index 0000000..18b8d2b
--- /dev/null
@@ -0,0 +1,84 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__RandomWalker__hxx__
+#define __fpa__Filters__RandomWalker__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::RandomWalker< _TDataInterface >::
+SetWeightFunction( TScalarWeight* p )
+{
+  if( this->m_ScalarWeight.GetPointer( ) != p )
+  {
+    this->_Deassociate( this->m_ScalarWeight );
+    this->m_ScalarWeight = p;
+    this->_Associate( this->m_ScalarWeight );
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::RandomWalker< _TDataInterface >::
+SetWeightFunction( TVertexWeight* p )
+{
+  if( this->m_VertexWeight.GetPointer( ) != p )
+  {
+    this->_Deassociate( this->m_VertexWeight );
+    this->m_VertexWeight = p;
+    this->_Associate( this->m_VertexWeight );
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+fpa::Filters::RandomWalker< _TDataInterface >::
+RandomWalker( )
+  : Superclass( false )
+{
+  this->SetInitValue( TCost( 0 ) );
+  /* TODO
+     this->SetWeight(
+     fpa::Functors::RegionGrow::Tautology< TInputValue >::New( )
+     );
+  */
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+fpa::Filters::RandomWalker< _TDataInterface >::
+~RandomWalker( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::RandomWalker< _TDataInterface >::
+_PostComputeOutputValue( TNode& n )
+{
+  // Nothing to do with this algorithm
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::RandomWalker< _TDataInterface >::
+_PreComputeOutputValue( TNode& n )
+{
+  if( this->m_VertexWeight.IsNotNull( ) )
+  {
+    TCost 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 = TCost( -1 );
+}
+
+#endif // __fpa__Filters__RandomWalker__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/RegionGrow.h b/lib/fpa/Filters/RegionGrow.h
new file mode 100644 (file)
index 0000000..89790e8
--- /dev/null
@@ -0,0 +1,81 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__RegionGrow__h__
+#define __fpa__Filters__RegionGrow__h__
+
+#include <itkFunctionBase.h>
+#include <fpa/Config.h>
+#include <fpa/Filters/QueueAlgorithm.h>
+#include <fpa/Functors/VertexFunction.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    /**
+     */
+    template< class _TDataInterface >
+    class RegionGrow
+      : public fpa::Filters::QueueAlgorithm< _TDataInterface >
+    {
+    public:
+      typedef _TDataInterface TDataInterface;
+      typedef fpa::Filters::QueueAlgorithm< TDataInterface > Superclass;
+      typedef RegionGrow                                     Self;
+      typedef itk::SmartPointer< Self >                      Pointer;
+      typedef itk::SmartPointer< const Self >                ConstPointer;
+
+      typedef typename TDataInterface::TTraits TTraits;
+      fpaTraitsMacro( typename TTraits );
+
+      typedef itk::FunctionBase< TInputValue, bool >         TScalarPredicate;
+      typedef fpa::Functors::VertexFunction< TVertex, bool > TVertexPredicate;
+
+    public:
+      itkTypeMacro( fpa::Filters::RegionGrow, fpa::Filters::QueueAlgorithm );
+
+      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 _PostComputeOutputValue( TNode& n ) override;
+      virtual void _PreComputeOutputValue( TNode& n ) override;
+
+    private:
+      RegionGrow( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      typename TScalarPredicate::Pointer m_ScalarPredicate;
+      typename TVertexPredicate::Pointer m_VertexPredicate;
+
+      TOutputValue m_InsideValue;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/RegionGrow.hxx>
+#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 (file)
index 0000000..50ae38d
--- /dev/null
@@ -0,0 +1,107 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__RegionGrow__hxx__
+#define __fpa__Filters__RegionGrow__hxx__
+
+#include <limits>
+#include <fpa/Functors/RegionGrow/Tautology.h>
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::RegionGrow< _TDataInterface >::
+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 _TDataInterface >
+void fpa::Filters::RegionGrow< _TDataInterface >::
+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 _TDataInterface >
+typename fpa::Filters::RegionGrow< _TDataInterface >::
+TOutputValue fpa::Filters::RegionGrow< _TDataInterface >::
+GetOutsideValue( ) const
+{
+  return( this->GetInitValue( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::RegionGrow< _TDataInterface >::
+SetOutsideValue( const TOutputValue& v )
+{
+  this->SetInitValue( v );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+fpa::Filters::RegionGrow< _TDataInterface >::
+RegionGrow( )
+  : Superclass( false )
+{
+  this->SetOutsideValue( TOutputValue( 0 ) );
+  this->m_InsideValue = std::numeric_limits< TOutputValue >::max( );
+  this->SetPredicate(
+    fpa::Functors::RegionGrow::Tautology< TInputValue >::New( )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+fpa::Filters::RegionGrow< _TDataInterface >::
+~RegionGrow( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TDataInterface >
+void fpa::Filters::RegionGrow< _TDataInterface >::
+_PostComputeOutputValue( TNode& n )
+{
+  TInputValue value = this->_GetInputValue( n.Vertex );
+  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 _TDataInterface >
+void fpa::Filters::RegionGrow< _TDataInterface >::
+_PreComputeOutputValue( TNode& n )
+{
+  // Nothing to do with this algorithm
+}
+
+#endif // __fpa__Filters__RegionGrow__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/Filters/SingleSeedInterface.h b/lib/fpa/Filters/SingleSeedInterface.h
new file mode 100644 (file)
index 0000000..d06e91b
--- /dev/null
@@ -0,0 +1,48 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__SingleSeedInterface__h__
+#define __fpa__Filters__SingleSeedInterface__h__
+
+#include <fpa/Filters/BaseSeedsInterface.h>
+
+namespace fpa
+{
+  namespace Filters
+  {
+    /**
+     */
+    template< class _TTraits >
+    class SingleSeedInterface
+      : public fpa::Filters::BaseSeedsInterface< _TTraits >
+    {
+    public:
+      typedef fpa::Filters::BaseSeedsInterface< _TTraits > Superclass;
+      typedef SingleSeedInterface                          Self;
+      typedef _TTraits TTraits;
+      fpaTraitsMacro( typename TTraits );
+
+    public:
+      void SetSeed( const TPoint& s );
+      void SetSeed( const TVertex& s );
+
+    protected:
+      SingleSeedInterface( itk::ProcessObject* f );
+      virtual ~SingleSeedInterface( );
+
+      virtual void _PrepareSeeds( const itk::DataObject* reference ) override;
+
+    protected:
+      TSeed m_InputSeed;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/Filters/SingleSeedInterface.hxx>
+#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 (file)
index 0000000..25acc2b
--- /dev/null
@@ -0,0 +1,73 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Filters__SingleSeedInterface__hxx__
+#define __fpa__Filters__SingleSeedInterface__hxx__
+
+#include <itkImageBase.h>
+
+// -------------------------------------------------------------------------
+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 >
+fpa::Filters::SingleSeedInterface< _TTraits >::
+SingleSeedInterface( itk::ProcessObject* f )
+  : Superclass( f )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+fpa::Filters::SingleSeedInterface< _TTraits >::
+~SingleSeedInterface( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TTraits >
+void fpa::Filters::SingleSeedInterface< _TTraits >::
+_PrepareSeeds( const itk::DataObject* reference )
+{
+  // Input object is an image?
+  typedef itk::ImageBase< TTraits::Dimension > _TImageBase;
+  const _TImageBase* image =
+    dynamic_cast< const _TImageBase* >( reference );
+  if( image != NULL )
+  {
+    this->m_UnifiedSeeds.clear( );
+    if( this->m_InputSeed.IsPoint )
+      image->TransformPhysicalPointToIndex(
+        this->m_InputSeed.Point, this->m_InputSeed.Vertex
+        );
+    TNode node;
+    node.Vertex = this->m_InputSeed.Vertex;
+    node.Parent = this->m_InputSeed.Vertex;
+    node.FrontId = this->m_InputSeed.FrontId;
+    this->m_UnifiedSeeds.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 (file)
index 0000000..814f42b
--- /dev/null
@@ -0,0 +1,69 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Functors__BaseVertexFunction__h__
+#define __fpa__Functors__BaseVertexFunction__h__
+
+#include <itkDataObject.h>
+#include <itkObject.h>
+
+namespace fpa
+{
+  namespace Functors
+  {
+    /**
+     */
+    template< class _TVertex >
+    class BaseVertexFunction
+      : public itk::Object
+    {
+    public:
+      typedef _TVertex TVertex;
+      typedef itk::Object                     Superclass;
+      typedef BaseVertexFunction              Self;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+    public:
+      itkTypeMacro( fpa::Functors::BaseVertexFunction, 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:
+      BaseVertexFunction( )
+        : Superclass( ),
+          m_DataObject( NULL )
+        {
+        }
+
+      virtual ~BaseVertexFunction( )
+        {
+        }
+
+    private:
+      // Purposely not implemented.
+      BaseVertexFunction( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      itk::DataObject::ConstPointer m_DataObject;
+    };
+
+  } // 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 (file)
index 0000000..e917e95
--- /dev/null
@@ -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 <cmath>
+#include <fpa/Functors/VertexFunction.h>
+
+namespace fpa
+{
+  namespace Functors
+  {
+    namespace Dijkstra
+    {
+      namespace Image
+      {
+        /**
+         */
+        template< class _TImage, class _TValue >
+        class Gaussian
+          : public fpa::Functors::VertexFunction< typename _TImage::IndexType, _TValue >
+        {
+        public:
+          typedef _TImage TImage;
+          typedef _TValue TValue;
+          typedef typename TImage::IndexType TVertex;
+          typedef fpa::Functors::VertexFunction< 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::VertexFunction
+            );
+
+        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 (file)
index 0000000..543a5ef
--- /dev/null
@@ -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 <fpa/Functors/VertexFunction.h>
+
+namespace fpa
+{
+  namespace Functors
+  {
+    namespace Dijkstra
+    {
+      namespace Image
+      {
+        /**
+         */
+        template< class _TImage, class _TValue >
+        class Identity
+          : public fpa::Functors::VertexFunction< typename _TImage::IndexType, _TValue >
+        {
+        public:
+          typedef _TImage TImage;
+          typedef _TValue TValue;
+          typedef typename TImage::IndexType TVertex;
+          typedef fpa::Functors::VertexFunction< 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::VertexFunction
+            );
+
+        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 (file)
index 0000000..af9bbe7
--- /dev/null
@@ -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 <itkFunctionBase.h>
+
+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 (file)
index 0000000..57abad4
--- /dev/null
@@ -0,0 +1,77 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Functors__RegionGrow__BinaryThreshold__h__
+#define __fpa__Functors__RegionGrow__BinaryThreshold__h__
+
+#include <itkFunctionBase.h>
+
+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 <fpa/Functors/RegionGrow/BinaryThreshold.hxx>
+#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 (file)
index 0000000..f7ad48f
--- /dev/null
@@ -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 <limits>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..94fc0db
--- /dev/null
@@ -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 <itkFunctionBase.h>
+
+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/Functors/VertexFunction.h b/lib/fpa/Functors/VertexFunction.h
new file mode 100644 (file)
index 0000000..43fd538
--- /dev/null
@@ -0,0 +1,59 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__Functors__VertexFunction__h__
+#define __fpa__Functors__VertexFunction__h__
+
+#include <fpa/Functors/BaseVertexFunction.h>
+
+namespace fpa
+{
+  namespace Functors
+  {
+    /**
+     */
+    template< class _TVertex, class _TValue >
+    class VertexFunction
+      : public fpa::Functors::BaseVertexFunction< _TVertex >
+    {
+    public:
+      typedef _TVertex TVertex;
+      typedef _TValue  TValue;
+      typedef fpa::Functors::BaseVertexFunction< TVertex > Superclass;
+      typedef VertexFunction                               Self;
+      typedef itk::SmartPointer< Self >                    Pointer;
+      typedef itk::SmartPointer< const Self >              ConstPointer;
+
+    public:
+      itkTypeMacro(
+        fpa::Functors::VertexFunction, fpa::Functors::BaseVertexFunction
+        );
+
+    public:
+      virtual TValue Evaluate(
+        const TVertex& vertex, const TVertex& parent
+        ) const = 0;
+
+    protected:
+      VertexFunction( )
+        : Superclass( )
+        {
+        }
+
+      virtual ~VertexFunction( )
+        {
+        }
+
+    private:
+      // Purposely not implemented.
+      VertexFunction( const Self& other );
+      Self& operator=( const Self& other );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __fpa__Functors__VertexFunction__h__
+// eof - $RCSfile$
diff --git a/lib/fpa/VTK/Image/PathToPolyDataFilter.h b/lib/fpa/VTK/Image/PathToPolyDataFilter.h
new file mode 100644 (file)
index 0000000..d6157e0
--- /dev/null
@@ -0,0 +1,70 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__VTK__Image__PathToPolyDataFilter__h__
+#define __fpa__VTK__Image__PathToPolyDataFilter__h__
+
+#include <vtkPolyDataAlgorithm.h>
+
+namespace fpa
+{
+  namespace VTK
+  {
+    namespace Image
+    {
+      /**
+       */
+      template< class _TPath >
+      class PathToPolyDataFilter
+        : public vtkPolyDataAlgorithm
+      {
+      public:
+        typedef PathToPolyDataFilter Self;
+        typedef _TPath               TPath;
+
+      public:
+        vtkTypeMacro( PathToPolyDataFilter, vtkPolyDataAlgorithm );
+
+      public:
+        static Self* New( );
+
+        const TPath* GetInput( ) const;
+        void SetInput( const TPath* path );
+
+      protected:
+        PathToPolyDataFilter( );
+        virtual ~PathToPolyDataFilter( );
+
+        int RequestData(
+          vtkInformation* information,
+          vtkInformationVector** input,
+          vtkInformationVector* output
+          );
+        int RequestInformation(
+          vtkInformation* information,
+          vtkInformationVector** input,
+          vtkInformationVector* output
+          );
+
+      private:
+        // Purposely not implemented
+        PathToPolyDataFilter( const Self& );
+        void operator=( const Self& );
+
+      protected:
+        const TPath* m_Path;
+      };
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <fpa/VTK/Image/PathToPolyDataFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+#endif // __fpa__VTK__Image__PathToPolyDataFilter__h__
+
+// eof - $RCSfile$
diff --git a/lib/fpa/VTK/Image/PathToPolyDataFilter.hxx b/lib/fpa/VTK/Image/PathToPolyDataFilter.hxx
new file mode 100644 (file)
index 0000000..4965778
--- /dev/null
@@ -0,0 +1,133 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+#ifndef __fpa__VTK__Image__PathToPolyDataFilter__hxx__
+#define __fpa__VTK__Image__PathToPolyDataFilter__hxx__
+
+#include <vtkCellArray.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+#include <vtkPointData.h>
+#include <vtkUnsignedIntArray.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+typename fpa::VTK::Image::PathToPolyDataFilter< _TPath >::
+Self* fpa::VTK::Image::PathToPolyDataFilter< _TPath >::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+const typename
+fpa::VTK::Image::PathToPolyDataFilter< _TPath >::
+TPath* fpa::VTK::Image::PathToPolyDataFilter< _TPath >::
+GetInput( ) const
+{
+  return( this->m_Path );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+void fpa::VTK::Image::PathToPolyDataFilter< _TPath >::
+SetInput( const TPath* path )
+{
+  if( this->m_Path != path )
+  {
+    this->m_Path = path;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+fpa::VTK::Image::PathToPolyDataFilter< _TPath >::
+PathToPolyDataFilter( )
+  : vtkPolyDataAlgorithm( ),
+    m_Path( NULL )
+{
+  this->SetNumberOfInputPorts( 0 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+fpa::VTK::Image::PathToPolyDataFilter< _TPath >::
+~PathToPolyDataFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TPath >
+int fpa::VTK::Image::PathToPolyDataFilter< _TPath >::
+RequestData(
+  vtkInformation* information,
+  vtkInformationVector** input,
+  vtkInformationVector* output
+  )
+{
+  static const unsigned int dim = TPath::PathDimension;
+  if( this->m_Path == 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::PathToPolyDataFilter< _TPath >::
+RequestInformation(
+  vtkInformation* information,
+  vtkInformationVector** input,
+  vtkInformationVector* output
+  )
+{
+  return( 1 );
+}
+
+#endif // __fpa__VTK__Image__PathToPolyDataFilterFilter__hxx__
+// eof - $RCSfile$
diff --git a/lib/fpa/VTK/Image/SkeletonToPolyDataFilter.h b/lib/fpa/VTK/Image/SkeletonToPolyDataFilter.h
new file mode 100644 (file)
index 0000000..f34ae2e
--- /dev/null
@@ -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 <vtkPolyDataAlgorithm.h>
+
+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 <fpa/VTK/Image/SkeletonToPolyDataFilter.hxx>
+#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 (file)
index 0000000..6b1aeef
--- /dev/null
@@ -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 <vtkCellArray.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+#include <vtkPointData.h>
+#include <vtkUnsignedIntArray.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..38f8172
--- /dev/null
@@ -0,0 +1,11 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#include <fpa/fpa_export.h>
+#include <string>
+
+std::string FPA_EXPORT version( ) { return( "@prj_VER@" ); }
+
+// eof - $RCSfile$
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d769819
--- /dev/null
@@ -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 (file)
index 0000000..712d537
--- /dev/null
@@ -0,0 +1,8 @@
+## =========================================================================
+## @author Leonardo Florez Valencia
+## @email florez-l@javeriana.edu.co
+## =========================================================================
+
+subdirs(RegionGrow RandomWalker Dijkstra)
+
+## eof - $RCSfile$
diff --git a/tests/image/Dijkstra/CMakeLists.txt b/tests/image/Dijkstra/CMakeLists.txt
new file mode 100644 (file)
index 0000000..47c3bfa
--- /dev/null
@@ -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
+  ExtractSkeleton
+  )
+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 (file)
index 0000000..6d94cae
--- /dev/null
@@ -0,0 +1,80 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#include <itkImage.h>
+#include <itkImageFileReader.h>
+#include <fpa/Common/Image/PathWriter.h>
+#include <fpa/Filters/Image/ExtractAxis.h>
+
+// -------------------------------------------------------------------------
+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::PathWriter< 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/ExtractSkeleton.cxx b/tests/image/Dijkstra/ExtractSkeleton.cxx
new file mode 100644 (file)
index 0000000..9984de9
--- /dev/null
@@ -0,0 +1,82 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#include <itkImage.h>
+#include <itkImageFileReader.h>
+#include <fpa/Common/Image/SkeletonWriter.h>
+#include <fpa/Filters/Image/ExtractSkeleton.h>
+
+// -------------------------------------------------------------------------
+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::ExtractSkeleton< 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/Dijkstra/Gaussian.cxx b/tests/image/Dijkstra/Gaussian.cxx
new file mode 100644 (file)
index 0000000..3139e83
--- /dev/null
@@ -0,0 +1,102 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#include <itkImage.h>
+#include <itkImageFileReader.h>
+#include <itkImageFileWriter.h>
+#include <fpa/Filters/Image/Dijkstra.h>
+#include <fpa/Functors/Dijkstra/Image/Gaussian.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..223283a
--- /dev/null
@@ -0,0 +1,93 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#include <itkImage.h>
+#include <itkImageFileWriter.h>
+#include <fpa/Filters/Image/Dijkstra.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..fc0ace7
--- /dev/null
@@ -0,0 +1,102 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#include <itkImage.h>
+#include <itkImageFileReader.h>
+#include <itkImageFileWriter.h>
+#include <fpa/Filters/Image/Dijkstra.h>
+#include <fpa/Functors/Dijkstra/Invert.h>
+
+// -------------------------------------------------------------------------
+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/RandomWalker/CMakeLists.txt b/tests/image/RandomWalker/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e4bd49a
--- /dev/null
@@ -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 (file)
index 0000000..82d44ae
--- /dev/null
@@ -0,0 +1,91 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#include <itkImage.h>
+#include <itkImageFileReader.h>
+#include <itkImageFileWriter.h>
+#include <fpa/Filters/Image/RandomWalker.h>
+#include <fpa/Functors/Dijkstra/Image/Gaussian.h>
+
+// -------------------------------------------------------------------------
+const unsigned int Dim = 2;
+typedef unsigned char TPixel;
+typedef unsigned char TLabel;
+typedef float TCost;
+typedef itk::Image< TPixel, Dim > TImage;
+typedef itk::Image< TLabel, Dim > TLabelImage;
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  // Get arguments
+  if( argc < 7 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " input_image input_label output_image output_costs alpha beta"
+      << std::endl;
+    return( 1 );
+
+  } // fi
+  std::string input_image_filename = argv[ 1 ];
+  std::string input_label_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< TImage > TImageReader;
+  TImageReader::Pointer input_image_reader = TImageReader::New( );
+  input_image_reader->SetFileName( input_image_filename );
+
+  // Read labels
+  typedef itk::ImageFileReader< TLabelImage > TLabelImageReader;
+  TLabelImageReader::Pointer input_label_reader = TLabelImageReader::New( );
+  input_label_reader->SetFileName( input_label_filename );
+
+  // Prepare weight functor
+  typedef fpa::Functors::Dijkstra::Image::Gaussian< TImage, TCost > TWeight;
+  TWeight::Pointer weight = TWeight::New( );
+  weight->SetAlpha( alpha );
+  weight->SetBeta( beta );
+
+  // Prepare filter
+  typedef fpa::Filters::Image::RandomWalker< TImage, TLabelImage, TCost > TFilter;
+  TFilter::Pointer filter = TFilter::New( );
+  filter->SetInputImage( input_image_reader->GetOutput( ) );
+  filter->SetInputLabels( input_label_reader->GetOutput( ) );
+  filter->SetWeightFunction( weight );
+
+  // Execute filter
+  filter->Update( );
+
+  // Save results
+  typedef itk::ImageFileWriter< TFilter::TLabelImage > 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 (file)
index 0000000..3e15d36
--- /dev/null
@@ -0,0 +1,95 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#include <itkImage.h>
+#include <itkImageFileReader.h>
+#include <itkImageFileWriter.h>
+#include <fpa/Filters/Image/RegionGrow.h>
+#include <fpa/Functors/RegionGrow/BinaryThreshold.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..e5c55b5
--- /dev/null
@@ -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 (file)
index 0000000..8d11ac2
--- /dev/null
@@ -0,0 +1,82 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#include <itkImage.h>
+#include <itkImageFileReader.h>
+#include <itkImageFileWriter.h>
+#include <fpa/Filters/Image/Mori.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..486cc62
--- /dev/null
@@ -0,0 +1,95 @@
+// =========================================================================
+// @author Leonardo Florez Valencia
+// @email florez-l@javeriana.edu.co
+// =========================================================================
+
+#include <itkImage.h>
+#include <itkImageFileWriter.h>
+#include <fpa/Filters/Image/RegionGrow.h>
+#include <fpa/Functors/RegionGrow/Tautology.h>
+
+// -------------------------------------------------------------------------
+const unsigned int Dim = 2;
+typedef unsigned char  TPixel;
+typedef unsigned short TMark;
+typedef itk::Image< TPixel, Dim > TImage;
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  // Get arguments
+  if( argc < 5 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " output_image output_marks size stop [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 ] ) );
+  bool stop = ( argv[ 4 ][ 0 ] == '1' );
+
+  // 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, TMark > TFilter;
+  TFilter::Pointer filter = TFilter::New( );
+  filter->SetInput( image );
+  filter->SetPredicate( predicate );
+  filter->SetInsideValue( std::numeric_limits< TPixel >::max( ) );
+  filter->SetOutsideValue( TPixel( 0 ) );
+  filter->SetStopAtOneFront( stop );
+
+  // Get all seeds
+  for( int i = 5; 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$