1 // =========================================================================
2 // @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
3 // =========================================================================
5 #include "CTArteries.h"
6 #include "ui_CTArteries.h"
7 #include "ui_Parameters.h"
8 #include "FileDialog.h"
12 #include <itkImageFileReader.h>
13 #include <itkImageSeriesReader.h>
15 #include <vtkMarchingCubes.h>
16 #include <vtkRenderer.h>
17 #include <vtkRenderWindow.h>
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>
29 #include "algorithms/RandomWalkSegmentation.h"
31 // -------------------------------------------------------------------------
32 #define QT_ACTION_CONN( x ) \
34 this->m_UI->a##x, SIGNAL( triggered( ) ), this, SLOT( _s##x( ) ) \
37 // -------------------------------------------------------------------------
39 CTArteries( int argc, char* argv[], QWidget* parent )
40 : Superclass( parent ),
41 m_UI( new Ui::CTArteries ),
42 m_UIParameters( new Ui::Parameters )
44 this->m_UI->setupUi( this );
45 this->m_DlgParameters = new QDialog( );
46 this->m_UIParameters->setupUi( this->m_DlgParameters );
48 // Connect signals with slots
49 QT_ACTION_CONN( Open );
50 QT_ACTION_CONN( Config );
51 QT_ACTION_CONN( Process );
54 // -------------------------------------------------------------------------
59 delete this->m_UIParameters;
60 delete this->m_DlgParameters;
63 // -------------------------------------------------------------------------
64 template< class _TStrings >
66 _openImage( const _TStrings& fnames )
68 // Create appropriate reader
69 itk::ImageSource< TImage >::Pointer reader;
70 if( fnames.size( ) == 1 )
72 itk::ImageFileReader< TImage >::Pointer r =
73 itk::ImageFileReader< TImage >::New( );
74 r->SetFileName( *( fnames.begin( ) ) );
77 else if( fnames.size( ) > 1 )
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 )
89 if( reader.IsNull( ) )
94 this->m_Image = reader->GetOutput( );
95 this->m_Image->DisconnectPipeline( );
97 catch( std::exception& err )
100 QMessageBox::critical( this, "Error opening image", err.what( ) );
103 this->_showInputImage( );
106 // -------------------------------------------------------------------------
108 _openDicom( const std::string& dirname )
110 ivq::Qt::DicomSeriesSelectorDialog dlg( this );
111 dlg.setStartDir( dirname );
112 if( dlg.exec( ) == QDialog::Accepted )
113 this->_openImage( *( dlg.selectedFilenames( ) ) );
116 // -------------------------------------------------------------------------
120 if( this->m_Image.IsNotNull( ) )
122 this->m_VTKImage = TVTKImage::New( );
123 this->m_VTKImage->SetInput( this->m_Image );
124 this->m_VTKImage->Update( );
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 );
131 ivq::VTK::ImageViewer* view = viewers->GetView( 2 );
133 vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor >::New( );
134 this->m_Seeds->SetActor( view->GetImageActor( ) );
135 this->m_Seeds->SetInteractor( view->GetRenderWindow( )->GetInteractor( ) );
138 viewers->ResetCameras( );
139 this->m_Seeds->EnabledOn( );
144 this->m_VTKImage = NULL;
149 // -------------------------------------------------------------------------
154 typedef ivq::VTK::SeedWidgetOverImageActor::TSeeds _TSeeds;
155 if( this->m_Image.IsNull( ) || this->m_Seeds.GetPointer( ) == NULL )
157 QMessageBox::critical( this, "Error processing", "No valid input image." );
161 std::vector< TImage::PointType > seeds;
162 for( _TSeeds::value_type sValue: this->m_Seeds->GetSeeds( ) )
164 for( unsigned int i = 0; i < sValue.second.size( ); i += 3 )
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 );
175 if( seeds.size( ) < 2 )
177 QMessageBox::critical( this, "Error processing", "Not enough seeds." );
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 );
197 catch( std::exception& err )
199 QMessageBox::critical(
201 QMessageBox::tr( "Error reading image" ),
202 QMessageBox::tr( err.what( ) )
207 this->m_Seeds->EnabledOff( );
209 this->m_Segmentation = seg->GetOutput( );
210 this->m_Axis = seg->GetOutputAxis( );
211 this->m_Segmentation->DisconnectPipeline( );
212 this->m_Axis->DisconnectPipeline( );
215 // -------------------------------------------------------------------------
217 _showProcessResults( )
219 if( this->m_Segmentation.IsNull( ) || this->m_Axis.IsNull( ) )
222 this->m_VTKSegmentation = TVTKScalarImage::New( );
223 this->m_VTKSegmentation->SetInput( this->m_Segmentation );
224 this->m_VTKSegmentation->Update( );
227 vtkImageData* seg = this->m_VTKSegmentation->GetOutput( );
229 seg->GetScalarRange( r );
230 vtkSmartPointer< vtkMarchingCubes > mc =
231 vtkSmartPointer< vtkMarchingCubes >::New( );
232 mc->SetInputData( seg );
233 mc->SetValue( 0, 0 );
235 this->m_Surface = vtkSmartPointer< ivq::VTK::PolyDataActor >::New( );
236 this->m_Surface->SetInputConnection( mc->GetOutputPort( ) );
237 this->m_Surface->Update( );
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 );
246 vtkRenderer* renderer =
247 this->m_UI->MPR->GetRendererWidget( )->GetRenderer( );
248 renderer->AddViewProp( this->m_Surface->GetActor( ) );
250 renderer->ResetCamera( );
251 this->m_UI->MPR->GetRendererWidget( )->GetRenderWindow( )->Render( );
254 // -------------------------------------------------------------------------
258 FileDialog dlg( this );
260 "Medical images (*.mhd *.dcm);;Other images (*.png *.jpg *.bmp);;\
263 if( dlg.exec( ) == QDialog::Accepted )
265 std::set< std::string > filenames, dirnames;
266 QStringList names = dlg.selectedFiles( );
267 for( QString name: names )
269 QFileInfo info( name );
271 dirnames.insert( name.toStdString( ) );
273 filenames.insert( name.toStdString( ) );
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 );
282 QMessageBox::critical(
284 "Error opening image",
285 "Directory - files mixed up, don't know what to do."
291 // -------------------------------------------------------------------------
295 this->m_DlgParameters->exec( );
298 // -------------------------------------------------------------------------
303 this->_showProcessResults( );
306 // -------------------------------------------------------------------------
307 #include <QApplication>
309 int main( int argc, char* argv[] )
311 QApplication a( argc, argv );
312 CTArteries w( argc, argv );