From ecc6a890d06f47b5fe6643d7d9468d31d671ec4e Mon Sep 17 00:00:00 2001 From: Leonardo Florez-Valencia Date: Sun, 22 Oct 2017 22:06:20 -0500 Subject: [PATCH] ... --- appli/CTArteries/CTArteries.cxx | 198 +++++++++++++++++++++++++++++++- appli/CTArteries/CTArteries.h | 14 +++ appli/CTArteries/CTArteries.ui | 26 ++++- 3 files changed, 233 insertions(+), 5 deletions(-) diff --git a/appli/CTArteries/CTArteries.cxx b/appli/CTArteries/CTArteries.cxx index 54b8aeb..282f66f 100644 --- a/appli/CTArteries/CTArteries.cxx +++ b/appli/CTArteries/CTArteries.cxx @@ -122,6 +122,10 @@ CTArteries( int argc, char* argv[], QWidget* parent ) QT_ACTION_CONN( Open ); QT_ACTION_CONN( Config ); QT_ACTION_CONN( Process ); + QT_ACTION_CONN( MarkReference ); + QT_ACTION_CONN( MarkStenosis ); + QT_ACTION_CONN( SaveResults ); + QT_ACTION_CONN( UpdateContour ); // Load log if( argc == 3 ) @@ -378,11 +382,17 @@ _prepareQuantification( ) for( auto eIt = edge->BeginGeomLnext( ); eIt != edge->EndGeomLnext( ); ++eIt ) points.push_back( mesh->GetPoint( *eIt ) ); - } // fi + TFourier f( points.begin( ), points.end( ), 6 ); + f.SetOrderingToCounterClockWise( ); + this->m_Fourier.push_back( f ); + } + else + { + TFourier f( 6 ); + f[ 1 ] = 0.1; + this->m_Fourier.push_back( f ); - TFourier f( points.begin( ), points.end( ), 6 ); - f.SetOrderingToCounterClockWise( ); - this->m_Fourier.push_back( f ); + } // fi vtkSmartPointer< ivq::VTK::PolyDataActor > actor = vtkSmartPointer< ivq::VTK::PolyDataActor >::New( ); @@ -468,6 +478,9 @@ _prepareQuantification( ) this->m_UI->Plot->rescaleAxes( ); this->m_UI->Plot->replot( ); + this->m_StenosisText = new QCPItemText( this->m_UI->Plot ); + this->m_StenosisText->setText( "Stenosis: NaN" ); + this->m_UI->Plot->replot( ); } // ------------------------------------------------------------------------- @@ -534,6 +547,64 @@ _showProcessResults( ) slice_view->Render( ); this->_prepareQuantification( ); + this->m_StenosisSlice = -1; + this->m_ReferenceSlice = -1; + this->m_StenosisLine = NULL; + this->m_ReferenceLine = NULL; +} + +// ------------------------------------------------------------------------- +void CTArteries:: +_showStenosis( ) +{ + if( this->m_StenosisSlice >= 0 ) + { + if( this->m_StenosisLine == NULL ) + this->m_StenosisLine = new QCPItemLine( this->m_UI->Plot ); + this->m_StenosisLine->start->setCoords( this->m_StenosisSlice, 0 ); + this->m_StenosisLine->end->setCoords( + this->m_StenosisSlice, + this->m_UI->Plot->yAxis->range( ).size( ) + ); + this->m_UI->Plot->replot( ); + + } // fi + if( this->m_ReferenceSlice >= 0 ) + { + if( this->m_ReferenceLine == NULL ) + this->m_ReferenceLine = new QCPItemLine( this->m_UI->Plot ); + this->m_ReferenceLine->start->setCoords( this->m_ReferenceSlice, 0 ); + this->m_ReferenceLine->end->setCoords( + this->m_ReferenceSlice, + this->m_UI->Plot->yAxis->range( ).size( ) + ); + this->m_UI->Plot->replot( ); + + } // fi + if( this->m_StenosisSlice < 0 || this->m_ReferenceSlice < 0 ) + return; + + double sa, sb, st, sp; + this->m_Fourier[ this->m_StenosisSlice ].GetEllipse( 1, sa, sb, st, sp ); + double sarea = this->m_Fourier[ this->m_StenosisSlice ].GetArea( ); + double ra, rb, rt, rp; + this->m_Fourier[ this->m_ReferenceSlice ].GetEllipse( 1, ra, rb, rt, rp ); + double rarea = this->m_Fourier[ this->m_ReferenceSlice ].GetArea( ); + double qmin = 100.0 * ( 1.0 - ( sb / rb ) ); + double qmax = 100.0 * ( 1.0 - ( sa / ra ) ); + double qarea = 100.0 * ( 1.0 - ( sarea / rarea ) ); + + std::stringstream s; + s << "Stenosis: " << std::endl + << qmin << "% (min diameter)" << std::endl + << qmax << "% (max diameter)" << std::endl + << qarea << "% (area)"; + this->m_StenosisText->setText( s.str( ).c_str( ) ); + this->m_StenosisText->position->setCoords( + ( this->m_ReferenceSlice + this->m_StenosisSlice ) * 0.5, + this->m_UI->Plot->yAxis->range( ).center( ) + ); + this->m_UI->Plot->replot( ); } // ------------------------------------------------------------------------- @@ -628,6 +699,125 @@ _sProcess( ) this->_showProcessResults( ); } +// ------------------------------------------------------------------------- +void CTArteries:: +_sMarkReference( ) +{ + if( this->m_Fourier.size( ) == 0 ) + return; + ivq::VTK::ImageViewer* slice_view = this->m_UI->Slice->GetViewer( ); + this->m_ReferenceSlice = slice_view->GetImageActor( )->GetSliceNumber( ); + this->_showStenosis( ); +} + +// ------------------------------------------------------------------------- +void CTArteries:: +_sMarkStenosis( ) +{ + if( this->m_Fourier.size( ) == 0 ) + return; + ivq::VTK::ImageViewer* slice_view = this->m_UI->Slice->GetViewer( ); + this->m_StenosisSlice = slice_view->GetImageActor( )->GetSliceNumber( ); + this->_showStenosis( ); +} + +// ------------------------------------------------------------------------- +void CTArteries:: +_sSaveResults( ) +{ + std::string fname = + QFileDialog::getSaveFileName( + this, + "Select one or more files to open", + ".", + "CSV files (*.csv);;All files (*)" + ).toStdString( ); + if( fname == "" ) + return; + + std::ofstream out( fname.c_str( ) ); + out << "slice;min_diameter;max_diameter;area" << std::endl; + for( unsigned int i = 0; i < this->m_Fourier.size( ); ++i ) + { + double a, b, t, p; + this->m_Fourier[ i ].GetEllipse( 1, a, b, t, p ); + double area = this->m_Fourier[ i ].GetArea( ); + out << i << ";" << b << ";" << a << ";" << area << std::endl; + + } // rof + out << "############################" << std::endl; + typedef ivq::VTK::SeedWidgetOverImageActor::TSeeds _TSeeds; + const _TSeeds& seeds = this->m_Seeds->GetSeeds( ); + for( _TSeeds::value_type seed: seeds ) + { + for( unsigned int i = 0; i < seed.second.size( ); i += 3 ) + { + out + << seed.second[ i + 0 ] << " " + << seed.second[ i + 1 ] << " " + << seed.second[ i + 2 ] << std::endl; + + } // rof + + } // rof + out << "############################" << std::endl; + out.close( ); +} + +// ------------------------------------------------------------------------- +void CTArteries:: +_sUpdateContour( ) +{ + if( this->m_ContourActor == NULL ) + return; + vtkSmartPointer< vtkPolyData > new_pd = + vtkSmartPointer< vtkPolyData >::New( ); + this->m_Spline->GetPolyData( new_pd ); + + ivq::VTK::ImageViewer* slice_view = this->m_UI->Slice->GetViewer( ); + ivq::VTK::ImageActor* slice_actor = slice_view->GetImageActor( ); + this->m_ContoursActors[ slice_actor->GetSliceNumber( ) ]-> + SetInputData( new_pd ); + slice_view->Render( ); + + + typedef itk::QuadEdgeMesh< double, 2 > _TQEMesh; + typedef _TQEMesh::PointType _T2DPoint; + typedef std::vector< _T2DPoint > _T2DPoints; + _T2DPoints points; + _TQEMesh::Pointer mesh = _TQEMesh::New( ); + for( unsigned int i = 0; i < new_pd->GetNumberOfPoints( ); ++i ) + { + _T2DPoint pnt; + double p[ 3 ]; + new_pd->GetPoint( i, p ); + pnt[ 0 ] = p[ 0 ]; + pnt[ 1 ] = p[ 1 ]; + mesh->AddPoint( pnt ); + + } // rof + vtkCellArray* lines = new_pd->GetLines( ); + lines->InitTraversal( ); + vtkIdType* ids = new vtkIdType[ 2 ]; + vtkIdType npts; + while( lines->GetNextCell( npts, ids ) != 0 ) + mesh->AddEdge( ids[ 0 ], ids[ 1 ] ); + delete ids; + _TQEMesh::QEPrimal* edge = mesh->GetEdge( ); + if( edge != NULL ) + { + mesh->AddFace( edge ); + edge = mesh->GetEdge( ); + for( auto eIt = edge->BeginGeomLnext( ); eIt != edge->EndGeomLnext( ); ++eIt ) + points.push_back( mesh->GetPoint( *eIt ) ); + + TFourier f( points.begin( ), points.end( ), 6 ); + f.SetOrderingToCounterClockWise( ); + this->m_Fourier[ slice_actor->GetSliceNumber( ) ] = f; + + } // fi +} + // ------------------------------------------------------------------------- template< class _TImagePtr, class _TVTKImagePtr, class _TCurvePtr > void CTArteries:: diff --git a/appli/CTArteries/CTArteries.h b/appli/CTArteries/CTArteries.h index 90d9e09..0fd1b45 100644 --- a/appli/CTArteries/CTArteries.h +++ b/appli/CTArteries/CTArteries.h @@ -20,6 +20,8 @@ class vtkPolyData; class vtkSplineWidget; class QDialog; +class QCPItemLine; +class QCPItemText; namespace Ui { class CTArteries; @@ -75,6 +77,7 @@ protected: void _process( const std::vector< TImage::PointType >& seeds ); void _prepareQuantification( ); void _showProcessResults( ); + void _showStenosis( ); void _ExecuteLog( const std::string& fname ); @@ -82,6 +85,10 @@ protected slots: void _sOpen( ); void _sConfig( ); void _sProcess( ); + void _sMarkReference( ); + void _sMarkStenosis( ); + void _sSaveResults( ); + void _sUpdateContour( ); private: template< class _TImagePtr, class _TVTKImagePtr, class _TCurvePtr > @@ -124,6 +131,13 @@ private: vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor > m_Seeds; vtkSmartPointer< vtkSplineWidget > m_Spline; + // References + int m_StenosisSlice; + int m_ReferenceSlice; + QCPItemLine* m_StenosisLine; + QCPItemLine* m_ReferenceLine; + QCPItemText* m_StenosisText; + friend class ContourCallback; }; diff --git a/appli/CTArteries/CTArteries.ui b/appli/CTArteries/CTArteries.ui index 5bbd884..3af923a 100644 --- a/appli/CTArteries/CTArteries.ui +++ b/appli/CTArteries/CTArteries.ui @@ -44,7 +44,7 @@ 0 0 800 - 20 + 17 @@ -52,6 +52,7 @@ File + @@ -70,6 +71,9 @@ + + + @@ -91,6 +95,26 @@ Config + + + Mark reference + + + + + Mark stenosis + + + + + Save + + + + + Update contour + + -- 2.47.1