From f8061bd4d18239ca8c02cfb4324989d1b6c3f074 Mon Sep 17 00:00:00 2001 From: Joao Carreira Date: Fri, 13 Mar 2015 03:45:13 +0000 Subject: [PATCH] Support for ploting single and multiple plots --- app/PlotSubWindow.cpp | 116 ++++++++++++++++++++++++++++++++---------- app/PlotSubWindow.h | 30 ++++++++--- app/QualityHandle.cpp | 116 +++++++++++++++++++++++++++++++++--------- app/QualityHandle.h | 9 +++- 4 files changed, 213 insertions(+), 58 deletions(-) diff --git a/app/PlotSubWindow.cpp b/app/PlotSubWindow.cpp index 9605711..1a5d7dd 100644 --- a/app/PlotSubWindow.cpp +++ b/app/PlotSubWindow.cpp @@ -23,6 +23,7 @@ */ #include "PlotSubWindow.h" +#include "qcustomplot.h" namespace plaYUVer { @@ -36,7 +37,7 @@ Void PlotSubWindow::definePlotColors() m_arrayColorList.append( Qt::cyan ); } -PlotSubWindow::PlotSubWindow( QWidget * parent ) : +PlotSubWindow::PlotSubWindow( QWidget * parent, const QString& windowTitle ) : SubWindowHandle( parent, SubWindowHandle::PLOT_SUBWINDOW ) { setParent( parent ); @@ -45,7 +46,19 @@ PlotSubWindow::PlotSubWindow( QWidget * parent ) : setBackgroundRole( QPalette::Light ); setVisible( false ); + definePlotColors(); + m_uiNumberPlots = 0; + m_dScaleFactor = 1; + + setWindowName( windowTitle ); + m_cPlotArea = new QCustomPlot( this ); + + QSizePolicy sizePolicy( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding ); + sizePolicy.setHorizontalStretch( 0 ); + sizePolicy.setVerticalStretch( 0 ); + sizePolicy.setHeightForWidth( m_cPlotArea->sizePolicy().hasHeightForWidth() ); + m_cPlotArea->setSizePolicy( sizePolicy ); setWidget( m_cPlotArea ); // configure right and top axis to show ticks but no labels: @@ -58,26 +71,16 @@ PlotSubWindow::PlotSubWindow( QWidget * parent ) : connect( m_cPlotArea->xAxis, SIGNAL( rangeChanged(QCPRange) ), m_cPlotArea->xAxis2, SLOT( setRange(QCPRange) ) ); connect( m_cPlotArea->yAxis, SIGNAL( rangeChanged(QCPRange) ), m_cPlotArea->yAxis2, SLOT( setRange(QCPRange) ) ); - definePlotColors(); - m_uiNumberPlots = 0; + QFont legendFont = font(); // start out with MainWindow's font.. + legendFont.setPointSize( 9 ); // and make a bit smaller for legend + m_cPlotArea->legend->setFont( legendFont ); + m_cPlotArea->legend->setVisible( false ); - m_cPlotArea->setInteractions( QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables ); + m_cPlotArea->setInteractions( QCP::iRangeZoom | QCP::iRangeDrag ); //QCP::iSelectPlottables -} - -Void PlotSubWindow::Example() -{ - // generate some points of data (y0 for first, y1 for second graph): - QVector x( 250 ), y0( 250 ), y1( 250 ); - for( int i = 0; i < 250; ++i ) - { - x[i] = i; - y0[i] = exp( -i / 150.0 ) * cos( i / 10.0 ); // exponentially decaying cosine - y1[i] = exp( -i / 150.0 ); // exponential envelope - } - - addPlot( x, y0 ); - addPlot( x, y1 ); + m_cPlotPen.setStyle( Qt::SolidLine ); + m_cPlotPen.setColor( Qt::black ); + m_cPlotPen.setWidthF( 2 ); } @@ -88,12 +91,15 @@ PlotSubWindow::~PlotSubWindow() Void PlotSubWindow::normalSize() { - + m_cPlotArea->xAxis->setRange( m_aAxisRange[HORIZONTAL][0], m_aAxisRange[HORIZONTAL][1] ); + m_cPlotArea->yAxis->setRange( m_aAxisRange[VERTICAL][0], m_aAxisRange[VERTICAL][1] ); + m_cPlotArea->replot(); + m_dScaleFactor = 1; } Void PlotSubWindow::zoomToFit() { - + normalSize(); } Void PlotSubWindow::zoomToFactor( Double factor, QPoint center ) @@ -103,7 +109,23 @@ Void PlotSubWindow::zoomToFactor( Double factor, QPoint center ) Void PlotSubWindow::scaleView( Double scale, QPoint center ) { + scale -= 1; + scale /= 10; + scale += 1; + m_dScaleFactor *= scale; +// +// UInt aNewAxisRange[2][2]; +// for( UInt axis = 0; axis < 2; axis++ ) +// for( UInt dim = 0; dim < 2; dim++ ) +// aNewAxisRange[axis][dim] = m_aAxisRange[axis][dim] / m_dScaleFactor; +// +// m_cPlotArea->xAxis->setRange( aNewAxisRange[HORIZONTAL][0], aNewAxisRange[HORIZONTAL][1] ); +// m_cPlotArea->yAxis->setRange( aNewAxisRange[VERTICAL][0], aNewAxisRange[VERTICAL][1] ); + + m_cPlotArea->xAxis->scaleRange( scale, 0 ); + m_cPlotArea->yAxis->scaleRange( scale, 0 ); + m_cPlotArea->replot(); } QSize PlotSubWindow::sizeHint() const @@ -123,19 +145,61 @@ QSize PlotSubWindow::sizeHint() const QSize PlotSubWindow::sizeHint( const QSize & maxSize ) const { - return maxSize; + return maxSize * 2 / 3; } -Void PlotSubWindow::addPlot( const QVector &key, const QVector &value ) +Void PlotSubWindow::setAxisName( const QString& nameAxisX, const QString& nameAxisY ) +{ + m_cPlotArea->xAxis->setLabel( nameAxisX ); + m_cPlotArea->yAxis->setLabel( nameAxisY ); +} + +Void PlotSubWindow::setAxisRange( const QLine& axisLimits ) +{ + setAxisRange( HORIZONTAL, axisLimits.x1(), axisLimits.x2() ); + setAxisRange( VERTICAL, axisLimits.y1(), axisLimits.y2() ); +} + +Void PlotSubWindow::setAxisRange( PlotSubWindow::Axis eAxis, const Int& axisStart, const Int& axisEnd ) +{ + if( eAxis == HORIZONTAL ) + { + m_cPlotArea->xAxis->setRange( axisStart, axisEnd ); + horizontalScrollBar()->setRange( axisStart * 100, axisEnd * 100 ); + m_aAxisRange[HORIZONTAL][0] = axisStart; + m_aAxisRange[HORIZONTAL][1] = axisEnd; + } + if( eAxis == VERTICAL ) + { + m_cPlotArea->yAxis->setRange( axisStart, axisEnd ); + verticalScrollBar()->setRange( axisStart * 100, axisEnd * 100 ); + m_aAxisRange[VERTICAL][0] = axisStart; + m_aAxisRange[VERTICAL][1] = axisEnd; + } + m_cPlotArea->replot(); +} + +Void PlotSubWindow::addPlot( const QVector &arrayX, const QVector &arrayY, const QString& key ) { QCPGraph *newPlot = m_cPlotArea->addGraph(); - newPlot->setPen( QPen( m_arrayColorList.at( m_uiNumberPlots ) ) ); // line color blue for first graph - newPlot->setBrush( QBrush( QColor( 0, 0, 255, 20 ) ) ); // first graph will be filled with translucent blue + m_cPlotPen.setColor( m_arrayColorList.at( m_uiNumberPlots ) ); + newPlot->setPen( m_cPlotPen ); // line style // pass data points to graphs: - newPlot->setData( key, value ); + newPlot->setData( arrayX, arrayY ); // let the ranges scale themselves so graph 0 fits perfectly in the visible area: newPlot->rescaleAxes( m_uiNumberPlots > 1 ? true : false ); + if( !key.isEmpty() ) + { + m_cPlotArea->legend->setVisible( true ); + newPlot->setName( key ); + } + + m_aAxisRange[HORIZONTAL][0] = m_cPlotArea->xAxis->range().lower; + m_aAxisRange[HORIZONTAL][1] = m_cPlotArea->xAxis->range().upper; + m_aAxisRange[VERTICAL][0] = m_cPlotArea->yAxis->range().lower; + m_aAxisRange[VERTICAL][1] = m_cPlotArea->yAxis->range().upper; + m_uiNumberPlots++; } diff --git a/app/PlotSubWindow.h b/app/PlotSubWindow.h index c8da96c..090b50b 100644 --- a/app/PlotSubWindow.h +++ b/app/PlotSubWindow.h @@ -33,7 +33,8 @@ #include #endif #include "SubWindowHandle.h" -#include "qcustomplot.h" + +class QCustomPlot; namespace plaYUVer { @@ -44,13 +45,22 @@ Q_OBJECT private: QCustomPlot* m_cPlotArea; + QVector m_arrayColorList; + QPen m_cPlotPen; + + enum Axis + { + HORIZONTAL, + VERTICAL, + }; + Double m_aAxisRange[2][2]; + Double m_dScaleFactor; UInt m_uiNumberPlots; - Void Example(); - public: - PlotSubWindow( QWidget * parent = 0 ); + + PlotSubWindow( QWidget * parent, const QString& windowTitle ); ~PlotSubWindow(); Void definePlotColors(); @@ -69,7 +79,7 @@ public: Double getScaleFactor() { - return 0; + return m_dScaleFactor; } /** @@ -78,7 +88,15 @@ public: QSize sizeHint() const; QSize sizeHint( const QSize & ) const; - Void addPlot(const QVector &key, const QVector &value); + Void setAxisName( const QString& nameAxisX, const QString& nameAxisY ); + + Void setAxisRange( const QLine& axisLimits ); + Void setAxisRange( PlotSubWindow::Axis eAxis, const Int& axisStart, const Int& axisEnd ); + + Void setKey( const QString& key ); + + Void addPlot( const QVector &arrayX, const QVector &arrayY, const QString& key = QString() ); + }; } // NAMESPACE diff --git a/app/QualityHandle.cpp b/app/QualityHandle.cpp index 646c80d..6ce37e9 100644 --- a/app/QualityHandle.cpp +++ b/app/QualityHandle.cpp @@ -29,6 +29,9 @@ #include "PlotSubWindow.h" #include "DialogSubWindowSelector.h" #include "lib/LibMemory.h" +#if( QT_VERSION_PLAYUVER == 5 ) +#include "QtConcurrent/qtconcurrentrun.h" +#endif namespace plaYUVer { @@ -65,8 +68,11 @@ Void QualityHandle::createActions() m_arrayActions.resize( TOTAL_ACT ); m_arrayActions[SELECT_REF_ACT] = new QAction( "Select Reference", this ); connect( m_arrayActions[SELECT_REF_ACT], SIGNAL( triggered() ), this, SLOT( slotSelectReference() ) ); - m_arrayActions[PLOT_QUALITY] = new QAction( "CREATE_PLOT", this ); - connect( m_arrayActions[PLOT_QUALITY], SIGNAL( triggered() ), this, SLOT( slotCreatePlot() ) ); + + m_arrayActions[PLOT_QUALITY] = new QAction( "Plot Window's Quality", this ); + connect( m_arrayActions[PLOT_QUALITY], SIGNAL( triggered() ), this, SLOT( slotPlotQualitySingle() ) ); + m_arrayActions[PLOT_SEVERAL_QUALITY] = new QAction( "Plot Several Quality", this ); + connect( m_arrayActions[PLOT_SEVERAL_QUALITY], SIGNAL( triggered() ), this, SLOT( slotPlotQualitySeveral() ) ); } QMenu* QualityHandle::createMenu() @@ -77,6 +83,7 @@ QMenu* QualityHandle::createMenu() m_pcMenuQuality->addAction( m_arrayActions[SELECT_REF_ACT] ); m_pcMenuQuality->addSeparator(); m_pcMenuQuality->addAction( m_arrayActions[PLOT_QUALITY] ); + m_pcMenuQuality->addAction( m_arrayActions[PLOT_SEVERAL_QUALITY] ); return m_pcMenuQuality; } @@ -102,7 +109,9 @@ Void QualityHandle::updateMenus() m_pcSubMenuQualityMetrics->setEnabled( hasSubWindow ); m_arrayActions[SELECT_REF_ACT]->setEnabled( hasSubWindow ); + m_arrayActions[PLOT_QUALITY]->setEnabled( hasSubWindow ); + m_arrayActions[PLOT_SEVERAL_QUALITY]->setEnabled( hasSubWindow ); m_pcQualityHandleSideBar->updateSideBar( hasSubWindow ); } @@ -128,25 +137,24 @@ Void QualityHandle::update( VideoSubWindow* currSubWindow ) m_pcQualityHandleSideBar->updateCurrentWindow( currSubWindow ); } -QVector* QualityHandle::measureQuality( QVector apcWindowList ) +Void QualityHandle::measureQuality( QVector apcWindowList ) { QVector* padQualityValues; UInt numberOfWindows = apcWindowList.size(); UInt64 currFrames = 0; UInt64 numberOfFrames = INT_MAX; - QApplication::setOverrideCursor( Qt::WaitCursor ); - //! Check reference window for( UInt i = 0; i < numberOfWindows; i++ ) { if( !apcWindowList.at( i )->getRefSubWindow() ) { - return NULL; + return; } } VideoSubWindow* pcReferenceWindow = apcWindowList.at( 0 )->getRefSubWindow(); + numberOfFrames = pcReferenceWindow->getInputStream()->getFrameNum(); for( UInt i = 0; i < numberOfWindows; i++ ) { currFrames = apcWindowList.at( i )->getInputStream()->getFrameNum(); @@ -160,28 +168,49 @@ QVector* QualityHandle::measureQuality( QVector apcWind PlaYUVerFrame* pcReferenceFrame; PlaYUVerFrame* pcCurrFrame; - for( UInt f = 1; f < numberOfFrames; f++ ) + for( UInt f = 0; f < numberOfFrames; f++ ) { padQualityValues[0].append( f ); pcReferenceFrame = pcReferenceWindow->getCurrFrame(); for( UInt i = 0; i < numberOfWindows; i++ ) { - pcCurrFrame = apcWindowList.at( 0 )->getCurrFrame(); - padQualityValues[i + 1].append( pcCurrFrame->getQuality( 0, pcReferenceFrame, LUMA ) ); - apcWindowList.at( 0 )->play(); - apcWindowList.at( 0 )->playEvent(); + pcCurrFrame = apcWindowList.at( i )->getCurrFrame(); + padQualityValues[i + 1].append( pcCurrFrame->getQuality( m_iQualityMetricIdx, pcReferenceFrame, LUMA ) ); + apcWindowList.at( i )->seekRelativeEvent( true ); } - pcReferenceWindow->play(); - pcReferenceWindow->playEvent(); + pcReferenceWindow->seekRelativeEvent( true ); } for( UInt i = 0; i < numberOfWindows; i++ ) { - apcWindowList.at( 0 )->stop(); + apcWindowList.at( i )->stop(); } pcReferenceWindow->stop(); - QApplication::restoreOverrideCursor(); - return padQualityValues; + QString plotWindowTitle( QStringLiteral( "Quality - " ) ); + if( apcWindowList.size() == 1 ) + { + plotWindowTitle += apcWindowList.at( 0 )->getWindowName(); + } + PlotSubWindow* pcPlotWindow = new PlotSubWindow( m_pcParet, plotWindowTitle ); + pcPlotWindow->setAxisName( "Frame Number", QString::fromStdString( PlaYUVerFrame::supportedQualityMetricsList()[m_iQualityMetricIdx] ) ); + + if( apcWindowList.size() > 1 ) + { + QString key; + for( UInt i = 0; i < numberOfWindows; i++ ) + { + key = apcWindowList.at( i )->getWindowName(); + pcPlotWindow->addPlot( padQualityValues[0], padQualityValues[i + 1], key ); + } + } + else + { + pcPlotWindow->addPlot( padQualityValues[0], padQualityValues[1] ); + } + + m_pcMainWindowManager->addSubWindow( pcPlotWindow ); + pcPlotWindow->show(); + } Void QualityHandle::slotQualityMetricChanged( Int idx ) @@ -220,7 +249,7 @@ Void QualityHandle::slotSelectReference() } } -Void QualityHandle::slotCreatePlot() +Void QualityHandle::slotPlotQualitySingle() { VideoSubWindow* pcSubWindow = qobject_cast( m_pcMainWindowManager->activeSubWindow() ); if( pcSubWindow ) @@ -229,18 +258,57 @@ Void QualityHandle::slotCreatePlot() { QVector apcWindowList; apcWindowList.append( pcSubWindow ); - QVector* qualityVector = measureQuality( apcWindowList ); - PlotSubWindow* pcPlotWindow = new PlotSubWindow( m_pcParet ); - - pcPlotWindow->addPlot( qualityVector[0], qualityVector[1] ); - - m_pcMainWindowManager->addSubWindow( pcPlotWindow ); - pcPlotWindow->show(); +//#ifndef QT_NO_CONCURRENT +// m_cMeasurementResult.waitForFinished(); +// m_cMeasurementResult = QtConcurrent::run( this, &QualityHandle::measureQuality, apcWindowList ); +//#else + QApplication::setOverrideCursor( Qt::WaitCursor ); + measureQuality( apcWindowList ); + QApplication::restoreOverrideCursor(); +//#endif } } +} +Void QualityHandle::slotPlotQualitySeveral() +{ + VideoSubWindow* pcSubWindow = qobject_cast( m_pcMainWindowManager->activeSubWindow() ); + if( pcSubWindow ) + { + QVector apcWindowList; + + VideoSubWindow* pcRefSubWindow = pcSubWindow->getRefSubWindow(); + if( !pcRefSubWindow ) + { + pcRefSubWindow = pcSubWindow; + } + + VideoSubWindow* pcVideoSubWindow; + QList subWindowList = m_pcMainWindowManager->findSubWindow( SubWindowHandle::VIDEO_STREAM_SUBWINDOW ); + for( Int i = 0; i < subWindowList.size(); i++ ) + { + pcVideoSubWindow = qobject_cast( subWindowList.at( i ) ); + if( pcVideoSubWindow->getRefSubWindow() == pcRefSubWindow ) + { + apcWindowList.append( pcVideoSubWindow ); + } + } + + if( apcWindowList.size() > 0 ) + { +//#ifndef QT_NO_CONCURRENT +// m_cMeasurementResult.waitForFinished(); +// m_cMeasurementResult = QtConcurrent::run( this, &QualityHandle::measureQuality, apcWindowList ); +//#else + QApplication::setOverrideCursor( Qt::WaitCursor ); + measureQuality( apcWindowList ); + QApplication::restoreOverrideCursor(); +//#endif + + } + } } } // NAMESPACE diff --git a/app/QualityHandle.h b/app/QualityHandle.h index 29d683f..df01a2e 100644 --- a/app/QualityHandle.h +++ b/app/QualityHandle.h @@ -33,6 +33,7 @@ #elif( QT_VERSION_PLAYUVER == 4 ) #include #endif +#include "QFuture" #include "QualityMeasurementSidebar.h" namespace plaYUVer @@ -61,10 +62,12 @@ public: private: QWidget* m_pcParet; PlaYUVerSubWindowHandle* m_pcMainWindowManager; + enum { SELECT_REF_ACT, PLOT_QUALITY, + PLOT_SEVERAL_QUALITY, TOTAL_ACT, }; QVector m_arrayActions; @@ -78,7 +81,8 @@ private: QDockWidget* m_pcQualityHandleDock; QualityMeasurementSidebar* m_pcQualityHandleSideBar; - QVector* measureQuality( QVector apcWindowList ); + QFuture m_cMeasurementResult; + Void measureQuality( QVector apcWindowList ); Q_SIGNALS: void changed(); @@ -86,7 +90,8 @@ Q_SIGNALS: private Q_SLOTS: void slotQualityMetricChanged( int ); void slotSelectReference(); - void slotCreatePlot(); + void slotPlotQualitySingle(); + void slotPlotQualitySeveral(); }; } // NAMESPACE