]> Creatis software - FrontAlgorithms.git/blob - appli/CTArteries/CTArteries.cxx
2eec3c2fb588b05a15a7423ac99d0c5200c4f059
[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
15 #include <vtkMarchingCubes.h>
16 #include <vtkRenderer.h>
17 #include <vtkRenderWindow.h>
18
19 #include <QtGui>
20
21 #include <ivq/ITK/CPRImageFilter.h>
22 #include <ivq/VTK/ImageViewer.h>
23 #include <ivq/VTK/MPRViewers.h>
24 #include <ivq/VTK/PolyDataActor.h>
25 #include <ivq/VTK/SeedWidgetOverImageActor.h>
26 #include <ivq/Qt/DicomSeriesSelectorDialog.h>
27 #include <ivq/Qt/RendererWidget.h>
28
29 #include "algorithms/RandomWalkSegmentation.h"
30
31 // -------------------------------------------------------------------------
32 #define QT_ACTION_CONN( x )                                             \
33   this->connect(                                                        \
34     this->m_UI->a##x, SIGNAL( triggered( ) ), this, SLOT( _s##x( ) )    \
35     )
36
37 // -------------------------------------------------------------------------
38 CTArteries::
39 CTArteries( int argc, char* argv[], QWidget* parent )
40   : Superclass( parent ),
41     m_UI( new Ui::CTArteries ),
42     m_UIParameters( new Ui::Parameters )
43 {
44   this->m_UI->setupUi( this );
45   this->m_DlgParameters = new QDialog( );
46   this->m_UIParameters->setupUi( this->m_DlgParameters );
47
48   // Connect signals with slots
49   QT_ACTION_CONN( Open );
50   QT_ACTION_CONN( Config );
51   QT_ACTION_CONN( Process );
52 }
53
54 // -------------------------------------------------------------------------
55 CTArteries::
56 ~CTArteries( )
57 {
58   delete this->m_UI;
59   delete this->m_UIParameters;
60   delete this->m_DlgParameters;
61 }
62
63 // -------------------------------------------------------------------------
64 template< class _TStrings >
65 void CTArteries::
66 _openImage( const _TStrings& fnames )
67 {
68   // Create appropriate reader
69   itk::ImageSource< TImage >::Pointer reader;
70   if( fnames.size( ) == 1 )
71   {
72     itk::ImageFileReader< TImage >::Pointer r =
73       itk::ImageFileReader< TImage >::New( );
74     r->SetFileName( *( fnames.begin( ) ) );
75     reader = r;
76   }
77   else if( fnames.size( ) > 1 )
78   {
79     itk::ImageSeriesReader< TImage >::Pointer r =
80       itk::ImageSeriesReader< TImage >::New( );
81     typename _TStrings::const_iterator i;
82     for( i = fnames.begin( ); i != fnames.end( ); ++i )
83       r->AddFileName( *i );
84     reader = r;
85
86   } // fi
87
88   // Execute reader
89   if( reader.IsNull( ) )
90     return;
91   try
92   {
93     reader->Update( );
94     this->m_Image = reader->GetOutput( );
95     this->m_Image->DisconnectPipeline( );
96   }
97   catch( std::exception& err )
98   {
99     this->m_Image = NULL;
100     QMessageBox::critical( this, "Error opening image", err.what( ) );
101
102   } // yrt
103   this->_showInputImage( );
104 }
105
106 // -------------------------------------------------------------------------
107 void CTArteries::
108 _openDicom( const std::string& dirname )
109 {
110   ivq::Qt::DicomSeriesSelectorDialog dlg( this );
111   dlg.setStartDir( dirname );
112   if( dlg.exec( ) == QDialog::Accepted )
113     this->_openImage( *( dlg.selectedFilenames( ) ) );
114 }
115
116 // -------------------------------------------------------------------------
117 void CTArteries::
118 _showInputImage( )
119 {
120   if( this->m_Image.IsNotNull( ) )
121   {
122     this->m_VTKImage = TVTKImage::New( );
123     this->m_VTKImage->SetInput( this->m_Image );
124     this->m_VTKImage->Update( );
125
126     ivq::VTK::MPRViewers* viewers = this->m_UI->MPR->GetViewers( );
127     viewers->SetInputData( this->m_VTKImage->GetOutput( ) );
128     viewers->SetColorWindow( 1000 );
129     viewers->SetColorLevel( 100 );
130
131     ivq::VTK::ImageViewer* view = viewers->GetView( 2 );
132     this->m_Seeds =
133       vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor >::New( );
134     this->m_Seeds->SetActor( view->GetImageActor( ) );
135     this->m_Seeds->SetInteractor( view->GetRenderWindow( )->GetInteractor( ) );
136
137     viewers->Render( );
138     viewers->ResetCameras( );
139     this->m_Seeds->EnabledOn( );
140     viewers->Render( );
141   }
142   else
143   {
144     this->m_VTKImage = NULL;
145
146   } // fi
147 }
148
149 // -------------------------------------------------------------------------
150 void CTArteries::
151 _process( )
152 {
153   // Get seeds
154   typedef ivq::VTK::SeedWidgetOverImageActor::TSeeds _TSeeds;
155   if( this->m_Image.IsNull( ) || this->m_Seeds.GetPointer( ) == NULL )
156   {
157     QMessageBox::critical( this, "Error processing", "No valid input image." );
158     return;
159
160   } // fi
161   std::vector< TImage::PointType > seeds;
162   for( _TSeeds::value_type sValue: this->m_Seeds->GetSeeds( ) )
163   {
164     for( unsigned int i = 0; i < sValue.second.size( ); i += 3 )
165     {
166       TImage::PointType pnt;
167       pnt[ 0 ] = sValue.second[ i + 0 ];
168       pnt[ 1 ] = sValue.second[ i + 1 ];
169       pnt[ 2 ] = sValue.second[ i + 2 ];
170       seeds.push_back( pnt );
171
172     } // rof
173
174   } // rof
175   if( seeds.size( ) < 2 )
176   {
177     QMessageBox::critical( this, "Error processing", "Not enough seeds." );
178     return;
179
180   } // fi
181
182   // Create algorithm
183   typedef RandomWalkSegmentation< TImage, TScalarImage > _TSegmentation;
184   _TSegmentation::Pointer seg = _TSegmentation::New( );
185   seg->SetInput( this->m_Image );
186   seg->SetBeta( this->m_UIParameters->Beta->value( ) );
187   seg->SetSigma( this->m_UIParameters->Sigma->value( ) );
188   seg->SetRadius( this->m_UIParameters->Radius->value( ) );
189   seg->SetStartSeed( seeds[ 0 ] );
190   seg->SetEndSeed( seeds[ 1 ] );
191   for( TImage::PointType seed: seeds )
192     seg->AddSeed( seed );
193   try
194   {
195     seg->Update( );
196   }
197   catch( std::exception& err )
198   {
199     QMessageBox::critical(
200       this,
201       QMessageBox::tr( "Error reading image" ),
202       QMessageBox::tr( err.what( ) )
203       );
204     return;
205
206   } // yrt
207   this->m_Seeds->EnabledOff( );
208
209   this->m_Segmentation = seg->GetOutput( );
210   this->m_Axis = seg->GetOutputAxis( );
211   this->m_Segmentation->DisconnectPipeline( );
212   this->m_Axis->DisconnectPipeline( );
213 }
214
215 // -------------------------------------------------------------------------
216 void CTArteries::
217 _showProcessResults( )
218 {
219   if( this->m_Segmentation.IsNull( ) || this->m_Axis.IsNull( ) )
220     return;
221
222   this->m_VTKSegmentation = TVTKScalarImage::New( );
223   this->m_VTKSegmentation->SetInput( this->m_Segmentation );
224   this->m_VTKSegmentation->Update( );
225
226   // Show surface
227   vtkImageData* seg = this->m_VTKSegmentation->GetOutput( );
228   double r[ 2 ];
229   seg->GetScalarRange( r );
230   vtkSmartPointer< vtkMarchingCubes > mc =
231     vtkSmartPointer< vtkMarchingCubes >::New( );
232   mc->SetInputData( seg );
233   mc->SetValue( 0, 0 );
234   mc->Update( );
235   this->m_Surface = vtkSmartPointer< ivq::VTK::PolyDataActor >::New( );
236   this->m_Surface->SetInputConnection( mc->GetOutputPort( ) );
237   this->m_Surface->Update( );
238
239   // Prepare curve
240   this->m_Curve = TCurve::New( );
241   for( unsigned int i = 0; i < this->m_Axis->GetSize( ); ++i )
242     this->m_Curve->AddPoint( this->m_Axis->GetPoint( i ) );
243   this->m_Curve->Smooth( 2 );
244
245   // Show all data
246   vtkRenderer* renderer =
247     this->m_UI->MPR->GetRendererWidget( )->GetRenderer( );
248   renderer->AddViewProp( this->m_Surface->GetActor( ) );
249   renderer->Render( );
250   renderer->ResetCamera( );
251   this->m_UI->MPR->GetRendererWidget( )->GetRenderWindow( )->Render( );
252 }
253
254 // -------------------------------------------------------------------------
255 void CTArteries::
256 _sOpen( )
257 {
258   FileDialog dlg( this );
259   dlg.setNameFilter(
260     "Medical images (*.mhd *.dcm);;Other images (*.png *.jpg *.bmp);;\
261 All files (*)"
262     );
263   if( dlg.exec( ) == QDialog::Accepted )
264   {
265     std::set< std::string > filenames, dirnames;
266     QStringList names = dlg.selectedFiles( );
267     for( QString name: names )
268     {
269       QFileInfo info( name );
270       if( info.isDir( ) )
271         dirnames.insert( name.toStdString( ) );
272       else
273         filenames.insert( name.toStdString( ) );
274
275     } // rof
276
277     if( dirnames.size( ) == 1 && filenames.size( ) == 0 )
278       this->_openDicom( *( dirnames.begin( ) ) );
279     else if( dirnames.size( ) == 0 && filenames.size( ) > 0 )
280       this->_openImage( filenames );
281     else
282       QMessageBox::critical(
283         this,
284         "Error opening image",
285         "Directory - files mixed up, don't know what to do."
286         );
287
288   } // fi
289 }
290
291 // -------------------------------------------------------------------------
292 void CTArteries::
293 _sConfig( )
294 {
295   this->m_DlgParameters->exec( );
296 }
297
298 // -------------------------------------------------------------------------
299 void CTArteries::
300 _sProcess( )
301 {
302   this->_process( );
303   this->_showProcessResults( );
304 }
305
306 // -------------------------------------------------------------------------
307 #include <QApplication>
308
309 int main( int argc, char* argv[] )
310 {
311   QApplication a( argc, argv );
312   CTArteries w( argc, argv );
313   w.show( );
314   return( a.exec( ) );
315 }
316
317 // eof - $RCSfile$