1 // =========================================================================
2 // @author Leonardo Florez Valencia (florez-l@javeriana.edu.co)
3 // =========================================================================
7 #include <tclap/CmdLine.h>
9 #include <itkMinimumMaximumImageCalculator.h>
10 #include <itkInvertIntensityImageFilter.h>
11 #include <itkHessianRecursiveGaussianImageFilter.h>
12 #include <itkHessian3DToVesselnessMeasureImageFilter.h>
14 #include <fpa/Filters/Image/Mori.h>
16 #include "MoriLabelling.h"
19 // -------------------------------------------------------------------------
22 : m_UndefinedLabel( 0 ),
26 this->m_StrArg[ "input" ] = TArgument( "", true );
27 this->m_StrArg[ "seed_file" ] = TArgument( "", false );
28 this->m_StrArg[ "seed" ] = TArgument( "", false );
29 this->m_StrArg[ "seed_type" ] = TArgument( "point", false );
31 this->m_DblArg[ "beta" ] = TArgument( "2.5", false );
32 this->m_DblArg[ "epsilon" ] = TArgument( "1e-5", false );
33 this->m_DblArg[ "vesselness_sigma" ] = TArgument( "0.5", false );
34 this->m_DblArg[ "vesselness_alpha1" ] = TArgument( "0.5", false );
35 this->m_DblArg[ "vesselness_alpha2" ] = TArgument( "2", false );
36 this->m_DblArg[ "mori_min_thr" ] = TArgument( "-850", false );
37 this->m_DblArg[ "mori_kernel" ] = TArgument( "20", false );
38 this->m_DblArg[ "mori_signal_thr" ] = TArgument( "100", false );
39 this->m_DblArg[ "mori_signal_influence" ] = TArgument( "0.5", false );
40 this->m_DblArg[ "mori_lower" ] = TArgument( "-1024", false );
41 this->m_DblArg[ "mori_upper" ] = TArgument( "0", false );
42 this->m_DblArg[ "mori_delta" ] = TArgument( "1", false );
43 this->m_DblArg[ "slicerw_thr" ] = TArgument( "5", false );
44 this->m_DblArg[ "fastrw_thr" ] = TArgument( "65", false );
45 this->m_DblArg[ "labels_upper_thr" ] = TArgument( "-400", false );
48 // -------------------------------------------------------------------------
54 // -------------------------------------------------------------------------
55 void CTBronchi::Process::
56 ParseArguments( int argc, char* argv[] )
58 typedef TCLAP::ValueArg< std::string > _TStrArg;
59 typedef TCLAP::ValueArg< TScalar > _TDblArg;
60 std::map< std::string, _TStrArg* > strArg;
61 std::map< std::string, _TDblArg* > dblArg;
62 unsigned char flag = 'a';
64 TArguments::iterator sIt = this->m_StrArg.begin( );
65 for( ; sIt != this->m_StrArg.end( ); ++sIt )
67 std::stringstream fStr;
73 _TStrArg* a = new _TStrArg(
74 fStr.str( ), sIt->first, sIt->first,
75 std::get< 1 >( sIt->second ),
76 std::get< 0 >( sIt->second ),
79 strArg[ sIt->first ] = a;
83 TArguments::iterator dIt = this->m_DblArg.begin( );
84 for( ; dIt != this->m_DblArg.end( ); ++dIt )
86 std::stringstream fStr;
92 std::istringstream vStr( std::get< 0 >( dIt->second ) );
96 _TDblArg* a = new _TDblArg(
97 fStr.str( ), dIt->first, dIt->first,
98 std::get< 1 >( dIt->second ),
101 dblArg[ dIt->first ] = a;
105 std::map< std::string, _TStrArg* >::iterator saIt;
106 std::map< std::string, _TDblArg* >::iterator daIt;
109 TCLAP::CmdLine cmd( "CTBronchi pipeline", ' ', "1.0.0" );
110 for( saIt = strArg.begin( ); saIt != strArg.end( ); ++saIt )
111 cmd.add( *( saIt->second ) );
112 for( daIt = dblArg.begin( ); daIt != dblArg.end( ); ++daIt )
113 cmd.add( *( daIt->second ) );
114 cmd.parse( argc, argv );
116 catch( TCLAP::ArgException& err )
118 std::stringstream msg;
119 msg << err.error( ) << " " << err.argId( );
120 throw std::runtime_error( msg.str( ) );
124 for( saIt = strArg.begin( ); saIt != strArg.end( ); ++saIt )
126 std::get< 0 >( this->m_StrArg[ saIt->first ] ) = saIt->second->getValue( );
130 for( daIt = dblArg.begin( ); daIt != dblArg.end( ); ++daIt )
132 std::stringstream vStr;
133 vStr << daIt->second->getValue( );
134 std::get< 0 >( this->m_DblArg[ daIt->first ] ) = vStr.str( );
139 // Compute base filename
140 std::string iname = std::get< 0 >( this->m_StrArg[ "input" ] );
141 this->m_BaseFileName = iname.substr( 0, iname.find_last_of( "." ) );
144 // -------------------------------------------------------------------------
145 void CTBronchi::Process::
149 this->_Vesselness( );
151 this->_MoriLabelling( );
154 // -------------------------------------------------------------------------
155 void CTBronchi::Process::
158 std::string iname = std::get< 0 >( this->m_StrArg[ "input" ] );
159 std::string sname = std::get< 0 >( this->m_StrArg[ "seed_file" ] );
160 std::string seed = std::get< 0 >( this->m_StrArg[ "seed" ] );
161 std::string stype = std::get< 0 >( this->m_StrArg[ "seed_type" ] );
162 if( sname == "" && seed == "" )
163 throw std::runtime_error( "No seed given." );
166 std::ifstream str( sname.c_str( ) );
167 str.seekg( 0, std::ios::end );
168 seed.reserve( str.tellg( ) );
169 str.seekg( 0, std::ios::beg );
171 std::istreambuf_iterator< char >( str ),
172 std::istreambuf_iterator< char >( )
179 std::istringstream sSeed( seed );
182 if( stype == "point" )
183 sSeed >> pnt[ 0 ] >> pnt[ 1 ] >> pnt[ 2 ];
185 sSeed >> idx[ 0 ] >> idx[ 1 ] >> idx[ 2 ];
188 double t = this->m_Input.Load( iname );
190 std::runtime_error( std::string( "Could not read \"" ) + iname + "\"" );
191 std::cout << "\"" << iname << "\" read in " << t << " s." << std::endl;
194 if( stype == "point" )
195 this->m_Input.Get( )->TransformPhysicalPointToIndex( pnt, idx );
197 this->m_Input.Get( )->TransformIndexToPhysicalPoint( idx, pnt );
198 this->m_Seed = TSeed( idx, pnt );
201 // -------------------------------------------------------------------------
202 void CTBronchi::Process::
205 std::string vname = this->m_BaseFileName + "_vesselness.mha";
206 double t = this->m_Vesselness.Load( vname );
213 v << std::get< 0 >( this->m_DblArg[ "vesselness_sigma" ] ) << " "
214 << std::get< 0 >( this->m_DblArg[ "vesselness_alpha1" ] ) << " "
215 << std::get< 0 >( this->m_DblArg[ "vesselness_alpha2" ] );
216 std::istringstream w( v.str( ) );
221 typedef itk::MinimumMaximumImageCalculator< TPixelImage::TImage > _TMinMax;
222 _TMinMax::Pointer minMax = _TMinMax::New( );
223 minMax->SetImage( this->m_Input.Get( ) );
226 // Invert intensities
227 typedef CTBronchi::Filter< itk::InvertIntensityImageFilter< TPixelImage::TImage > > _TInverter;
229 inverter.Get( )->SetInput( this->m_Input.Get( ) );
230 inverter.Get( )->SetMaximum( minMax->GetMaximum( ) );
231 double t1 = inverter.Update( );
233 std::cout << "Inversion executed in " << t1 << " s" << std::endl;
235 // Compute hessian image
236 typedef CTBronchi::Filter< itk::HessianRecursiveGaussianImageFilter< TPixelImage::TImage > > _THessian;
238 hessian.Get( )->SetInput( inverter.Get( )->GetOutput( ) );
239 hessian.Get( )->SetSigma( s );
240 t1 = hessian.Update( );
242 std::cout << "Hessian executed in " << t1 << " s" << std::endl;
245 typedef CTBronchi::Filter< itk::Hessian3DToVesselnessMeasureImageFilter< TScalar > > _TVesselness;
246 _TVesselness vesselness;
247 vesselness.Get( )->SetInput( hessian.Get( )->GetOutput( ) );
248 vesselness.Get( )->SetAlpha1( a1 );
249 vesselness.Get( )->SetAlpha2( a2 );
250 t1 = vesselness.Update( );
252 std::cout << "Hessian measure computed in " << t1 << " s." << std::endl;
254 this->m_Vesselness.Set( vesselness.Get( )->GetOutput( ) );
255 t1 = this->m_Vesselness.Save( vname );
257 std::cout << "\"" << vname << "\" saved in " << t1 << " s." << std::endl;
260 std::cout << "Vesselness computed in " << t << " s." << std::endl;
263 // -------------------------------------------------------------------------
264 void CTBronchi::Process::
267 std::string mname = this->m_BaseFileName + "_mori.mha";
268 double t = this->m_Mori.Load( mname );
275 v << std::get< 0 >( this->m_DblArg[ "mori_min_thr" ] ) << " "
276 << std::get< 0 >( this->m_DblArg[ "mori_kernel" ] ) << " "
277 << std::get< 0 >( this->m_DblArg[ "mori_signal_thr" ] ) << " "
278 << std::get< 0 >( this->m_DblArg[ "mori_signal_influence" ] ) << " "
279 << std::get< 0 >( this->m_DblArg[ "mori_lower" ] ) << " "
280 << std::get< 0 >( this->m_DblArg[ "mori_upper" ] ) << " "
281 << std::get< 0 >( this->m_DblArg[ "mori_delta" ] );
282 std::istringstream w( v.str( ) );
283 TScalar mThr, sKernel, sThr, sInfluence, lower, upper, delta;
284 w >> mThr >> sKernel >> sThr >> sInfluence >> lower >> upper >> delta;
287 typedef CTBronchi::Filter< fpa::Filters::Image::Mori< TPixelImage::TImage, TLabelImage::TImage > > _TMori;
289 mori.Get( )->SetInput( this->m_Input.Get( ) );
290 mori.Get( )->SetSeed( this->m_Seed.second );
291 mori.Get( )->SetInsideValue( this->m_InsideLabel );
292 mori.Get( )->SetOutsideValue( this->m_UndefinedLabel );
293 mori.Get( )->SetMinimumThreshold( mThr );
294 mori.Get( )->SetSignalKernelSize( sKernel );
295 mori.Get( )->SetSignalThreshold( sThr );
296 mori.Get( )->SetSignalInfluence( sInfluence );
297 mori.Get( )->SetThresholds( lower, upper, delta );
298 double t1 = mori.Update( );
300 std::cout << "Segmentation computed in " << t1 << " s." << std::endl;
302 this->m_Mori.Set( mori.Get( )->GetOutput( ) );
303 t1 = this->m_Mori.Save( mname );
305 std::cout << "\"" << mname << "\" saved in " << t1 << " s." << std::endl;
308 std::cout << "Mori segmentation computed in " << t << " s." << std::endl;
311 // -------------------------------------------------------------------------
312 void CTBronchi::Process::
315 std::string mname = this->m_BaseFileName + "_labels.mha";
316 double t = this->m_Labels.Load( mname );
323 v << std::get< 0 >( this->m_DblArg[ "fastrw_thr" ] ) << " "
324 << std::get< 0 >( this->m_DblArg[ "labels_upper_thr" ] );
325 std::istringstream w( v.str( ) );
330 typedef CTBronchi::Filter< CTBronchi::MoriLabelling< TPixelImage::TImage, TLabelImage::TImage, TScalarImage::TImage > > _TLabelling;
331 _TLabelling labelling;
332 labelling.Get( )->SetInput( this->m_Input.Get( ) );
333 labelling.Get( )->SetInputLabels( this->m_Mori.Get( ) );
334 labelling.Get( )->SetInputVesselness( this->m_Vesselness.Get( ) );
335 labelling.Get( )->SetVesselnessThreshold( vThr );
336 labelling.Get( )->SetUpperThreshold( uThr );
337 labelling.Get( )->SetInsideValue( this->m_InsideLabel );
338 labelling.Get( )->SetOutsideValue( this->m_OutsideLabel );
339 labelling.Get( )->SetFillValue( this->m_OutsideLabel );
340 double t1 = labelling.Update( );
342 std::cout << "Labelling computed in " << t1 << " s." << std::endl;
344 this->m_Labels.Set( labelling.Get( )->GetOutput( ) );
345 t1 = this->m_Labels.Save( mname );
347 std::cout << "\"" << mname << "\" saved in " << t1 << " s." << std::endl;
350 std::cout << "Mori labelling computed in " << t << " s." << std::endl;