]> Creatis software - FrontAlgorithms.git/blob - appli/CTArteries/CTArteries.cxx
...
[FrontAlgorithms.git] / appli / CTArteries / CTArteries.cxx
1 // =========================================================================
2 // @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
3 // =========================================================================
4
5 #include "CTArteries.h"
6 #include "ui_CTArteries.h"
7 #include "ui_Parameters.h"
8 #include "FileDialog.h"
9
10 #include <set>
11
12 #include <itkImageFileReader.h>
13 #include <itkImageSeriesReader.h>
14 #include <itkQuadEdgeMesh.h>
15
16 #include <vtkMarchingCubes.h>
17 #include <vtkMarchingSquares.h>
18 #include <vtkPolyDataConnectivityFilter.h>
19 #include <vtkPolyDataMapper.h>
20 #include <vtkProperty.h>
21 #include <vtkRenderer.h>
22 #include <vtkRenderWindow.h>
23 #include <vtkSplineWidget.h>
24
25 #include <QtGui>
26
27 #include <ivq/ITK/CPRImageFilter.h>
28 #include <ivq/VTK/ImageActor.h>
29 #include <ivq/VTK/ImageViewer.h>
30 #include <ivq/VTK/MPRViewers.h>
31 #include <ivq/VTK/PolyDataActor.h>
32 #include <ivq/VTK/SeedWidgetOverImageActor.h>
33 #include <ivq/Qt/DicomSeriesSelectorDialog.h>
34 #include <ivq/Qt/RendererWidget.h>
35
36 #include "algorithms/RandomWalkSegmentation.h"
37
38 // -------------------------------------------------------------------------
39 #define QT_ACTION_CONN( x )                                             \
40   this->connect(                                                        \
41     this->m_UI->a##x, SIGNAL( triggered( ) ), this, SLOT( _s##x( ) )    \
42     )
43
44 // -------------------------------------------------------------------------
45 class ContourCallback
46   : public vtkCommand
47 {
48 public:
49   static ContourCallback* New( )
50     {
51       return( new ContourCallback( ) );
52     }
53   virtual void Execute(
54     vtkObject* caller, unsigned long eId, void* data
55     ) override
56     {
57       ivq::VTK::ImageActor* actor =
58         ivq::VTK::ImageActor::SafeDownCast( caller );
59       if( eId == vtkCommand::InteractionEvent && actor != NULL )
60       {
61         ivq::VTK::ImageViewer* viewer = this->Window->m_UI->Slice->GetViewer( );
62         if( this->Window->m_ContourActor != NULL )
63           viewer->GetRenderer( )->RemoveViewProp( this->Window->m_ContourActor->GetActor( ) );
64
65         double abnds[ 6 ];
66         actor->GetActorBounds( abnds );
67         unsigned int nSlice = actor->GetSliceNumber( );
68         for( unsigned int i = 0; i < 16; ++i )
69         {
70           double w = double( 6.28 ) * double( i ) / double( 16 );
71           CTArteries::TFourier::TPoint v = this->Window->m_Fourier[ nSlice ]( w );
72           this->Window->m_Spline->SetHandlePosition(
73             i, v[ 0 ], v[ 1 ], abnds[ 4 ]
74             );
75
76         } // rof
77         this->Window->m_Spline->SetProjectionPosition(
78           (
79             actor->GetBounds( )[ 4 ] +
80             actor->GetBounds( )[ 5 ]
81             ) / double( 2 )
82           );
83
84
85         this->Window->m_ContourActor =
86           this->Window->m_ContoursActors[ actor->GetSliceNumber( ) ];
87         viewer->GetRenderer( )->AddViewProp( this->Window->m_ContourActor->GetActor( ) );
88         viewer->Render( );
89
90       } // fi
91     }
92
93 protected:
94   ContourCallback( )
95     : vtkCommand( )
96     {
97     }
98   virtual ~ContourCallback( )
99     {
100     }
101
102 private:
103   // Purposely not implemented
104   ContourCallback( const ContourCallback& other );
105   ContourCallback& operator=( const ContourCallback& other );
106 public:
107   CTArteries* Window;
108 };
109
110 // -------------------------------------------------------------------------
111 CTArteries::
112 CTArteries( int argc, char* argv[], QWidget* parent )
113   : Superclass( parent ),
114     m_UI( new Ui::CTArteries ),
115     m_UIParameters( new Ui::Parameters )
116 {
117   this->m_UI->setupUi( this );
118   this->m_DlgParameters = new QDialog( );
119   this->m_UIParameters->setupUi( this->m_DlgParameters );
120
121   // Connect signals with slots
122   QT_ACTION_CONN( Open );
123   QT_ACTION_CONN( Config );
124   QT_ACTION_CONN( Process );
125
126   // Load log
127   if( argc == 3 )
128   {
129     std::string cmd( argv[ 1 ] );
130     std::string fname( argv[ 2 ] );
131     if( cmd == "-log" )
132       this->_ExecuteLog( fname );
133
134   } // fi
135 }
136
137 // -------------------------------------------------------------------------
138 CTArteries::
139 ~CTArteries( )
140 {
141   delete this->m_UI;
142   delete this->m_UIParameters;
143   delete this->m_DlgParameters;
144 }
145
146 // -------------------------------------------------------------------------
147 template< class _TStrings >
148 void CTArteries::
149 _openImage( const _TStrings& fnames )
150 {
151   // Save log
152   std::ofstream str_log( "CTArteries.log" );
153   str_log << fnames.size( ) << std::endl;
154   for( const std::string& s: fnames )
155     str_log << s << std::endl;
156   str_log.close( );
157
158   // Create appropriate reader
159   itk::ImageSource< TImage >::Pointer reader;
160   if( fnames.size( ) == 1 )
161   {
162     itk::ImageFileReader< TImage >::Pointer r =
163       itk::ImageFileReader< TImage >::New( );
164     r->SetFileName( *( fnames.begin( ) ) );
165     reader = r;
166   }
167   else if( fnames.size( ) > 1 )
168   {
169     itk::ImageSeriesReader< TImage >::Pointer r =
170       itk::ImageSeriesReader< TImage >::New( );
171     typename _TStrings::const_iterator i;
172     for( i = fnames.begin( ); i != fnames.end( ); ++i )
173       r->AddFileName( *i );
174     reader = r;
175
176   } // fi
177
178   // Execute reader
179   if( reader.IsNull( ) )
180     return;
181   try
182   {
183     reader->Update( );
184     this->m_Image = reader->GetOutput( );
185     this->m_Image->DisconnectPipeline( );
186   }
187   catch( std::exception& err )
188   {
189     this->m_Image = NULL;
190     QMessageBox::critical( this, "Error opening image", err.what( ) );
191
192   } // yrt
193   this->_showInputImage( );
194 }
195
196 // -------------------------------------------------------------------------
197 void CTArteries::
198 _openDicom( const std::string& dirname )
199 {
200   ivq::Qt::DicomSeriesSelectorDialog dlg( this );
201   dlg.setStartDir( dirname );
202   if( dlg.exec( ) == QDialog::Accepted )
203     this->_openImage( *( dlg.selectedFilenames( ) ) );
204 }
205
206 // -------------------------------------------------------------------------
207 void CTArteries::
208 _showInputImage( )
209 {
210   if( this->m_Image.IsNotNull( ) )
211   {
212     this->m_VTKImage = TVTKImage::New( );
213     this->m_VTKImage->SetInput( this->m_Image );
214     this->m_VTKImage->Update( );
215
216     ivq::VTK::MPRViewers* viewers = this->m_UI->MPR->GetViewers( );
217     viewers->SetInputData( this->m_VTKImage->GetOutput( ) );
218     viewers->SetColorWindow( 1000 );
219     viewers->SetColorLevel( 100 );
220
221     ivq::VTK::ImageViewer* view = viewers->GetView( 2 );
222     this->m_Seeds =
223       vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor >::New( );
224     this->m_Seeds->SetActor( view->GetImageActor( ) );
225     this->m_Seeds->SetInteractor( view->GetRenderWindow( )->GetInteractor( ) );
226
227     viewers->Render( );
228     viewers->ResetCameras( );
229     this->m_Seeds->EnabledOn( );
230     viewers->Render( );
231   }
232   else
233   {
234     this->m_VTKImage = NULL;
235
236   } // fi
237 }
238
239 // -------------------------------------------------------------------------
240 void CTArteries::
241 _process( const std::vector< TImage::PointType >& seeds )
242 {
243   // Save log
244   std::ofstream str_log( "CTArteries.log", std::ios_base::app );
245   str_log << this->m_UIParameters->Beta->value( ) << std::endl;
246   str_log << this->m_UIParameters->Sigma->value( ) << std::endl;
247   str_log << this->m_UIParameters->Radius->value( ) << std::endl;
248   str_log << seeds.size( ) << std::endl;
249   for( TImage::PointType seed: seeds )
250     str_log << seed << std::endl;
251   str_log.close( );
252
253   // Create algorithm
254   typedef RandomWalkSegmentation< TImage, TScalarImage > _TSegmentation;
255   _TSegmentation::Pointer seg = _TSegmentation::New( );
256   seg->SetInput( this->m_Image );
257   seg->SetBeta( this->m_UIParameters->Beta->value( ) );
258   seg->SetSigma( this->m_UIParameters->Sigma->value( ) );
259   seg->SetRadius( this->m_UIParameters->Radius->value( ) );
260   seg->SetStartSeed( seeds[ 0 ] );
261   seg->SetEndSeed( seeds[ 1 ] );
262   for( TImage::PointType seed: seeds )
263     seg->AddSeed( seed );
264   try
265   {
266     seg->DebugOn( );
267     seg->Update( );
268     seg->DebugOff( );
269   }
270   catch( std::exception& err )
271   {
272     QMessageBox::critical(
273       this,
274       QMessageBox::tr( "Error reading image" ),
275       QMessageBox::tr( err.what( ) )
276       );
277     return;
278
279   } // yrt
280   this->m_Seeds->EnabledOff( );
281
282   this->m_Segmentation = seg->GetOutput( );
283   this->m_Axis = seg->GetOutputAxis( );
284   this->m_Segmentation->DisconnectPipeline( );
285   this->m_Axis->DisconnectPipeline( );
286 }
287
288 // -------------------------------------------------------------------------
289 void CTArteries::
290 _prepareQuantification( )
291 {
292   this->m_Contours.clear( );
293   this->m_ContoursActors.clear( );
294   this->m_Fourier.clear( );
295
296   TImage::RegionType ext_region = this->m_CPRImage->GetRequestedRegion( );
297   for( long z = 0; z < ext_region.GetSize( )[ 2 ]; ++z )
298   {
299     TImage::IndexType slc_idx = ext_region.GetIndex( );
300     TImage::SizeType slc_size = ext_region.GetSize( );
301     slc_idx[ 2 ] += z;
302     slc_size[ 2 ] = 1;
303     TImage::RegionType slc_region;
304     slc_region.SetIndex( slc_idx );
305     slc_region.SetSize( slc_size );
306
307     typedef itk::RegionOfInterestImageFilter< TScalarImage, TScalarImage > _TROI;
308     _TROI::Pointer roi = _TROI::New( );
309     roi->SetInput( this->m_CPRSegmentation );
310     roi->SetRegionOfInterest( slc_region );
311
312     /* TODO
313        slc_idx[ 2 ] = 1;
314        slc_size[ 2 ] = 0;
315        slc_region.SetIndex( slc_idx );
316        slc_region.SetSize( slc_size );
317        typedef itk::Image< TBinPixel, 2 > _TBinSlice;
318        typedef itk::ExtractImageFilter< TBinImage, _TBinSlice > _TCollapse;
319        _TCollapse::Pointer collapse = _TCollapse::New( );
320        collapse->SetInput( roi->GetOutput( ) );
321        collapse->SetDirectionCollapseToIdentity( );
322        collapse->SetExtractionRegion( slc_region );
323        collapse->UpdateLargestPossibleRegion( );
324     */
325     typedef TScalarImage _TScalarSlice;
326
327     typedef itk::ImageToVTKImageFilter< _TScalarSlice > _TVTKScalarSlice;
328     _TVTKScalarSlice::Pointer vtk_slice = _TVTKScalarSlice::New( );
329     vtk_slice->SetInput( roi->GetOutput( ) );
330     vtk_slice->Update( );
331
332     double r[ 2 ];
333     vtk_slice->GetOutput( )->GetScalarRange( r );
334
335     vtkSmartPointer< vtkMarchingSquares > ms =
336       vtkSmartPointer< vtkMarchingSquares >::New( );
337     ms->SetInputData( vtk_slice->GetOutput( ) );
338     ms->SetValue( 0, 0 );
339
340     vtkSmartPointer< vtkPolyDataConnectivityFilter > conn =
341       vtkSmartPointer< vtkPolyDataConnectivityFilter >::New( );
342     conn->SetInputConnection( ms->GetOutputPort( ) );
343     conn->SetExtractionModeToClosestPointRegion( );
344     conn->SetClosestPoint( 0, 0, 0 );
345     conn->Update( );
346
347     vtkSmartPointer< vtkPolyData > cnt = vtkSmartPointer< vtkPolyData >::New( );
348     cnt->DeepCopy( conn->GetOutput( ) );
349     this->m_Contours.push_back( cnt );
350
351     typedef itk::QuadEdgeMesh< double, 2 > _TQEMesh;
352     typedef _TQEMesh::PointType _T2DPoint;
353     typedef std::vector< _T2DPoint > _T2DPoints;
354     _T2DPoints points;
355     _TQEMesh::Pointer mesh = _TQEMesh::New( );
356     for( unsigned int i = 0; i < cnt->GetNumberOfPoints( ); ++i )
357     {
358       _T2DPoint pnt;
359       double p[ 3 ];
360       cnt->GetPoint( i, p );
361       pnt[ 0 ] = p[ 0 ];
362       pnt[ 1 ] = p[ 1 ];
363       mesh->AddPoint( pnt );
364
365     } // rof
366     vtkCellArray* lines = cnt->GetLines( );
367     lines->InitTraversal( );
368     vtkIdType* ids = new vtkIdType[ 2 ];
369     vtkIdType npts;
370     while( lines->GetNextCell( npts, ids ) != 0 )
371       mesh->AddEdge( ids[ 0 ], ids[ 1 ] );
372     delete ids;
373     _TQEMesh::QEPrimal* edge = mesh->GetEdge( );
374     if( edge != NULL )
375     {
376       mesh->AddFace( edge );
377       edge = mesh->GetEdge( );
378       for( auto eIt = edge->BeginGeomLnext( ); eIt != edge->EndGeomLnext( ); ++eIt )
379         points.push_back( mesh->GetPoint( *eIt ) );
380
381     } // fi
382
383     TFourier f( points.begin( ), points.end( ), 6 );
384     f.SetOrderingToCounterClockWise( );
385     this->m_Fourier.push_back( f );
386
387     vtkSmartPointer< ivq::VTK::PolyDataActor > actor =
388       vtkSmartPointer< ivq::VTK::PolyDataActor >::New( );
389     actor->SetInputData( cnt );
390     actor->GetMapper( )->ScalarVisibilityOff( );
391     actor->Update( );
392     actor->GetProperty( )->SetColor( 1, 0, 0 );
393     actor->GetProperty( )->SetLineWidth( 2 );
394     this->m_ContoursActors.push_back( actor );
395
396   } // rof
397
398   ivq::VTK::ImageViewer* slice_view = this->m_UI->Slice->GetViewer( );
399   vtkSmartPointer< ContourCallback > cbk =
400     vtkSmartPointer< ContourCallback >::New( );
401   cbk->Window = this;
402   slice_view->GetImageActor( )->AddObserver( vtkCommand::InteractionEvent, cbk );
403   this->m_ContourActor = NULL;
404
405   this->m_Spline = vtkSmartPointer< vtkSplineWidget >::New( );
406   this->m_Spline->SetCurrentRenderer( slice_view->GetRenderer( ) );
407   this->m_Spline->SetDefaultRenderer( slice_view->GetRenderer( ) );
408   this->m_Spline->SetInputData( slice_view->GetInput( ) );
409   this->m_Spline->SetProp3D( slice_view->GetImageActor( ) );
410   this->m_Spline->SetInteractor( slice_view->GetRenderWindow( )->GetInteractor( ) );
411   double bnds[ 6 ];
412   slice_view->GetInput( )->GetBounds( bnds );
413   this->m_Spline->PlaceWidget(
414     bnds[ 0 ], bnds[ 1 ],
415     bnds[ 2 ], bnds[ 3 ],
416     bnds[ 4 ], bnds[ 5 ]
417     );
418   this->m_Spline->ProjectToPlaneOn( );
419   this->m_Spline->SetProjectionNormalToZAxes( );
420   this->m_Spline->SetProjectionPosition(
421     (
422       slice_view->GetImageActor( )->GetBounds( )[ 4 ] +
423       slice_view->GetImageActor( )->GetBounds( )[ 5 ]
424       ) / double( 2 )
425     );
426   this->m_Spline->SetHandleSize( 0.005 );
427   this->m_Spline->ClosedOn( );
428   this->m_Spline->SetNumberOfHandles( 16 );
429   this->m_Spline->EnabledOn( );
430
431   QVector< double > xdata, dmindata, dmaxdata, areadata;
432   double data[ 3 ];
433   for( unsigned int i = 0; i < this->m_Fourier.size( ); ++i )
434   {
435     double a, b, t, p;
436     this->m_Fourier[ i ].GetEllipse( 1, a, b, t, p );
437     double area = this->m_Fourier[ i ].GetArea( );
438
439     xdata.push_back( double( i ) );
440     dmindata.push_back( b );
441     dmaxdata.push_back( a );
442     areadata.push_back( area );
443
444   } // rof
445   this->m_UI->Plot->addGraph( this->m_UI->Plot->xAxis, this->m_UI->Plot->yAxis );
446   this->m_UI->Plot->graph( 0 )->setPen( QPen( QColor( 255, 0, 0 ) ) );
447   this->m_UI->Plot->graph( 0 )->setName( "Minimum diameter (mm)" );
448   this->m_UI->Plot->graph( 0 )->setData( xdata, dmindata );
449
450   this->m_UI->Plot->addGraph( this->m_UI->Plot->xAxis, this->m_UI->Plot->yAxis );
451   this->m_UI->Plot->graph( 1 )->setPen( QPen( QColor( 0, 255, 0 ) ) );
452   this->m_UI->Plot->graph( 1 )->setName( "Maximum diameter (mm)" );
453   this->m_UI->Plot->graph( 1 )->setData( xdata, dmaxdata );
454
455   this->m_UI->Plot->addGraph( this->m_UI->Plot->xAxis, this->m_UI->Plot->yAxis2 );
456   this->m_UI->Plot->graph( 2 )->setPen( QPen( QColor( 0, 0, 255 ) ) );
457   this->m_UI->Plot->graph( 2 )->setName( "Area (mm2)" );
458   this->m_UI->Plot->graph( 2 )->setData( xdata, areadata );
459
460   this->m_UI->Plot->xAxis->setLabel( "Position" );
461   this->m_UI->Plot->yAxis->setLabel( "Diameters (mm)" );
462   this->m_UI->Plot->yAxis2->setLabel( "Areas (mm2)" );
463
464   this->m_UI->Plot->legend->setVisible( true );
465   this->m_UI->Plot->xAxis->setVisible( true );
466   this->m_UI->Plot->yAxis->setVisible( true );
467   this->m_UI->Plot->yAxis2->setVisible( true );
468
469   this->m_UI->Plot->rescaleAxes( );
470   this->m_UI->Plot->replot( );
471 }
472
473 // -------------------------------------------------------------------------
474 void CTArteries::
475 _showProcessResults( )
476 {
477   if( this->m_Segmentation.IsNull( ) || this->m_Axis.IsNull( ) )
478     return;
479
480   this->m_VTKSegmentation = TVTKScalarImage::New( );
481   this->m_VTKSegmentation->SetInput( this->m_Segmentation );
482   this->m_VTKSegmentation->Update( );
483
484   // Show surface
485   vtkImageData* seg = this->m_VTKSegmentation->GetOutput( );
486   double r[ 2 ];
487   seg->GetScalarRange( r );
488   vtkSmartPointer< vtkMarchingCubes > mc =
489     vtkSmartPointer< vtkMarchingCubes >::New( );
490   mc->SetInputData( seg );
491   mc->SetValue( 0, 0 );
492   mc->Update( );
493   this->m_Surface = vtkSmartPointer< ivq::VTK::PolyDataActor >::New( );
494   this->m_Surface->SetInputConnection( mc->GetOutputPort( ) );
495   this->m_Surface->Update( );
496
497   // Prepare curve
498   this->m_Curve = TCurve::New( );
499   for( unsigned int i = 0; i < this->m_Axis->GetSize( ); ++i )
500     this->m_Curve->AddPoint( this->m_Axis->GetPoint( i ) );
501   this->m_Curve->Smooth( 2 );
502
503   // Compute CPRs
504   this->_CPR(
505     this->m_CPRImage, this->m_VTKCPRImage,
506     this->m_Image, this->m_Curve
507     );
508   this->_CPR(
509     this->m_CPRSegmentation, this->m_VTKCPRSegmentation,
510     this->m_Segmentation, this->m_Curve
511     );
512
513   // Show all data
514   vtkRenderer* renderer =
515     this->m_UI->MPR->GetRendererWidget( )->GetRenderer( );
516   renderer->AddViewProp( this->m_Surface->GetActor( ) );
517   renderer->Render( );
518   renderer->ResetCamera( );
519   this->m_UI->MPR->GetRendererWidget( )->GetRenderWindow( )->Render( );
520
521   ivq::VTK::ImageViewer* cpr_view = this->m_UI->CPR->GetViewer( );
522   ivq::VTK::ImageViewer* slice_view = this->m_UI->Slice->GetViewer( );
523
524   cpr_view->SetInputData( this->m_VTKCPRImage->GetOutput( ) );
525   cpr_view->SetColorWindow( 1000 );
526   cpr_view->SetColorLevel( 100 );
527   cpr_view->SetSliceOrientationToXZ( );
528   cpr_view->Render( );
529
530   slice_view->SetInputData( this->m_VTKCPRImage->GetOutput( ) );
531   slice_view->SetColorWindow( 1000 );
532   slice_view->SetColorLevel( 100 );
533   slice_view->SetSliceOrientationToXY( );
534   slice_view->Render( );
535
536   this->_prepareQuantification( );
537 }
538
539 // -------------------------------------------------------------------------
540 void CTArteries::
541 _ExecuteLog( const std::string& fname )
542 {
543   std::ifstream str_log( fname.c_str( ) );
544   if( str_log )
545   {
546     str_log.close( );
547
548   } // fi
549 }
550
551 // -------------------------------------------------------------------------
552 void CTArteries::
553 _sOpen( )
554 {
555   FileDialog dlg( this );
556   dlg.setNameFilter(
557     "Medical images (*.mhd *.dcm);;Other images (*.png *.jpg *.bmp);;\
558 All files (*)"
559     );
560   if( dlg.exec( ) == QDialog::Accepted )
561   {
562     std::set< std::string > filenames, dirnames;
563     QStringList names = dlg.selectedFiles( );
564     for( QString name: names )
565     {
566       QFileInfo info( name );
567       if( info.isDir( ) )
568         dirnames.insert( name.toStdString( ) );
569       else
570         filenames.insert( name.toStdString( ) );
571
572     } // rof
573
574     if( dirnames.size( ) == 1 && filenames.size( ) == 0 )
575       this->_openDicom( *( dirnames.begin( ) ) );
576     else if( dirnames.size( ) == 0 && filenames.size( ) > 0 )
577       this->_openImage( filenames );
578     else
579       QMessageBox::critical(
580         this,
581         "Error opening image",
582         "Directory - files mixed up, don't know what to do."
583         );
584
585   } // fi
586 }
587
588 // -------------------------------------------------------------------------
589 void CTArteries::
590 _sConfig( )
591 {
592   this->m_DlgParameters->exec( );
593 }
594
595 // -------------------------------------------------------------------------
596 void CTArteries::
597 _sProcess( )
598 {
599   // Get seeds
600   typedef ivq::VTK::SeedWidgetOverImageActor::TSeeds _TSeeds;
601   if( this->m_Image.IsNull( ) || this->m_Seeds.GetPointer( ) == NULL )
602   {
603     QMessageBox::critical( this, "Error processing", "No valid input image." );
604     return;
605
606   } // fi
607   std::vector< TImage::PointType > seeds;
608   for( _TSeeds::value_type sValue: this->m_Seeds->GetSeeds( ) )
609   {
610     for( unsigned int i = 0; i < sValue.second.size( ); i += 3 )
611     {
612       TImage::PointType pnt;
613       pnt[ 0 ] = sValue.second[ i + 0 ];
614       pnt[ 1 ] = sValue.second[ i + 1 ];
615       pnt[ 2 ] = sValue.second[ i + 2 ];
616       seeds.push_back( pnt );
617
618     } // rof
619
620   } // rof
621   if( seeds.size( ) < 2 )
622   {
623     QMessageBox::critical( this, "Error processing", "Not enough seeds." );
624     return;
625
626   } // fi
627   this->_process( seeds );
628   this->_showProcessResults( );
629 }
630
631 // -------------------------------------------------------------------------
632 template< class _TImagePtr, class _TVTKImagePtr, class _TCurvePtr >
633 void CTArteries::
634 _CPR(
635   _TImagePtr& output, _TVTKImagePtr& vtk_output,
636   const _TImagePtr& input, const _TCurvePtr& curve
637   )
638 {
639   typedef typename _TImagePtr::ObjectType _TImage;
640   typedef typename _TCurvePtr::ObjectType _TCurve;
641   typedef ivq::ITK::CPRImageFilter< _TImage, _TCurve > _TFilter;
642
643   typename _TFilter::Pointer cpr = _TFilter::New( );
644   cpr->SetInput( input );
645   cpr->SetCurve( curve );
646   cpr->SetSliceRadius( 40 );
647   cpr->Update( );
648   output = cpr->GetOutput( );
649   output->DisconnectPipeline( );
650
651   vtk_output = _TVTKImagePtr::ObjectType::New( );
652   vtk_output->SetInput( output );
653   vtk_output->Update( );
654 }
655
656 // -------------------------------------------------------------------------
657 #include <QApplication>
658
659 int main( int argc, char* argv[] )
660 {
661   QApplication a( argc, argv );
662   CTArteries w( argc, argv );
663   w.show( );
664   return( a.exec( ) );
665 }
666
667 // eof - $RCSfile$