]> Creatis software - FrontAlgorithms.git/commitdiff
...
authorLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Tue, 5 Dec 2017 17:06:20 +0000 (12:06 -0500)
committerLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Tue, 5 Dec 2017 17:06:20 +0000 (12:06 -0500)
appli/CTBronchi/CMakeLists.txt
appli/CTBronchi/CommandLineProcess.cxx [new file with mode: 0644]
appli/CTBronchi/Filter.h [new file with mode: 0644]
appli/CTBronchi/Filter.hxx [new file with mode: 0644]
appli/CTBronchi/Image.h
appli/CTBronchi/Image.hxx
appli/CTBronchi/Process.cxx
appli/CTBronchi/Process.h

index b5f19be277946146496cb99752650b68e4474036..be25477167f2a9469390de5c032cabc74a92741a 100644 (file)
@@ -4,36 +4,58 @@
 
 option(fpa_BUILD_CTBronchi "Build bronchi analysis from CT images applications?" OFF)
 if(fpa_BUILD_CTBronchi)
-  set(_pfx fpa_CTBronchi_)
-  set(
-    _examples
-    Vesselness
-    MoriSegmentation
-    MoriLabelling
-    FastRandomWalker
-    SliceBySliceRandomWalker
-    AndSegmentations
-    Skeleton
+  BuildLibrary(
+    fpa_CTBronchi SHARED
+    INSTALL_ALL
+    SOURCE
+    Filter.h Filter.hxx
+    Image.h Image.hxx
+    Process.h Process.cxx
+    LINKS fpa cpPlugins::tclap
     )
-  foreach(_e ${_examples})
-    BuildApplication(
-      ${_pfx}${_e}
-      SOURCE ${_e}.cxx
-      INSTALL
-      RECURRENT
-      LINKS fpa cpPlugins::tclap
-      )
-  endforeach(_e)
 
-  configure_file(
-    Process.sh
-    ${PROJECT_BINARY_DIR}/${_pfx}Process.sh
-    COPYONLY
-    )
-  install(
-    FILES ${PROJECT_BINARY_DIR}/${_pfx}Process.sh
-    DESTINATION bin
+  BuildApplication(
+    fpa_CTBronchi_CommandLineProcess
+    SOURCE CommandLineProcess.cxx
+    INSTALL
+    RECURRENT
+    LINKS fpa_CTBronchi
     )
+
 endif(fpa_BUILD_CTBronchi)
 
+#option(fpa_BUILD_CTBronchi "Build bronchi analysis from CT images applications?" OFF)
+#if(fpa_BUILD_CTBronchi)
+#  set(_pfx fpa_CTBronchi_)
+#  set(
+#    _examples
+#    Vesselness
+#    MoriSegmentation
+#    MoriLabelling
+#    FastRandomWalker
+#    SliceBySliceRandomWalker
+#    AndSegmentations
+#    Skeleton
+#    )
+#  foreach(_e ${_examples})
+#    BuildApplication(
+#      ${_pfx}${_e}
+#      SOURCE ${_e}.cxx
+#      INSTALL
+#      RECURRENT
+#      LINKS fpa cpPlugins::tclap
+#      )
+#  endforeach(_e)
+
+#  configure_file(
+#    Process.sh
+#    ${PROJECT_BINARY_DIR}/${_pfx}Process.sh
+#    COPYONLY
+#    )
+#  install(
+#    FILES ${PROJECT_BINARY_DIR}/${_pfx}Process.sh
+#    DESTINATION bin
+#    )
+#endif(fpa_BUILD_CTBronchi)
+
 ## eof - $RCSfile$
diff --git a/appli/CTBronchi/CommandLineProcess.cxx b/appli/CTBronchi/CommandLineProcess.cxx
new file mode 100644 (file)
index 0000000..8131d0e
--- /dev/null
@@ -0,0 +1,25 @@
+// =========================================================================
+// @author Leonardo Florez Valencia (florez-l@javeriana.edu.co)
+// =========================================================================
+
+#include <iostream>
+#include "Process.h"
+
+int main( int argc, char* argv[] )
+{
+  try
+  {
+    CTBronchi::Process process;
+    process.ParseArguments( argc, argv );
+    process.Update( );
+  }
+  catch( std::exception& err )
+  {
+    std::cerr << "Error caught: " << err.what( ) << std::endl;
+    return( 1 );
+
+  } // yrt
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/appli/CTBronchi/Filter.h b/appli/CTBronchi/Filter.h
new file mode 100644 (file)
index 0000000..20de5ec
--- /dev/null
@@ -0,0 +1,39 @@
+// =========================================================================
+// @author Leonardo Florez Valencia (florez-l@javeriana.edu.co)
+// =========================================================================
+#ifndef __CTBronchi__Filter__h__
+#define __CTBronchi__Filter__h__
+
+namespace CTBronchi
+{
+  /**
+   */
+  template< class _TFilter >
+  class Filter
+  {
+  public:
+    typedef _TFilter TFilter;
+
+  public:
+    Filter( );
+    virtual ~Filter( );
+
+    bool IsNotNull( ) const;
+    bool IsNull( ) const;
+
+    TFilter* Get( );
+    const TFilter* Get( ) const;
+
+    double Update( );
+
+  protected:
+    typename TFilter::Pointer m_Filter;
+  };
+
+} // ecapseman
+
+#include "Filter.hxx"
+
+#endif // __CTBronchi__Filter__h__
+
+// eof - $RCSfile$
diff --git a/appli/CTBronchi/Filter.hxx b/appli/CTBronchi/Filter.hxx
new file mode 100644 (file)
index 0000000..8f4f8e6
--- /dev/null
@@ -0,0 +1,79 @@
+// =========================================================================
+// @author Leonardo Florez Valencia (florez-l@javeriana.edu.co)
+// =========================================================================
+#ifndef __CTBronchi__Filter__hxx__
+#define __CTBronchi__Filter__hxx__
+
+#include <chrono>
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+CTBronchi::Filter< _TFilter >::
+Filter( )
+{
+  this->m_Filter = TFilter::New( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+CTBronchi::Filter< _TFilter >::
+~Filter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+bool CTBronchi::Filter< _TFilter >::
+IsNotNull( ) const
+{
+  return( this->m_Filter.IsNotNull( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+bool CTBronchi::Filter< _TFilter >::
+IsNull( ) const
+{
+  return( this->m_Filter.IsNotNull( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+typename CTBronchi::Filter< _TFilter >::
+TFilter* CTBronchi::Filter< _TFilter >::
+Get( )
+{
+  return( this->m_Filter );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+const typename CTBronchi::Filter< _TFilter >::
+TFilter* CTBronchi::Filter< _TFilter >::
+Get( ) const
+{
+  return( this->m_Filter );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+double CTBronchi::Filter< _TFilter >::
+Update( )
+{
+  if( this->IsNotNull( ) )
+  {
+    std::chrono::time_point< std::chrono::high_resolution_clock > s, e;
+    std::chrono::duration< double > t;
+    s = std::chrono::high_resolution_clock::now( );
+    this->m_Filter->Update( );
+    e = std::chrono::high_resolution_clock::now( );
+    t = e - s;
+    return( t.count( ) );
+  }
+  else
+    return( -1 );
+}
+
+#endif // __CTBronchi__Filter__hxx__
+
+// eof - $RCSfile$
index 8b243e640e11c2ea7b32b0b367c9f4997d6097bf..4518293ac709aaf4129e58abcce4c26501e9d6d8 100644 (file)
@@ -14,7 +14,7 @@ namespace CTBronchi
   class Image
   {
   public:
-    static const unsigned int _VDim = VDim;
+    static const unsigned int VDim = _VDim;
     typedef _TPixel TPixel;
     typedef itk::Image< TPixel, VDim > TImage;
 
@@ -28,10 +28,10 @@ namespace CTBronchi
     TImage* Get( );
     const TImage* Get( ) const;
     void Set( TImage* image );
-    void Set( const TImage::Pointer& image );
+    void Set( const typename TImage::Pointer& image );
 
-    void Load( const std::string& fname );
-    void Save( const std::string& fname );
+    double Load( const std::string& fname );
+    double Save( const std::string& fname );
 
   protected:
     typename TImage::Pointer m_Image;
index 4b6fa9b8ff1c37ae2285b89e2bfbe1349a59c000..86ce8ebc7551c3d8f2032b127a42f41f5622362a 100644 (file)
@@ -4,6 +4,7 @@
 #ifndef __CTBronchi__Image__hxx__
 #define __CTBronchi__Image__hxx__
 
+#include "Filter.h"
 #include <itkImageFileReader.h>
 #include <itkImageFileWriter.h>
 
@@ -61,57 +62,64 @@ void CTBronchi::Image< _TPixel, _VDim >::
 Set( TImage* image )
 {
   this->m_Image = image;
-  this->m_Image->DisconnectPipeline( );
+  if( this->m_Image.IsNotNull( ) )
+    this->m_Image->DisconnectPipeline( );
 }
 
 // -------------------------------------------------------------------------
 template< class _TPixel, unsigned int _VDim >
 void CTBronchi::Image< _TPixel, _VDim >::
-Set( const TImage::Pointer& image )
+Set( const typename TImage::Pointer& image )
 {
   this->m_Image = image.GetPointer( );
-  this->m_Image->DisconnectPipeline( );
+  if( this->m_Image.IsNotNull( ) )
+    this->m_Image->DisconnectPipeline( );
 }
 
 // -------------------------------------------------------------------------
 template< class _TPixel, unsigned int _VDim >
-void CTBronchi::Image< _TPixel, _VDim >::
+double CTBronchi::Image< _TPixel, _VDim >::
 Load( const std::string& fname )
 {
-  typedef itk::ImageFileReader< TImage > _TReader;
-  typename _TReader::Pointer r = _TReader::New( );
-  r->SetFileName( fname );
+  typedef CTBronchi::Filter< itk::ImageFileReader< TImage > > _TReader;
+  _TReader r;
+  r.Get( )->SetFileName( fname );
   try
   {
-    r->Update( );
-    this->Set( r->GetOutput( ) );
+    double t = r.Update( );
+    this->Set( r.Get( )->GetOutput( ) );
+    return( t );
   }
   catch( ... )
   {
     this->Set( NULL );
+    return( -1 );
 
   } // yrt
 }
 
 // -------------------------------------------------------------------------
 template< class _TPixel, unsigned int _VDim >
-void CTBronchi::Image< _TPixel, _VDim >::
+double CTBronchi::Image< _TPixel, _VDim >::
 Save( const std::string& fname )
 {
-  typedef itk::ImageFileWriter< TImage > _TWriter;
+  typedef CTBronchi::Filter< itk::ImageFileWriter< TImage > > _TWriter;
 
+  double t = -1;
   if( this->IsNotNull( ) )
   {
-    typename _TWriter::Pointer w = _TWriter::New( );
-    w->SetFileName( fname );
-    w->SetInput( this->m_Image );
+    _TWriter w;
+    w.Get( )->SetFileName( fname );
+    w.Get( )->UseCompressionOn( );
+    w.Get( )->SetInput( this->m_Image );
     try
     {
-      w->Update( );
+      t = w.Update( );
     }
     catch( ... ) { }
 
   } // fi
+  return( t );
 }
 
 #endif // __CTBronchi__Image__hxx__
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9f29ffc9c0ef410d45563552dcb3817fa3e4dd6a 100644 (file)
@@ -0,0 +1,353 @@
+// =========================================================================
+// @author Leonardo Florez Valencia (florez-l@javeriana.edu.co)
+// =========================================================================
+
+#include <fstream>
+#include <streambuf>
+#include <tclap/CmdLine.h>
+
+#include <itkMinimumMaximumImageCalculator.h>
+#include <itkInvertIntensityImageFilter.h>
+#include <itkHessianRecursiveGaussianImageFilter.h>
+#include <itkHessian3DToVesselnessMeasureImageFilter.h>
+
+#include <fpa/Filters/Image/Mori.h>
+
+#include "MoriLabelling.h"
+#include "Process.h"
+
+// -------------------------------------------------------------------------
+CTBronchi::Process::
+Process( )
+  : m_UndefinedLabel( 0 ),
+    m_InsideLabel( 1 ),
+    m_OutsideLabel( 2 )
+{
+  this->m_StrArg[ "input" ] = TArgument( "", true );
+  this->m_StrArg[ "seed_file" ] = TArgument( "", false );
+  this->m_StrArg[ "seed" ] = TArgument( "", false );
+  this->m_StrArg[ "seed_type" ] = TArgument( "point", false );
+
+  this->m_DblArg[ "beta" ] = TArgument( "2.5", false );
+  this->m_DblArg[ "epsilon" ] = TArgument( "1e-5", false );
+  this->m_DblArg[ "vesselness_sigma" ] = TArgument( "0.5", false );
+  this->m_DblArg[ "vesselness_alpha1" ] = TArgument( "0.5", false );
+  this->m_DblArg[ "vesselness_alpha2" ] = TArgument(  "2", false );
+  this->m_DblArg[ "mori_min_thr" ] = TArgument( "-850", false );
+  this->m_DblArg[ "mori_kernel" ] = TArgument( "20", false );
+  this->m_DblArg[ "mori_signal_thr" ] = TArgument( "100", false );
+  this->m_DblArg[ "mori_signal_influence" ] = TArgument( "0.5", false );
+  this->m_DblArg[ "mori_lower" ] = TArgument( "-1024", false );
+  this->m_DblArg[ "mori_upper" ] = TArgument( "0", false );
+  this->m_DblArg[ "mori_delta" ] = TArgument( "1", false );
+  this->m_DblArg[ "slicerw_thr" ] = TArgument( "5", false );
+  this->m_DblArg[ "fastrw_thr" ] = TArgument( "65", false );
+  this->m_DblArg[ "labels_upper_thr" ] = TArgument( "-400", false );
+}
+
+// -------------------------------------------------------------------------
+CTBronchi::Process::
+~Process( )
+{
+}
+
+// -------------------------------------------------------------------------
+void CTBronchi::Process::
+ParseArguments( int argc, char* argv[] )
+{
+  typedef TCLAP::ValueArg< std::string > _TStrArg;
+  typedef TCLAP::ValueArg< TScalar >     _TDblArg;
+  std::map< std::string, _TStrArg* > strArg;
+  std::map< std::string, _TDblArg* > dblArg;
+  unsigned char flag = 'a';
+
+  TArguments::iterator sIt = this->m_StrArg.begin( );
+  for( ; sIt != this->m_StrArg.end( ); ++sIt )
+  {
+    std::stringstream fStr;
+    fStr << flag;
+    flag++;
+    if( flag == 'h' )
+      flag++;
+
+    _TStrArg* a = new _TStrArg(
+      fStr.str( ), sIt->first, sIt->first,
+      std::get< 1 >( sIt->second ),
+      std::get< 0 >( sIt->second ),
+      "string"
+      );
+    strArg[ sIt->first ] = a;
+
+  } // rof
+
+  TArguments::iterator dIt = this->m_DblArg.begin( );
+  for( ; dIt != this->m_DblArg.end( ); ++dIt )
+  {
+    std::stringstream fStr;
+    fStr << flag;
+    flag++;
+    if( flag == 'h' )
+      flag++;
+
+    std::istringstream vStr( std::get< 0 >( dIt->second ) );
+    TScalar v;
+    vStr >> v;
+
+    _TDblArg* a = new _TDblArg(
+      fStr.str( ), dIt->first, dIt->first,
+      std::get< 1 >( dIt->second ),
+      v, "value"
+      );
+    dblArg[ dIt->first ] = a;
+
+  } // rof
+
+  std::map< std::string, _TStrArg* >::iterator saIt;
+  std::map< std::string, _TDblArg* >::iterator daIt;
+  try
+  {
+    TCLAP::CmdLine cmd( "CTBronchi pipeline", ' ', "1.0.0" );
+    for( saIt = strArg.begin( ); saIt != strArg.end( ); ++saIt )
+      cmd.add( *( saIt->second ) );
+    for( daIt = dblArg.begin( ); daIt != dblArg.end( ); ++daIt )
+      cmd.add( *( daIt->second ) );
+    cmd.parse( argc, argv );
+  }
+  catch( TCLAP::ArgException& err )
+  {
+    std::stringstream msg;
+    msg << err.error( ) << " " << err.argId( );
+    throw std::runtime_error( msg.str( ) );
+
+  } // yrt
+
+  for( saIt = strArg.begin( ); saIt != strArg.end( ); ++saIt )
+  {
+    std::get< 0 >( this->m_StrArg[ saIt->first ] ) = saIt->second->getValue( );
+    delete saIt->second;
+
+  } // rof
+  for( daIt = dblArg.begin( ); daIt != dblArg.end( ); ++daIt )
+  {
+    std::stringstream vStr;
+    vStr << daIt->second->getValue( );
+    std::get< 0 >( this->m_DblArg[ daIt->first ] ) = vStr.str( );
+    delete daIt->second;
+
+  } // rof
+
+  // Compute base filename
+  std::string iname = std::get< 0 >( this->m_StrArg[ "input" ] );
+  this->m_BaseFileName = iname.substr( 0, iname.find_last_of( "." ) );
+}
+
+// -------------------------------------------------------------------------
+void CTBronchi::Process::
+Update( )
+{
+  this->_Input( );
+  this->_Vesselness( );
+  this->_Mori( );
+  this->_MoriLabelling( );
+}
+
+// -------------------------------------------------------------------------
+void CTBronchi::Process::
+_Input( )
+{
+  std::string iname = std::get< 0 >( this->m_StrArg[ "input" ] );
+  std::string sname = std::get< 0 >( this->m_StrArg[ "seed_file" ] );
+  std::string seed = std::get< 0 >( this->m_StrArg[ "seed" ] );
+  std::string stype = std::get< 0 >( this->m_StrArg[ "seed_type" ] );
+  if( sname == "" && seed == "" )
+    throw std::runtime_error( "No seed given." );
+  if( sname != "" )
+  {
+    std::ifstream str( sname.c_str( ) );
+    str.seekg( 0, std::ios::end );
+    seed.reserve( str.tellg( ) );
+    str.seekg( 0, std::ios::beg );
+    seed.assign(
+      std::istreambuf_iterator< char >( str ),
+      std::istreambuf_iterator< char >( )
+      );
+    str.close( );
+
+  } // fi
+
+  // Get seed
+  std::istringstream sSeed( seed );
+  TPoint pnt;
+  TIndex idx;
+  if( stype == "point" )
+    sSeed >> pnt[ 0 ] >> pnt[ 1 ] >> pnt[ 2 ];
+  else
+    sSeed >> idx[ 0 ] >> idx[ 1 ] >> idx[ 2 ];
+
+  // Read image
+  double t = this->m_Input.Load( iname );
+  if( t < 0 )
+    std::runtime_error( std::string( "Could not read \"" ) + iname + "\"" );
+  std::cout << "\"" << iname << "\" read in " << t << " s." << std::endl;
+
+  // Synch seed
+  if( stype == "point" )
+    this->m_Input.Get( )->TransformPhysicalPointToIndex( pnt, idx );
+  else
+    this->m_Input.Get( )->TransformIndexToPhysicalPoint( idx, pnt );
+  this->m_Seed = TSeed( idx, pnt );
+}
+
+// -------------------------------------------------------------------------
+void CTBronchi::Process::
+_Vesselness( )
+{
+  std::string vname = this->m_BaseFileName + "_vesselness.mha";
+  double t = this->m_Vesselness.Load( vname );
+  if( t < 0 )
+  {
+    t = 0;
+
+    // Arguments
+    std::stringstream v;
+    v << std::get< 0 >( this->m_DblArg[ "vesselness_sigma" ] ) << " "
+      << std::get< 0 >( this->m_DblArg[ "vesselness_alpha1" ] ) << " "
+      << std::get< 0 >( this->m_DblArg[ "vesselness_alpha2" ] );
+    std::istringstream w( v.str( ) );
+    TScalar s, a1, a2;
+    w >> s >> a1 >> a2;
+
+    // Min-max
+    typedef itk::MinimumMaximumImageCalculator< TPixelImage::TImage > _TMinMax;
+    _TMinMax::Pointer minMax = _TMinMax::New( );
+    minMax->SetImage( this->m_Input.Get( ) );
+    minMax->Compute( );
+
+    // Invert intensities
+    typedef CTBronchi::Filter< itk::InvertIntensityImageFilter< TPixelImage::TImage > > _TInverter;
+    _TInverter inverter;
+    inverter.Get( )->SetInput( this->m_Input.Get( ) );
+    inverter.Get( )->SetMaximum( minMax->GetMaximum( ) );
+    double t1 = inverter.Update( );
+    t += t1;
+    std::cout << "Inversion executed in " << t1 << " s" << std::endl;
+
+    // Compute hessian image
+    typedef CTBronchi::Filter< itk::HessianRecursiveGaussianImageFilter< TPixelImage::TImage > > _THessian;
+    _THessian hessian;
+    hessian.Get( )->SetInput( inverter.Get( )->GetOutput( ) );
+    hessian.Get( )->SetSigma( s );
+    t1 = hessian.Update( );
+    t += t1;
+    std::cout << "Hessian executed in " << t1 << " s" << std::endl;
+
+    // Vesselness
+    typedef CTBronchi::Filter< itk::Hessian3DToVesselnessMeasureImageFilter< TScalar > > _TVesselness;
+    _TVesselness vesselness;
+    vesselness.Get( )->SetInput( hessian.Get( )->GetOutput( ) );
+    vesselness.Get( )->SetAlpha1( a1 );
+    vesselness.Get( )->SetAlpha2( a2 );
+    t1 = vesselness.Update( );
+    t += t1;
+    std::cout << "Hessian measure computed in " << t1 << " s." << std::endl;
+
+    this->m_Vesselness.Set( vesselness.Get( )->GetOutput( ) );
+    t1 = this->m_Vesselness.Save( vname );
+    t += t1;
+    std::cout << "\"" << vname << "\" saved in " << t1 << " s." << std::endl;
+
+  } // fi
+  std::cout << "Vesselness computed in " << t << " s." << std::endl;
+}
+
+// -------------------------------------------------------------------------
+void CTBronchi::Process::
+_Mori( )
+{
+  std::string mname = this->m_BaseFileName + "_mori.mha";
+  double t = this->m_Mori.Load( mname );
+  if( t < 0 )
+  {
+    t = 0;
+
+    // Arguments
+    std::stringstream v;
+    v << std::get< 0 >( this->m_DblArg[ "mori_min_thr" ] ) << " "
+      << std::get< 0 >( this->m_DblArg[ "mori_kernel" ] ) << " "
+      << std::get< 0 >( this->m_DblArg[ "mori_signal_thr" ] ) << " "
+      << std::get< 0 >( this->m_DblArg[ "mori_signal_influence" ] ) << " "
+      << std::get< 0 >( this->m_DblArg[ "mori_lower" ] ) << " "
+      << std::get< 0 >( this->m_DblArg[ "mori_upper" ] ) << " "
+      << std::get< 0 >( this->m_DblArg[ "mori_delta" ] );
+    std::istringstream w( v.str( ) );
+    TScalar mThr, sKernel, sThr, sInfluence, lower, upper, delta;
+    w >> mThr >> sKernel >> sThr >> sInfluence >> lower >> upper >> delta;
+
+    // Mori segmentation
+    typedef CTBronchi::Filter< fpa::Filters::Image::Mori< TPixelImage::TImage, TLabelImage::TImage > > _TMori;
+    _TMori mori;
+    mori.Get( )->SetInput( this->m_Input.Get( ) );
+    mori.Get( )->SetSeed( this->m_Seed.second );
+    mori.Get( )->SetInsideValue( this->m_InsideLabel );
+    mori.Get( )->SetOutsideValue( this->m_UndefinedLabel );
+    mori.Get( )->SetMinimumThreshold( mThr );
+    mori.Get( )->SetSignalKernelSize( sKernel );
+    mori.Get( )->SetSignalThreshold( sThr );
+    mori.Get( )->SetSignalInfluence( sInfluence );
+    mori.Get( )->SetThresholds( lower, upper, delta );
+    double t1 = mori.Update( );
+    t += t1;
+    std::cout << "Segmentation computed in " << t1 << " s." << std::endl;
+
+    this->m_Mori.Set( mori.Get( )->GetOutput( ) );
+    t1 = this->m_Mori.Save( mname );
+    t += t1;
+    std::cout << "\"" << mname << "\" saved in " << t1 << " s." << std::endl;
+
+  } // fi
+  std::cout << "Mori segmentation computed in " << t << " s." << std::endl;
+}
+
+// -------------------------------------------------------------------------
+void CTBronchi::Process::
+_MoriLabelling( )
+{
+  std::string mname = this->m_BaseFileName + "_labels.mha";
+  double t = this->m_Labels.Load( mname );
+  if( t < 0 )
+  {
+    t = 0;
+
+    // Arguments
+    std::stringstream v;
+    v << std::get< 0 >( this->m_DblArg[ "fastrw_thr" ] ) << " "
+      << std::get< 0 >( this->m_DblArg[ "labels_upper_thr" ] );
+    std::istringstream w( v.str( ) );
+    TScalar vThr, uThr;
+    w >> vThr >> uThr;
+
+    // Mori labelling
+    typedef CTBronchi::Filter< CTBronchi::MoriLabelling< TPixelImage::TImage, TLabelImage::TImage, TScalarImage::TImage > > _TLabelling;
+    _TLabelling labelling;
+    labelling.Get( )->SetInput( this->m_Input.Get( ) );
+    labelling.Get( )->SetInputLabels( this->m_Mori.Get( ) );
+    labelling.Get( )->SetInputVesselness( this->m_Vesselness.Get( ) );
+    labelling.Get( )->SetVesselnessThreshold( vThr );
+    labelling.Get( )->SetUpperThreshold( uThr );
+    labelling.Get( )->SetInsideValue( this->m_InsideLabel );
+    labelling.Get( )->SetOutsideValue( this->m_OutsideLabel );
+    labelling.Get( )->SetFillValue( this->m_OutsideLabel );
+    double t1 = labelling.Update( );
+    t += t1;
+    std::cout << "Labelling computed in " << t1 << " s." << std::endl;
+
+    this->m_Labels.Set( labelling.Get( )->GetOutput( ) );
+    t1 = this->m_Labels.Save( mname );
+    t += t1;
+    std::cout << "\"" << mname << "\" saved in " << t1 << " s." << std::endl;
+
+  } // fi
+  std::cout << "Mori labelling computed in " << t << " s." << std::endl;
+}
+
+// eof - $RCSfile$
index 9daaf662b3027a054abe3fb799e62e1b4a7857b4..bae6f4388b4d1752d4046173aac84d51e970dde3 100644 (file)
@@ -4,25 +4,65 @@
 #ifndef __CTBronchi__Process__h__
 #define __CTBronchi__Process__h__
 
-#include <itkImage.h>
+#include <map>
+#include <tuple>
+#include <fpa_ctbronchi_export.h>
+#include "Image.h"
 
 namespace CTBronchi
 {
-  class Process
+  class FPA_CTBRONCHI_EXPORT Process
   {
+  public:
     // Some types and values
     static const unsigned int Dim = 3;
     typedef short         TPixel;
     typedef unsigned char TLabel;
     typedef float         TScalar;
 
-    double MeasureTime( itk::ProcessObject* f );
-
-    template< class _TImagePtr >
-    void ReadImage( _TImagePtr& image, const std::string& fname );
-
-    template< class _TImage >
-    void WriteImage( const _TImage* image, const std::string& fname );
+    // Arguments
+    typedef std::tuple< std::string, bool > TArgument;
+    typedef std::map< std::string, TArgument > TArguments;
+
+    // Images
+    typedef CTBronchi::Image< TPixel, Dim >  TPixelImage;
+    typedef CTBronchi::Image< TLabel, Dim >  TLabelImage;
+    typedef CTBronchi::Image< TScalar, Dim > TScalarImage;
+
+    // Seed
+    typedef TPixelImage::TImage::PointType TPoint;
+    typedef TPixelImage::TImage::IndexType TIndex;
+    typedef std::pair< TIndex, TPoint >    TSeed;
+
+  public:
+    Process( );
+    virtual ~Process( );
+
+    void ParseArguments( int argc, char* argv[] );
+    void Update( );
+
+  protected:
+    void _Input( );
+    void _Vesselness( );
+    void _Mori( );
+    void _MoriLabelling( );
+
+  protected:
+    TArguments m_StrArg;
+    TArguments m_DblArg;
+
+    std::string  m_BaseFileName;
+    TSeed        m_Seed;
+    TLabel m_UndefinedLabel;
+    TLabel m_InsideLabel;
+    TLabel m_OutsideLabel;
+
+    TPixelImage  m_Input;
+    TScalarImage m_Vesselness;
+    TLabelImage  m_Mori;
+    TLabelImage  m_Labels;
+    TLabelImage  m_FastRW;
+    TLabelImage  m_SliceRW;
   };
 
 } // ecapseman