// ========================================================================= // @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) // ========================================================================= #include "CTArteries.h" #include "ui_CTArteries.h" #include "ui_Parameters.h" #include "FileDialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "algorithms/RandomWalkSegmentation.h" // ------------------------------------------------------------------------- #define QT_ACTION_CONN( x ) \ this->connect( \ this->m_UI->a##x, SIGNAL( triggered( ) ), this, SLOT( _s##x( ) ) \ ) // ------------------------------------------------------------------------- CTArteries:: CTArteries( int argc, char* argv[], QWidget* parent ) : Superclass( parent ), m_UI( new Ui::CTArteries ), m_UIParameters( new Ui::Parameters ) { this->m_UI->setupUi( this ); this->m_DlgParameters = new QDialog( ); this->m_UIParameters->setupUi( this->m_DlgParameters ); // Connect signals with slots QT_ACTION_CONN( Open ); QT_ACTION_CONN( Config ); QT_ACTION_CONN( Process ); } // ------------------------------------------------------------------------- CTArteries:: ~CTArteries( ) { delete this->m_UI; delete this->m_UIParameters; delete this->m_DlgParameters; } // ------------------------------------------------------------------------- template< class _TStrings > void CTArteries:: _openImage( const _TStrings& fnames ) { // Create appropriate reader itk::ImageSource< TImage >::Pointer reader; if( fnames.size( ) == 1 ) { itk::ImageFileReader< TImage >::Pointer r = itk::ImageFileReader< TImage >::New( ); r->SetFileName( *( fnames.begin( ) ) ); reader = r; } else if( fnames.size( ) > 1 ) { itk::ImageSeriesReader< TImage >::Pointer r = itk::ImageSeriesReader< TImage >::New( ); typename _TStrings::const_iterator i; for( i = fnames.begin( ); i != fnames.end( ); ++i ) r->AddFileName( *i ); reader = r; } // fi // Execute reader if( reader.IsNull( ) ) return; try { reader->Update( ); this->m_Image = reader->GetOutput( ); this->m_Image->DisconnectPipeline( ); } catch( std::exception& err ) { this->m_Image = NULL; QMessageBox::critical( this, "Error opening image", err.what( ) ); } // yrt this->_showInputImage( ); } // ------------------------------------------------------------------------- void CTArteries:: _openDicom( const std::string& dirname ) { ivq::Qt::DicomSeriesSelectorDialog dlg( this ); dlg.setStartDir( dirname ); if( dlg.exec( ) == QDialog::Accepted ) this->_openImage( *( dlg.selectedFilenames( ) ) ); } // ------------------------------------------------------------------------- void CTArteries:: _showInputImage( ) { if( this->m_Image.IsNotNull( ) ) { this->m_VTKImage = TVTKImage::New( ); this->m_VTKImage->SetInput( this->m_Image ); this->m_VTKImage->Update( ); ivq::VTK::MPRViewers* viewers = this->m_UI->MPR->GetViewers( ); viewers->SetInputData( this->m_VTKImage->GetOutput( ) ); viewers->SetColorWindow( 1000 ); viewers->SetColorLevel( 100 ); ivq::VTK::ImageViewer* view = viewers->GetView( 2 ); this->m_Seeds = vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor >::New( ); this->m_Seeds->SetActor( view->GetImageActor( ) ); this->m_Seeds->SetInteractor( view->GetRenderWindow( )->GetInteractor( ) ); viewers->Render( ); viewers->ResetCameras( ); this->m_Seeds->EnabledOn( ); viewers->Render( ); } else { this->m_VTKImage = NULL; } // fi } // ------------------------------------------------------------------------- void CTArteries:: _process( ) { // Get seeds typedef ivq::VTK::SeedWidgetOverImageActor::TSeeds _TSeeds; if( this->m_Image.IsNull( ) || this->m_Seeds.GetPointer( ) == NULL ) { QMessageBox::critical( this, "Error processing", "No valid input image." ); return; } // fi std::vector< TImage::PointType > seeds; for( _TSeeds::value_type sValue: this->m_Seeds->GetSeeds( ) ) { for( unsigned int i = 0; i < sValue.second.size( ); i += 3 ) { TImage::PointType pnt; pnt[ 0 ] = sValue.second[ i + 0 ]; pnt[ 1 ] = sValue.second[ i + 1 ]; pnt[ 2 ] = sValue.second[ i + 2 ]; seeds.push_back( pnt ); } // rof } // rof if( seeds.size( ) < 2 ) { QMessageBox::critical( this, "Error processing", "Not enough seeds." ); return; } // fi // Create algorithm typedef RandomWalkSegmentation< TImage, TScalarImage > _TSegmentation; _TSegmentation::Pointer seg = _TSegmentation::New( ); seg->SetInput( this->m_Image ); seg->SetBeta( this->m_UIParameters->Beta->value( ) ); seg->SetSigma( this->m_UIParameters->Sigma->value( ) ); seg->SetRadius( this->m_UIParameters->Radius->value( ) ); seg->SetStartSeed( seeds[ 0 ] ); seg->SetEndSeed( seeds[ 1 ] ); for( TImage::PointType seed: seeds ) seg->AddSeed( seed ); try { seg->Update( ); } catch( std::exception& err ) { QMessageBox::critical( this, QMessageBox::tr( "Error reading image" ), QMessageBox::tr( err.what( ) ) ); return; } // yrt this->m_Seeds->EnabledOff( ); this->m_Segmentation = seg->GetOutput( ); this->m_Axis = seg->GetOutputAxis( ); this->m_Segmentation->DisconnectPipeline( ); this->m_Axis->DisconnectPipeline( ); } // ------------------------------------------------------------------------- void CTArteries:: _showProcessResults( ) { if( this->m_Segmentation.IsNull( ) || this->m_Axis.IsNull( ) ) return; this->m_VTKSegmentation = TVTKScalarImage::New( ); this->m_VTKSegmentation->SetInput( this->m_Segmentation ); this->m_VTKSegmentation->Update( ); // Show surface vtkImageData* seg = this->m_VTKSegmentation->GetOutput( ); double r[ 2 ]; seg->GetScalarRange( r ); vtkSmartPointer< vtkMarchingCubes > mc = vtkSmartPointer< vtkMarchingCubes >::New( ); mc->SetInputData( seg ); mc->SetValue( 0, 0 ); mc->Update( ); this->m_Surface = vtkSmartPointer< ivq::VTK::PolyDataActor >::New( ); this->m_Surface->SetInputConnection( mc->GetOutputPort( ) ); this->m_Surface->Update( ); // Prepare curve this->m_Curve = TCurve::New( ); for( unsigned int i = 0; i < this->m_Axis->GetSize( ); ++i ) this->m_Curve->AddPoint( this->m_Axis->GetPoint( i ) ); this->m_Curve->Smooth( 2 ); // Show all data vtkRenderer* renderer = this->m_UI->MPR->GetRendererWidget( )->GetRenderer( ); renderer->AddViewProp( this->m_Surface->GetActor( ) ); renderer->Render( ); renderer->ResetCamera( ); this->m_UI->MPR->GetRendererWidget( )->GetRenderWindow( )->Render( ); } // ------------------------------------------------------------------------- void CTArteries:: _sOpen( ) { FileDialog dlg( this ); dlg.setNameFilter( "Medical images (*.mhd *.dcm);;Other images (*.png *.jpg *.bmp);;\ All files (*)" ); if( dlg.exec( ) == QDialog::Accepted ) { std::set< std::string > filenames, dirnames; QStringList names = dlg.selectedFiles( ); for( QString name: names ) { QFileInfo info( name ); if( info.isDir( ) ) dirnames.insert( name.toStdString( ) ); else filenames.insert( name.toStdString( ) ); } // rof if( dirnames.size( ) == 1 && filenames.size( ) == 0 ) this->_openDicom( *( dirnames.begin( ) ) ); else if( dirnames.size( ) == 0 && filenames.size( ) > 0 ) this->_openImage( filenames ); else QMessageBox::critical( this, "Error opening image", "Directory - files mixed up, don't know what to do." ); } // fi } // ------------------------------------------------------------------------- void CTArteries:: _sConfig( ) { this->m_DlgParameters->exec( ); } // ------------------------------------------------------------------------- void CTArteries:: _sProcess( ) { this->_process( ); this->_showProcessResults( ); } // ------------------------------------------------------------------------- #include int main( int argc, char* argv[] ) { QApplication a( argc, argv ); CTArteries w( argc, argv ); w.show( ); return( a.exec( ) ); } // eof - $RCSfile$