From 2f4d396506bce68040e706b1c9525a6e68a39805 Mon Sep 17 00:00:00 2001 From: Yannick Verdie Date: Tue, 29 Jun 2010 22:14:24 +0000 Subject: [PATCH] New functions with QT GUI: - save/load window parameters implemented ! --- .../include/opencv2/highgui/highgui.hpp | 2 + .../include/opencv2/highgui/highgui_c.h | 2 + modules/highgui/src/window.cpp | 10 + modules/highgui/src/window_QT.cpp | 541 ++++++++++-------- modules/highgui/src/window_QT.h | 162 +++--- 5 files changed, 416 insertions(+), 301 deletions(-) diff --git a/modules/highgui/include/opencv2/highgui/highgui.hpp b/modules/highgui/include/opencv2/highgui/highgui.hpp index 9168df8668..97de19c2a4 100644 --- a/modules/highgui/include/opencv2/highgui/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui/highgui.hpp @@ -67,6 +67,8 @@ CV_EXPORTS double getWindowProperty(const string& winname, int prop_id);//YV //Only for QT CV_EXPORTS void displayOverlay(const string& winname, const string& text, int delayms); CV_EXPORTS void displayStatusBar(const string& winname, const string& text, int delayms); +CV_EXPORTS void saveWindowParameters(const string& windowName); +CV_EXPORTS void loadWindowParameters(const string& windowName); CV_EXPORTS int startLoop(int (*pt2Func)(int argc, char *argv[]), int argc, char* argv[]); CV_EXPORTS void stopLoop(); diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index 9bf6cada6c..2f0c5047c6 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -60,6 +60,8 @@ extern "C" { //-----------New for QT CVAPI(void) cvDisplayOverlay(const char* name, const char* text, int delayms); CVAPI(void) cvDisplayStatusBar(const char* name, const char* text, int delayms); +CVAPI(void) cvSaveWindowParameters(const char* name); +CVAPI(void) cvLoadWindowParameters(const char* name); CVAPI(int) cvStartLoop(int (*pt2Func)(int argc, char *argv[]), int argc, char* argv[]); CVAPI(void) cvStopLoop(); //---------------------- diff --git a/modules/highgui/src/window.cpp b/modules/highgui/src/window.cpp index 3ad87418cc..1bd2d9eb14 100644 --- a/modules/highgui/src/window.cpp +++ b/modules/highgui/src/window.cpp @@ -160,6 +160,16 @@ int waitKey(int delay) return cvWaitKey(delay); } +void saveWindowParameters(const string& windowName) +{ + cvSaveWindowParameters(windowName.c_str()); +} + +void loadWindowParameters(const string& windowName) +{ + cvLoadWindowParameters(windowName.c_str()); +} + int createTrackbar(const string& trackbarName, const string& winName, int* value, int count, TrackbarCallback callback, void* userdata) diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index 3bd794bd5d..82c3840965 100755 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -42,7 +42,6 @@ #ifdef HAVE_QT #include -#include //Static and global first static GuiReceiver guiMainThread; @@ -132,6 +131,22 @@ CV_IMPL void cvDisplayOverlay(const char* name, const char* text, int delayms) } +CV_IMPL void cvSaveWindowParameters(const char* name) +{ + QMetaObject::invokeMethod(&guiMainThread, + "saveWindowParameters", + Qt::AutoConnection, + Q_ARG(QString, QString(name))); +} + +CV_IMPL void cvLoadWindowParameters(const char* name) +{ + QMetaObject::invokeMethod(&guiMainThread, + "loadWindowParameters", + Qt::AutoConnection, + Q_ARG(QString, QString(name))); +} + CV_IMPL void cvDisplayStatusBar(const char* name, const char* text, int delayms) { @@ -235,7 +250,7 @@ CV_IMPL CvWindow* icvFindWindowByName( const char* arg ) foreach (QWidget *widget, QApplication::topLevelWidgets()) { w = (CvWindow*) widget; - if (w->name==name) + if (w->param_name==name) { window = w; break; @@ -249,7 +264,7 @@ CvTrackbar* icvFindTrackbarByName( const char* name_trackbar, const char* name_w { QPointer result = NULL; - + QPointer w = icvFindWindowByName( name_window ); if( !w ) @@ -258,8 +273,9 @@ CvTrackbar* icvFindTrackbarByName( const char* name_trackbar, const char* name_w QString nameQt = QString(name_trackbar); QPointer t; - //Warning ---- , asume the location 0 is myview and max-1 the status bar - for (int i = 1; i < w->layout->layout()->count()-2; ++i) + //Warning ---- , asume the location 0 is myview and max-1 the status bar + //done three times in the code, in loadtrackbars, savetrackbar and in findtrackbar + for (int i = 1; i < w->layout->layout()->count()-1; ++i) { t = (CvTrackbar*) w->layout->layout()->itemAt(i); @@ -467,6 +483,22 @@ GuiReceiver::GuiReceiver() : _bTimeOut(false) qApp->setQuitOnLastWindowClosed ( false );//maybe the user would like to access this setting } +void GuiReceiver::saveWindowParameters(QString name) +{ + QPointer w = icvFindWindowByName( name.toLatin1().data() ); + + if (w) + w->writeSettings(); +} + +void GuiReceiver::loadWindowParameters(QString name) +{ + QPointer w = icvFindWindowByName( name.toLatin1().data() ); + + if (w) + w->readSettings(); +} + double GuiReceiver::getRatioWindow(QString name) { QPointer w = icvFindWindowByName( name.toLatin1().data() ); @@ -504,7 +536,7 @@ double GuiReceiver::getPropWindow(QString name) if (!w) return -1; - return (double)w->flags; + return (double)w->param_flags; } void GuiReceiver::setPropWindow(QString name, double arg2 ) @@ -516,7 +548,7 @@ void GuiReceiver::setPropWindow(QString name, double arg2 ) int flags = (int) arg2; - if (w->flags == flags)//nothing to do + if (w->param_flags == flags)//nothing to do return; @@ -524,11 +556,11 @@ void GuiReceiver::setPropWindow(QString name, double arg2 ) { case CV_WINDOW_NORMAL: w->layout->setSizeConstraint(QLayout::SetMinAndMaxSize); - w->flags = flags; + w->param_flags = flags; break; case CV_WINDOW_AUTOSIZE: w->layout->setSizeConstraint(QLayout::SetFixedSize); - w->flags = flags; + w->param_flags = flags; break; default:; } @@ -757,16 +789,16 @@ void CvTrackbar::createDialog() int max = slider->maximum(); int i = QInputDialog::getInt(this->parentWidget(), - tr("Slider %1").arg(trackbar_name), - tr("New value:"), - value, - min, - max, - step, - &ok); + tr("Slider %1").arg(trackbar_name), + tr("New value:"), + value, + min, + max, + step, + &ok); if (ok) - slider->setValue(i); + slider->setValue(i); } @@ -776,7 +808,7 @@ void CvTrackbar::update(int myvalue) *dataSlider = myvalue; if (callback) - callback(myvalue); + callback(myvalue); } void CvTrackbar::setLabel(int myvalue) @@ -796,13 +828,13 @@ CvTrackbar::~CvTrackbar() CvWindow::CvWindow(QString arg, int arg2) { moveToThread(qApp->instance()->thread()); - name = arg; - flags = arg2; + param_name = arg; + param_flags = arg2; setAttribute(Qt::WA_DeleteOnClose);//in other case, does not release memory setContentsMargins(0,0,0,0); - setWindowTitle(name); - setObjectName(name); + setWindowTitle(param_name); + setObjectName(param_name); resize(400,300); @@ -811,22 +843,20 @@ CvWindow::CvWindow(QString arg, int arg2) myview->setAlignment(Qt::AlignHCenter); - shortcut_r_Zoom = new QShortcut(Qt::CTRL + Qt::Key_P, this); - QObject::connect( shortcut_r_Zoom, SIGNAL( activated ()),myview, SLOT( resetZoom( ) )); - shortcut_imgRegion = new QShortcut(Qt::CTRL + Qt::Key_O, this); - QObject::connect( shortcut_imgRegion, SIGNAL( activated ()),myview, SLOT( imgRegion( ) )); - shortcut_Plus = new QShortcut(QKeySequence(QKeySequence::ZoomIn), this); - QObject::connect( shortcut_Plus, SIGNAL( activated ()),myview, SLOT( ZoomIn() )); - shortcut_Minus = new QShortcut(QKeySequence(QKeySequence::ZoomOut), this); - QObject::connect(shortcut_Minus, SIGNAL( activated ()),myview, SLOT( ZoomOut() )); - shortcut_Left = new QShortcut(Qt::CTRL + Qt::Key_Left, this); - QObject::connect( shortcut_Left, SIGNAL( activated ()),myview, SLOT( siftWindowOnLeft() )); - shortcut_Right = new QShortcut(Qt::CTRL + Qt::Key_Right, this); - QObject::connect( shortcut_Right, SIGNAL( activated ()),myview, SLOT( siftWindowOnRight() )); - shortcut_Up = new QShortcut(Qt::CTRL + Qt::Key_Up, this); - QObject::connect(shortcut_Up, SIGNAL( activated ()),myview, SLOT( siftWindowOnUp() )); - shortcut_Down = new QShortcut(Qt::CTRL + Qt::Key_Down, this); - QObject::connect(shortcut_Down, SIGNAL( activated ()),myview, SLOT( siftWindowOnDown() )); + shortcutZ = new QShortcut(Qt::CTRL + Qt::Key_P, this); + QObject::connect( shortcutZ, SIGNAL( activated ()),myview, SLOT( resetZoom( ) )); + shortcutPlus = new QShortcut(QKeySequence(QKeySequence::ZoomIn), this); + QObject::connect( shortcutPlus, SIGNAL( activated ()),myview, SLOT( ZoomIn() )); + shortcutMinus = new QShortcut(QKeySequence(QKeySequence::ZoomOut), this); + QObject::connect(shortcutMinus, SIGNAL( activated ()),myview, SLOT( ZoomOut() )); + shortcutLeft = new QShortcut(Qt::CTRL + Qt::Key_Left, this); + QObject::connect( shortcutLeft, SIGNAL( activated ()),myview, SLOT( siftWindowOnLeft() )); + shortcutRight = new QShortcut(Qt::CTRL + Qt::Key_Right, this); + QObject::connect( shortcutRight, SIGNAL( activated ()),myview, SLOT( siftWindowOnRight() )); + shortcutUp = new QShortcut(Qt::CTRL + Qt::Key_Up, this); + QObject::connect(shortcutUp, SIGNAL( activated ()),myview, SLOT( siftWindowOnUp() )); + shortcutDown = new QShortcut(Qt::CTRL + Qt::Key_Down, this); + QObject::connect(shortcutDown, SIGNAL( activated ()),myview, SLOT( siftWindowOnDown() )); layout = new QBoxLayout(QBoxLayout::TopToBottom); //layout = new CustomLayout; @@ -837,8 +867,8 @@ CvWindow::CvWindow(QString arg, int arg2) layout->addWidget(myview,Qt::AlignCenter); //layout->addStretch(0); - if (flags == CV_WINDOW_AUTOSIZE) - layout->setSizeConstraint(QLayout::SetFixedSize); + if (param_flags == CV_WINDOW_AUTOSIZE) + layout->setSizeConstraint(QLayout::SetFixedSize); //now status bar myBar = new QStatusBar; @@ -864,29 +894,28 @@ CvWindow::~CvWindow() if (layout) { - while ((child = layout->takeAt(0)) != 0) - delete child; + while ((child = layout->takeAt(0)) != 0) + delete child; - delete layout; + delete layout; } delete myBar; delete myBar_msg; - delete shortcut_r_Zoom; - delete shortcut_imgRegion; - delete shortcut_Plus; - delete shortcut_Minus; - delete shortcut_Left; - delete shortcut_Right; - delete shortcut_Up; - delete shortcut_Down; + delete shortcutZ; + delete shortcutPlus; + delete shortcutMinus; + delete shortcutLeft; + delete shortcutRight; + delete shortcutUp; + delete shortcutDown; } ViewPort* CvWindow::getView() { - return myview; + return myview; } void CvWindow::displayInfo(QString text,int delayms) @@ -925,57 +954,132 @@ void CvWindow::keyPressEvent(QKeyEvent *event) if (key>=20 && key<=255 ) { - key = (int)event->text().toLocal8Bit().at(0); - goodKey = true; + key = (int)event->text().toLocal8Bit().at(0); + goodKey = true; } if (key == Qt::Key_Escape) { - key = 27; - goodKey = true; + key = 27; + goodKey = true; } //control plus (Z, +, -, up, down, left, right) are used for zoom/panning functions if (event->modifiers() != Qt::ControlModifier && goodKey) { - mutexKey.lock(); - last_key = key; - //last_key = event->nativeVirtualKey (); - mutexKey.unlock(); - key_pressed.wakeAll(); - //event->accept(); + mutexKey.lock(); + last_key = key; + //last_key = event->nativeVirtualKey (); + mutexKey.unlock(); + key_pressed.wakeAll(); + //event->accept(); } QWidget::keyPressEvent(event); } -void CvWindow::readSettings()//not tested +void CvWindow::readSettings() { - QSettings settings("Trolltech", "Application Example"); + //organisation and application's name + QSettings settings("OpenCV2", QFileInfo(QApplication::applicationFilePath()).fileName()); QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); QSize size = settings.value("size", QSize(400, 400)).toSize(); + param_name = settings.value("name_window",param_name).toString(); + + param_flags = settings.value("mode_resize",param_flags).toInt(); + qreal m11 = settings.value("matrix_view.m11",myview->param_matrixWorld.m11()).toReal(); + qreal m12 = settings.value("matrix_view.m12",myview->param_matrixWorld.m12()).toReal(); + qreal m13 = settings.value("matrix_view.m13",myview->param_matrixWorld.m13()).toReal(); + qreal m21 = settings.value("matrix_view.m21",myview->param_matrixWorld.m21()).toReal(); + qreal m22 = settings.value("matrix_view.m22",myview->param_matrixWorld.m22()).toReal(); + qreal m23 = settings.value("matrix_view.m23",myview->param_matrixWorld.m23()).toReal(); + qreal m31 = settings.value("matrix_view.m31",myview->param_matrixWorld.m31()).toReal(); + qreal m32 = settings.value("matrix_view.m32",myview->param_matrixWorld.m32()).toReal(); + qreal m33 = settings.value("matrix_view.m33",myview->param_matrixWorld.m33()).toReal(); + myview->param_matrixWorld = QTransform(m11,m12,m13,m21,m22,m23,m31,m32,m33); + + //trackbar here + icvLoadTrackbars(&settings); + resize(size); move(pos); } -void CvWindow::writeSettings()//not tested +void CvWindow::writeSettings() { - QSettings settings("Trolltech", "Application Example"); + //organisation and application's name + QSettings settings("OpenCV2", QFileInfo(QApplication::applicationFilePath()).fileName()); + settings.setValue("name_window",param_name); settings.setValue("pos", pos()); settings.setValue("size", size()); + settings.setValue("mode_resize",param_flags); + settings.setValue("view_aspectRatio",myview->param_keepRatio); + + settings.setValue("matrix_view.m11",myview->param_matrixWorld.m11()); + settings.setValue("matrix_view.m12",myview->param_matrixWorld.m12()); + settings.setValue("matrix_view.m13",myview->param_matrixWorld.m13()); + settings.setValue("matrix_view.m21",myview->param_matrixWorld.m21()); + settings.setValue("matrix_view.m22",myview->param_matrixWorld.m22()); + settings.setValue("matrix_view.m23",myview->param_matrixWorld.m23()); + settings.setValue("matrix_view.m31",myview->param_matrixWorld.m31()); + settings.setValue("matrix_view.m32",myview->param_matrixWorld.m32()); + settings.setValue("matrix_view.m33",myview->param_matrixWorld.m33()); + + icvSaveTrackbars(&settings); } +void CvWindow::icvLoadTrackbars(QSettings *settings) +{ + int size = settings->beginReadArray("trackbars"); + QPointer t; + //Warning ---- , asume the location 0 is myview and max-1 the status bar + //done three times in the code, in loadtrackbars, savetrackbar and in findtrackbar + + //trackbar are saved in the same order, so no need to use icvFindTrackbarByName + if (layout->layout()->count()-2 == size)//if not the same number, the window saved and loaded is not the same (nb trackbar not equal) + for (int i = 0; i < size; ++i) + { + settings->setArrayIndex(i); + t = (CvTrackbar*) layout->layout()->itemAt(i+1);//+1 because index 0 is myview (see Warning) + + if (t->trackbar_name == settings->value("name").toString()) + { + t->slider->setValue(settings->value("value").toInt()); + } + } + settings->endArray(); + +} + +void CvWindow::icvSaveTrackbars(QSettings *settings) +{ + QPointer t; + + //Warning ---- , asume the location 0 is myview and max-1 the status bar + //done three times in the code, in loadtrackbars, savetrackbar and in findtrackbar + settings->beginWriteArray("trackbars"); + for (int i = 0; i < layout->layout()->count()-2; ++i) { + t = (CvTrackbar*) layout->layout()->itemAt(i+1);//+1 because index 0 is myview (see Warning) + settings->setArrayIndex(i); + settings->setValue("name", t->trackbar_name); + settings->setValue("value", t->slider->value()); + } + settings->endArray(); +} + + + //Here is ViewPort ViewPort::ViewPort(CvWindow* arg, int arg2, int arg3) { centralWidget = arg, - mode = arg2; - keepRatio = arg3; - + mode_display = arg2; + param_keepRatio = arg3; + setupViewport(centralWidget); setContentsMargins(0,0,0,0); - + setObjectName(QString::fromUtf8("graphicsView")); timerDisplay = new QTimer(this); timerDisplay->setSingleShot(true); @@ -985,20 +1089,20 @@ ViewPort::ViewPort(CvWindow* arg, int arg2, int arg3) positionCorners = QRect(0,0,size().width(),size().height()); on_mouse = NULL; mouseCoordinate = QPoint(-1,-1); - - + + #if defined(OPENCV_GL) - if (mode == CV_MODE_OPENGL) + if ( mode_display == CV_MODE_OPENGL) { setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); initGL(); } #endif - + image2Draw_ipl=cvCreateImage(cvSize(centralWidget->width(),centralWidget->height()),IPL_DEPTH_8U,3); nbChannelOriginImage = 0; cvZero(image2Draw_ipl); - + setInteractive(false); setMouseTracking (true);//receive mouse event everytime } @@ -1007,68 +1111,63 @@ ViewPort::~ViewPort() { if (image2Draw_ipl) cvReleaseImage(&image2Draw_ipl); - + delete timerDisplay; } void ViewPort::setRatio(int flags) { - keepRatio = flags; + param_keepRatio = flags; updateGeometry(); viewport()->update(); } int ViewPort::getRatio() { - return keepRatio; + return param_keepRatio; } void ViewPort::resetZoom() { - matrixWorld.reset(); + param_matrixWorld.reset(); controlImagePosition(); } -void ViewPort::imgRegion( ) -{ - scaleView(threshold_zoom_img_region/matrixWorld.m11(), QPointF(size().width()/2,size().height()/2),false);//false = do not process the 1st param -} - void ViewPort::ZoomIn() { - scaleView( 0.5,QPointF(size().width()/2,size().height()/2),true); + scaleView( 0.5,QPointF(size().width()/2,size().height()/2)); } void ViewPort::ZoomOut() { - scaleView( -0.5,QPointF(size().width()/2,size().height()/2),true); + scaleView( -0.5,QPointF(size().width()/2,size().height()/2)); } //Note: move 2 percent of the window void ViewPort::siftWindowOnLeft() { - float delta = 2*width()/(100.0*matrixWorld.m11()); + float delta = 2*width()/(100.0*param_matrixWorld.m11()); moveView(QPointF(delta,0)); } //Note: move 2 percent of the window void ViewPort::siftWindowOnRight() { - float delta = -2*width()/(100.0*matrixWorld.m11()); + float delta = -2*width()/(100.0*param_matrixWorld.m11()); moveView(QPointF(delta,0)); } //Note: move 2 percent of the window void ViewPort::siftWindowOnUp() { - float delta = 2*height()/(100.0*matrixWorld.m11()); + float delta = 2*height()/(100.0*param_matrixWorld.m11()); moveView(QPointF(0,delta)); } //Note: move 2 percent of the window void ViewPort::siftWindowOnDown() { - float delta = -2*height()/(100.0*matrixWorld.m11()); + float delta = -2*height()/(100.0*param_matrixWorld.m11()); moveView(QPointF(0,delta)); } @@ -1076,7 +1175,7 @@ void ViewPort::startDisplayInfo(QString text, int delayms) { if (timerDisplay->isActive()) stopDisplayInfo(); - + infoText = text; timerDisplay->start(delayms); drawInfo = true; @@ -1097,20 +1196,20 @@ void ViewPort::updateImage(void* arr) { if (!arr) CV_Error(CV_StsNullPtr, "NULL arr pointer (in showImage)" ); - + IplImage* tempImage = (IplImage*)arr; - + if (!isSameSize(image2Draw_ipl,tempImage)) { cvReleaseImage(&image2Draw_ipl); image2Draw_ipl=cvCreateImage(cvGetSize(tempImage),IPL_DEPTH_8U,3); - + nbChannelOriginImage = tempImage->nChannels; updateGeometry(); } - + cvConvertImage(tempImage,image2Draw_ipl,CV_CVTIMG_SWAP_RB ); - + viewport()->update(); } @@ -1123,84 +1222,81 @@ void ViewPort::setMouseCallBack(CvMouseCallback m, void* param) void ViewPort::controlImagePosition() { qreal left, top, right, bottom; - + //after check top-left, bottom right corner to avoid getting "out" during zoom/panning - matrixWorld.map(0,0,&left,&top); - + param_matrixWorld.map(0,0,&left,&top); + if (left > 0) { - matrixWorld.translate(-left,0); + param_matrixWorld.translate(-left,0); left = 0; } if (top > 0) { - matrixWorld.translate(0,-top); + param_matrixWorld.translate(0,-top); top = 0; } //------- - + QSize sizeImage = size(); - matrixWorld.map(sizeImage.width(),sizeImage.height(),&right,&bottom); + param_matrixWorld.map(sizeImage.width(),sizeImage.height(),&right,&bottom); if (right < sizeImage.width()) { - matrixWorld.translate(sizeImage.width()-right,0); + param_matrixWorld.translate(sizeImage.width()-right,0); right = sizeImage.width(); } if (bottom < sizeImage.height()) { - matrixWorld.translate(0,sizeImage.height()-bottom); + param_matrixWorld.translate(0,sizeImage.height()-bottom); bottom = sizeImage.height(); } - + //save corner position positionCorners.setTopLeft(QPoint(left,top)); positionCorners.setBottomRight(QPoint(right,bottom)); //save also the inv matrix - matrixWorld_inv = matrixWorld.inverted(); - + matrixWorld_inv = param_matrixWorld.inverted(); + viewport()->update(); } void ViewPort::moveView(QPointF delta) { - matrixWorld.translate(delta.x(),delta.y()); + param_matrixWorld.translate(delta.x(),delta.y()); controlImagePosition(); } //factor is -0.5 (zoom out) or 0.5 (zoom in) -void ViewPort::scaleView(qreal factor,QPointF center,bool process_factor) +void ViewPort::scaleView(qreal factor,QPointF center) { - if (process_factor) - { - factor/=5;//-0.1 <-> 0.1 - factor+=1;//0.9 <-> 1.1 - } - + factor/=5;//-0.1 <-> 0.1 + factor+=1;//0.9 <-> 1.1 + //limit zoom out --- - if (matrixWorld.m11()==1 && factor < 1) + if (param_matrixWorld.m11()==1 && factor < 1) return; - - if (matrixWorld.m11()*factor<1) - factor = 1/matrixWorld.m11(); - - + + if (param_matrixWorld.m11()*factor<1) + factor = 1/param_matrixWorld.m11(); + + //limit zoom int --- - if (matrixWorld.m11()>100 && factor > 1) + if (param_matrixWorld.m11()>100 && factor > 1) return; - + //inverse the transform int a, b; matrixWorld_inv.map(center.x(),center.y(),&a,&b); - - matrixWorld.translate(a-factor*a,b-factor*b); - matrixWorld.scale(factor,factor); - + + param_matrixWorld.translate(a-factor*a,b-factor*b); + param_matrixWorld.scale(factor,factor); + controlImagePosition(); - + //display new zoom - centralWidget->displayStatusBar(tr("Zoom: %1%").arg(matrixWorld.m11()*100),1000); - - if (matrixWorld.m11()>1) + centralWidget->displayStatusBar(tr("Zoom: %1%").arg(param_matrixWorld.m11()*100),1000); + + if (param_matrixWorld.m11()>1) setCursor(Qt::OpenHandCursor); else unsetCursor(); @@ -1208,40 +1304,40 @@ void ViewPort::scaleView(qreal factor,QPointF center,bool process_factor) void ViewPort::wheelEvent(QWheelEvent *event) { - scaleView( -event->delta() / 240.0,event->pos(),true);//true means process the 1st parameter + scaleView( -event->delta() / 240.0,event->pos()); } void ViewPort::mousePressEvent(QMouseEvent *event) { int cv_event = -1, flags = 0; QPoint pt = event->pos(); - + //icvmouseHandler: pass parameters for cv_event, flags icvmouseHandler(event, mouse_down, cv_event, flags); icvmouseProcessing(QPointF(pt), cv_event, flags); - - if (matrixWorld.m11()>1) + + if (param_matrixWorld.m11()>1) { setCursor(Qt::ClosedHandCursor); positionGrabbing = event->pos(); } - + QWidget::mousePressEvent(event); } void ViewPort::mouseReleaseEvent(QMouseEvent *event) { - + int cv_event = -1, flags = 0; QPoint pt = event->pos(); - + //icvmouseHandler: pass parameters for cv_event, flags icvmouseHandler(event, mouse_up, cv_event, flags); icvmouseProcessing(QPointF(pt), cv_event, flags); - - if (matrixWorld.m11()>1) + + if (param_matrixWorld.m11()>1) setCursor(Qt::OpenHandCursor); - + QWidget::mouseReleaseEvent(event); } @@ -1249,11 +1345,11 @@ void ViewPort::mouseDoubleClickEvent(QMouseEvent *event) { int cv_event = -1, flags = 0; QPoint pt = event->pos(); - + //icvmouseHandler: pass parameters for cv_event, flags icvmouseHandler(event, mouse_dbclick, cv_event, flags); icvmouseProcessing(QPointF(pt), cv_event, flags); - + QWidget::mouseDoubleClickEvent(event); } @@ -1261,32 +1357,32 @@ void ViewPort::mouseMoveEvent(QMouseEvent *event) { int cv_event = -1, flags = 0; QPoint pt = event->pos(); - + //icvmouseHandler: pass parameters for cv_event, flags icvmouseHandler(event, mouse_move, cv_event, flags); icvmouseProcessing(QPointF(pt), cv_event, flags); - - - if (matrixWorld.m11()>1 && event->buttons() == Qt::LeftButton) + + + if (param_matrixWorld.m11()>1 && event->buttons() == Qt::LeftButton) { - QPointF dxy = (pt - positionGrabbing)/matrixWorld.m11(); - + QPointF dxy = (pt - positionGrabbing)/param_matrixWorld.m11(); + positionGrabbing = event->pos(); - + moveView(dxy); } - + //I update the statusbar here because if the user does a cvWaitkey(0) (like with inpaint.cpp) //the status bar will only be repaint when a click occurs. viewport()->update(); - + QWidget::mouseMoveEvent(event); } //up, down, dclick, move void ViewPort::icvmouseHandler(QMouseEvent *event, type_mouse_event category, int &cv_event, int &flags) { - + switch(event->modifiers()) { case Qt::ShiftModifier: @@ -1306,7 +1402,7 @@ void ViewPort::icvmouseHandler(QMouseEvent *event, type_mouse_event category, in break; default:; } - + switch(event->button()) { case Qt::LeftButton: @@ -1332,10 +1428,10 @@ void ViewPort::icvmouseProcessing(QPointF pt, int cv_event, int flags) matrixWorld_inv.map(pt.x(),pt.y(),&pfx,&pfy); mouseCoordinate.rx()=floor(pfx); mouseCoordinate.ry()=floor(pfy); - + if (on_mouse) on_mouse( cv_event, mouseCoordinate.x(),mouseCoordinate.y(), flags, on_mouse_param ); - + } QSize ViewPort::sizeHint() const @@ -1350,75 +1446,75 @@ QSize ViewPort::sizeHint() const void ViewPort::resizeEvent ( QResizeEvent *event) { - + controlImagePosition(); //ratioX=float(image2Draw_ipl->width)/float(width()); //ratioY=float(image2Draw_ipl->height)/float(height()); ratioX=width()/float(image2Draw_ipl->width); ratioY=height()/float(image2Draw_ipl->height); - - if(keepRatio == CV_WINDOW_KEEPRATIO)//to keep the same aspect ratio + + if(param_keepRatio == CV_WINDOW_KEEPRATIO)//to keep the same aspect ratio { QSize newSize = QSize(image2Draw_ipl->width,image2Draw_ipl->height); newSize.scale(event->size(),Qt::KeepAspectRatio); - + //imageWidth/imageHeight = newWidth/newHeight +/- epsilon //ratioX = ratioY +/- epsilon //||ratioX - ratioY|| = epsilon if (fabs(ratioX - ratioY)*100> ratioX)//avoid infinity loop / epsilon = 1% of ratioX { resize(newSize); - + //move to the middle //newSize get the delta offset to place the picture in the middle of its parent newSize= (event->size()-newSize)/2; move(newSize.width(),newSize.height()); } } - + return QGraphicsView::resizeEvent(event); } void ViewPort::paintEvent(QPaintEvent* event) { QPainter myPainter(viewport()); - myPainter.setWorldTransform(matrixWorld); - + myPainter.setWorldTransform(param_matrixWorld); + draw2D(&myPainter); - - + + #if defined(OPENCV_GL) - if (mode == CV_MODE_OPENGL && false)//disable it for now + if ( mode_display == CV_MODE_OPENGL && false)//disable it for now { setGL(this->width(),this->height()); draw3D(); unsetGL(); } #endif - + //in mode zoom/panning - if (matrixWorld.m11()>1) + if (param_matrixWorld.m11()>1) { - + myPainter.setWorldMatrixEnabled (false ); - - if (matrixWorld.m11()>=threshold_zoom_img_region) + + if (param_matrixWorld.m11()>=threshold_zoom_img_region) drawImgRegion(&myPainter); - + drawViewOverview(&myPainter); - + } - + //for statusbar drawStatusBar(); - + //for information overlay if (drawInfo) { myPainter.setWorldMatrixEnabled (false ); drawInstructions(&myPainter); } - + QGraphicsView::paintEvent(event); } @@ -1427,7 +1523,7 @@ void ViewPort::draw2D(QPainter *painter) image2Draw_qt = QImage((uchar*) image2Draw_ipl->imageData, image2Draw_ipl->width, image2Draw_ipl->height,QImage::Format_RGB888); // painter->drawImage(0,0,image2Draw_qt.scaled(this->width(),this->height(),Qt::KeepAspectRatio)); painter->drawImage(0,0,image2Draw_qt.scaled(this->width(),this->height(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)); - + } @@ -1440,7 +1536,7 @@ void ViewPort::drawStatusBar() mouseCoordinate.y()height) { QRgb rgbValue = image2Draw_qt.pixel(mouseCoordinate); - + if (nbChannelOriginImage==3) { centralWidget->myBar_msg->setText(tr("Coordinate: %1x%2 ~ ") @@ -1463,93 +1559,92 @@ void ViewPort::drawStatusBar() void ViewPort::drawImgRegion(QPainter *painter) { - qreal offsetX = matrixWorld.dx()/matrixWorld.m11(); + qreal offsetX = param_matrixWorld.dx()/param_matrixWorld.m11(); offsetX = offsetX - floor(offsetX); - qreal offsetY = matrixWorld.dy()/matrixWorld.m11(); + qreal offsetY = param_matrixWorld.dy()/param_matrixWorld.m11(); offsetY = offsetY - floor(offsetY); - + QSize view = size(); QVarLengthArray linesX; - for (qreal x = offsetX*matrixWorld.m11(); x < view.width(); x += matrixWorld.m11() ) - linesX.append(QLineF(x, 0, x, view.height())); - + for (qreal x = offsetX*param_matrixWorld.m11(); x < view.width(); x += param_matrixWorld.m11() ) + linesX.append(QLineF(x, 0, x, view.height())); + QVarLengthArray linesY; - for (qreal y = offsetY*matrixWorld.m11(); y < view.height(); y += matrixWorld.m11() ) + for (qreal y = offsetY*param_matrixWorld.m11(); y < view.height(); y += param_matrixWorld.m11() ) linesY.append(QLineF(0, y, view.width(), y)); - - + + QFont f = painter->font(); - f.setPointSize(threshold_zoom_img_region/3+(matrixWorld.m11()-threshold_zoom_img_region)/6); + f.setPixelSize(6+(param_matrixWorld.m11()-threshold_zoom_img_region)/5); //f.setStretch(0); painter->setFont(f); QString val; QRgb rgbValue; - + QPointF point1;//sorry, I do not know how to name it QPointF point2;//idem - - - for (int j=-1;j= 0 && point2.y() >= 0) rgbValue = image2Draw_qt.pixel(QPoint(point2.x(),point2.y())); else rgbValue = qRgb(0,0,0); - - const int margin = 1; + if (nbChannelOriginImage==3) { val = tr("%1").arg(qRed(rgbValue)); painter->setPen(QPen(Qt::red, 1)); - painter->drawText(QRect(point1.x(),point1.y()+margin,matrixWorld.m11(),matrixWorld.m11()/3), + painter->drawText(QRect(point1.x(),point1.y(),param_matrixWorld.m11(),param_matrixWorld.m11()/3), Qt::AlignCenter, val); - + val = tr("%1").arg(qGreen(rgbValue)); painter->setPen(QPen(Qt::green, 1)); - painter->drawText(QRect(point1.x(),point1.y()+matrixWorld.m11()/3+margin,matrixWorld.m11(),matrixWorld.m11()/3), + painter->drawText(QRect(point1.x(),point1.y()+param_matrixWorld.m11()/3,param_matrixWorld.m11(),param_matrixWorld.m11()/3), Qt::AlignCenter, val); - + val = tr("%1").arg(qBlue(rgbValue)); painter->setPen(QPen(Qt::blue, 1)); - painter->drawText(QRect(point1.x(),point1.y()+2*matrixWorld.m11()/3+margin,matrixWorld.m11(),matrixWorld.m11()/3), + painter->drawText(QRect(point1.x(),point1.y()+2*param_matrixWorld.m11()/3,param_matrixWorld.m11(),param_matrixWorld.m11()/3), Qt::AlignCenter, val); - + } else { - + val = tr("%1").arg(qRed(rgbValue)); - painter->drawText(QRect(point1.x(),point1.y(),matrixWorld.m11(),matrixWorld.m11()), + painter->drawText(QRect(point1.x(),point1.y(),param_matrixWorld.m11(),param_matrixWorld.m11()), Qt::AlignCenter, val); } } - + painter->setPen(QPen(Qt::black, 1)); painter->drawLines(linesX.data(), linesX.size()); painter->drawLines(linesY.data(), linesY.size()); - + } void ViewPort::drawViewOverview(QPainter *painter) { QSize viewSize = size(); viewSize.scale ( 100, 100,Qt::KeepAspectRatio ); - + const int margin = 5; - + //draw the image's location painter->setBrush(QColor(0, 0, 0, 127)); painter->setPen(Qt::darkGreen); painter->drawRect(QRect(width()-viewSize.width()-margin, 0,viewSize.width(),viewSize.height())); - + //daw the view's location inside the image - qreal ratioSize = 1/matrixWorld.m11(); + qreal ratioSize = 1/param_matrixWorld.m11(); qreal ratioWindow = (qreal)(viewSize.height())/(qreal)(size().height()); painter->setPen(Qt::darkBlue); painter->drawRect(QRectF(width()-viewSize.width()-positionCorners.left()*ratioSize*ratioWindow-margin, @@ -1563,7 +1658,7 @@ void ViewPort::drawInstructions(QPainter *painter) { QFontMetrics metrics = QFontMetrics(font()); int border = qMax(4, metrics.leading()); - + QRect rect = metrics.boundingRect(0, 0, width() - 2*border, int(height()*0.125), Qt::AlignCenter | Qt::TextWordWrap, infoText); painter->setRenderHint(QPainter::TextAntialiasing); @@ -1606,13 +1701,13 @@ void ViewPort::initGL() void ViewPort::icvgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) { GLdouble xmin, xmax, ymin, ymax; - + ymax = zNear * tan(fovy * M_PI / 360.0); ymin = -ymax; xmin = ymin * aspect; xmax = ymax * aspect; - - + + glFrustum(xmin, xmax, ymin, ymax, zNear, zFar); } @@ -1639,15 +1734,15 @@ void ViewPort::draw3D() { //draw scene here glLoadIdentity(); - + glTranslated(0.0, 0.0, -1.0); // QVector3D p = convert(positionMouse); //glTranslated(p.x(),p.y(),p.z()); - + glRotatef( 55, 1, 0, 0 ); glRotatef( 45, 0, 1, 0 ); glRotatef( 0, 0, 0, 1 ); - + static const int coords[6][4][3] = { { { +1, -1, -1 }, { -1, -1, -1 }, { -1, +1, -1 }, { +1, +1, -1 } }, { { +1, +1, -1 }, { -1, +1, -1 }, { -1, +1, +1 }, { +1, +1, +1 } }, @@ -1656,7 +1751,7 @@ void ViewPort::draw3D() { { +1, -1, +1 }, { -1, -1, +1 }, { -1, -1, -1 }, { +1, -1, -1 } }, { { -1, -1, +1 }, { +1, -1, +1 }, { +1, +1, +1 }, { -1, +1, +1 } } }; - + for (int i = 0; i < 6; ++i) { glColor3ub( i*20, 100+i*10, i*42 ); glBegin(GL_QUADS); diff --git a/modules/highgui/src/window_QT.h b/modules/highgui/src/window_QT.h index 86bbbef3c4..d739994f6a 100644 --- a/modules/highgui/src/window_QT.h +++ b/modules/highgui/src/window_QT.h @@ -69,6 +69,7 @@ #include #include #include +#include //Macro here #define CV_MODE_NORMAL 0 @@ -108,7 +109,9 @@ public slots: double getPropWindow(QString name); void setPropWindow(QString name, double flags ); double getRatioWindow(QString name); - void setRatioWindow(QString name, double arg2 ); + void setRatioWindow(QString name, double arg2 ); + void saveWindowParameters(QString name); + void loadWindowParameters(QString name); }; class CvTrackbar : public QHBoxLayout @@ -133,6 +136,7 @@ private: CvTrackbarCallback callback; QPointer parent; int* dataSlider; + }; class CvWindow : public QWidget @@ -146,37 +150,39 @@ public: void updateImage(void* arr); void displayInfo(QString text, int delayms ); void displayStatusBar(QString text, int delayms ); + void readSettings(); + void writeSettings(); ViewPort* getView(); - QString name; - int flags; QPointer layout; QPointer myBar; QPointer myBar_msg; - //QPointer layout; + + //parameters (will be save/load) + QString param_name; + int param_flags; + protected: - void readSettings(); - void writeSettings(); - virtual void keyPressEvent(QKeyEvent *event); private: QPointer myview; + QPointer shortcutZ; + QPointer shortcutPlus; + QPointer shortcutMinus; + QPointer shortcutLeft; + QPointer shortcutRight; + QPointer shortcutUp; + QPointer shortcutDown; - int status;//0 normal, 1 fullscreen (YV) - QPointer shortcut_r_Zoom; - QPointer shortcut_imgRegion; - QPointer shortcut_Plus; - QPointer shortcut_Minus; - QPointer shortcut_Left; - QPointer shortcut_Right; - QPointer shortcut_Up; - QPointer shortcut_Down; + void icvLoadTrackbars(QSettings *settings); + void icvSaveTrackbars(QSettings *settings); }; + enum type_mouse_event {mouse_up = 0, mouse_down = 1, mouse_dbclick = 2, mouse_move = 3}; static const int tableMouseButtons[][3]={ @@ -186,6 +192,7 @@ static const int tableMouseButtons[][3]={ {CV_EVENT_MOUSEMOVE,CV_EVENT_MOUSEMOVE,CV_EVENT_MOUSEMOVE} //mouse_move }; + class ViewPort : public QGraphicsView { Q_OBJECT @@ -195,20 +202,24 @@ public: void updateImage(void* arr); void startDisplayInfo(QString text, int delayms); void setMouseCallBack(CvMouseCallback m, void* param); + int getRatio(); + void setRatio(int arg); + + //parameters (will be save/load) + QTransform param_matrixWorld; + + int param_keepRatio; IplImage* image2Draw_ipl; QImage image2Draw_qt; + int mode_display;//opengl or native int nbChannelOriginImage; - void setRatio(int flags); - int getRatio(); - public slots: //reference: //http://www.qtcentre.org/wiki/index.php?title=QGraphicsView:_Smooth_Panning_and_Zooming //http://doc.qt.nokia.com/4.6/gestures-imagegestures-imagewidget-cpp.html - void scaleView(qreal scaleFactor, QPointF center, bool process1stParam); - void imgRegion( ); + void scaleView(qreal scaleFactor, QPointF center); void moveView(QPointF delta); void resetZoom(); void ZoomIn(); @@ -220,21 +231,14 @@ public slots: void resizeEvent ( QResizeEvent * ); private: - QPoint deltaOffset; - QPoint computeOffset(); QPoint mouseCoordinate; QPointF positionGrabbing; - QRect positionCorners; - QTransform matrixWorld; + QRect positionCorners; QTransform matrixWorld_inv; float ratioX, ratioY; - CvMouseCallback on_mouse; void* on_mouse_param; - int mode; - int keepRatio; - bool isSameSize(IplImage* img1,IplImage* img2); QSize sizeHint() const; QPointer centralWidget; @@ -270,64 +274,66 @@ private slots: void stopDisplayInfo(); }; + + //here css for trackbar /* from http://thesmithfam.org/blog/2010/03/10/fancy-qslider-stylesheet */ static const QString str_Trackbar_css = QString("") -+ "QSlider::groove:horizontal {" -+ "border: 1px solid #bbb;" -+ "background: white;" -+ "height: 10px;" -+ "border-radius: 4px;" -+ "}" + + "QSlider::groove:horizontal {" + + "border: 1px solid #bbb;" + + "background: white;" + + "height: 10px;" + + "border-radius: 4px;" + + "}" -+ "QSlider::sub-page:horizontal {" -+ "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," -+ "stop: 0 #66e, stop: 1 #bbf);" -+ "background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1," -+ "stop: 0 #bbf, stop: 1 #55f);" -+ "border: 1px solid #777;" -+ "height: 10px;" -+ "border-radius: 4px;" -+ "}" + + "QSlider::sub-page:horizontal {" + + "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," + + "stop: 0 #66e, stop: 1 #bbf);" + + "background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1," + + "stop: 0 #bbf, stop: 1 #55f);" + + "border: 1px solid #777;" + + "height: 10px;" + + "border-radius: 4px;" + + "}" -+ "QSlider::add-page:horizontal {" -+ "background: #fff;" -+ "border: 1px solid #777;" -+ "height: 10px;" -+ "border-radius: 4px;" -+ "}" + + "QSlider::add-page:horizontal {" + + "background: #fff;" + + "border: 1px solid #777;" + + "height: 10px;" + + "border-radius: 4px;" + + "}" -+ "QSlider::handle:horizontal {" -+ "background: qlineargradient(x1:0, y1:0, x2:1, y2:1," -+ "stop:0 #eee, stop:1 #ccc);" -+ "border: 1px solid #777;" -+ "width: 13px;" -+ "margin-top: -2px;" -+ "margin-bottom: -2px;" -+ "border-radius: 4px;" -+ "}" + + "QSlider::handle:horizontal {" + + "background: qlineargradient(x1:0, y1:0, x2:1, y2:1," + + "stop:0 #eee, stop:1 #ccc);" + + "border: 1px solid #777;" + + "width: 13px;" + + "margin-top: -2px;" + + "margin-bottom: -2px;" + + "border-radius: 4px;" + + "}" -+ "QSlider::handle:horizontal:hover {" -+ "background: qlineargradient(x1:0, y1:0, x2:1, y2:1," -+ "stop:0 #fff, stop:1 #ddd);" -+ "border: 1px solid #444;" -+ "border-radius: 4px;" -+ "}" + + "QSlider::handle:horizontal:hover {" + + "background: qlineargradient(x1:0, y1:0, x2:1, y2:1," + + "stop:0 #fff, stop:1 #ddd);" + + "border: 1px solid #444;" + + "border-radius: 4px;" + + "}" -+ "QSlider::sub-page:horizontal:disabled {" -+ "background: #bbb;" -+ "border-color: #999;" -+ "}" + + "QSlider::sub-page:horizontal:disabled {" + + "background: #bbb;" + + "border-color: #999;" + + "}" -+ "QSlider::add-page:horizontal:disabled {" -+ "background: #eee;" -+ "border-color: #999;" -+ "}" + + "QSlider::add-page:horizontal:disabled {" + + "background: #eee;" + + "border-color: #999;" + + "}" -+ "QSlider::handle:horizontal:disabled {" -+ "background: #eee;" -+ "border: 1px solid #aaa;" -+ "border-radius: 4px;" -+ "}"; + + "QSlider::handle:horizontal:disabled {" + + "background: #eee;" + + "border: 1px solid #aaa;" + + "border-radius: 4px;" + + "}"; #endif