From c3eb7881f17afb992896aed92549afb0a5ea4b75 Mon Sep 17 00:00:00 2001 From: Yannick Verdie Date: Mon, 12 Jul 2010 11:04:26 +0000 Subject: [PATCH] New functions with QT GUI: - 3 new points mostly done: - OpenGL support enabled (windows are rendered using GPU) - Save current screen (with overlay and so on...) with shortcut CTRL+S - Text rendering (with any system font, and possibility to set the style - normal, italic,... - the weight - normal, bold, ... - the color, the spacing between letters, and so on...) --- CMakeLists.txt | 2 +- modules/core/include/opencv2/core/core_c.h | 17 +- .../include/opencv2/highgui/highgui.hpp | 11 +- .../include/opencv2/highgui/highgui_c.h | 26 ++- modules/highgui/src/precomp.hpp | 1 - modules/highgui/src/window.cpp | 12 ++ modules/highgui/src/window_QT.cpp | 157 +++++++++++++----- modules/highgui/src/window_QT.h | 8 +- 8 files changed, 173 insertions(+), 61 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cea8f1e29..87e4b5842 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -510,7 +510,7 @@ if (QT4_FOUND AND AUTOSWITCH_QT) set(WITH_QT ON CACHE BOOL "Build with QT Backend support") find_package (OpenGL QUIET) if (QT_QTOPENGL_FOUND AND OPENGL_FOUND) - set(WITH_QT_OPENGL ON CACHE BOOL "Add OpenGL extention to QT") + set(WITH_QT_OPENGL ON CACHE BOOL "Add OpenGL extension to QT") endif() endif() diff --git a/modules/core/include/opencv2/core/core_c.h b/modules/core/include/opencv2/core/core_c.h index c38cc431e..cfd8bf497 100644 --- a/modules/core/include/opencv2/core/core_c.h +++ b/modules/core/include/opencv2/core/core_c.h @@ -1370,18 +1370,21 @@ CVAPI(int) cvInitLineIterator( const CvArr* image, CvPoint pt1, CvPoint pt2, #define CV_FONT_VECTOR0 CV_FONT_HERSHEY_SIMPLEX + /* Font structure */ typedef struct CvFont { - int font_face; /* =CV_FONT_* */ - const int* ascii; /* font data and metrics */ + const char* nameFont; //Qt:nameFont + CvScalar color; //Qt:ColorFont -> cvScalar(blue_component, green_component, red\_component[, alpha_component]) + int font_face; //Qt: bool italic /* =CV_FONT_* */ + const int* ascii; /* font data and metrics */ const int* greek; const int* cyrillic; float hscale, vscale; - float shear; /* slope coefficient: 0 - normal, >0 - italic */ - int thickness; /* letters thickness */ - float dx; /* horizontal interval between letters */ - int line_type; + float shear; /* slope coefficient: 0 - normal, >0 - italic */ + int thickness; //Qt: weight /* letters thickness */ + float dx; /* horizontal interval between letters */ + int line_type; //Qt: PointSize } CvFont; @@ -1408,6 +1411,8 @@ CVAPI(void) cvPutText( CvArr* img, const char* text, CvPoint org, CVAPI(void) cvGetTextSize( const char* text_string, const CvFont* font, CvSize* text_size, int* baseline ); + + /* Unpacks color value, if arrtype is CV_8UC?, is treated as packed color value, otherwise the first channels (depending on arrtype) of destination scalar are set to the same value = */ diff --git a/modules/highgui/include/opencv2/highgui/highgui.hpp b/modules/highgui/include/opencv2/highgui/highgui.hpp index 97de19c2a..fff34cff6 100644 --- a/modules/highgui/include/opencv2/highgui/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui/highgui.hpp @@ -64,14 +64,21 @@ CV_EXPORTS void setWindowProperty(const string& winname, int prop_id, double pro CV_EXPORTS double getWindowProperty(const string& winname, int prop_id);//YV -//Only for QT +//Only for Qt +//------------------------ +CV_EXPORTS void addText( const Mat& img, const char* text, Point org, CvFont font); + CV_EXPORTS void displayOverlay(const string& winname, const string& text, int delayms); CV_EXPORTS void displayStatusBar(const string& winname, const string& text, int delayms); + +typedef void (CV_CDECL *OpenGLCallback)(void* userdata); +CV_EXPORTS void createOpenGLCallback(const string& winname, CvOpenGLCallback callbackOpenGL, void* userdata CV_DEFAULT(0)); + 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(); - +//------------------------- CV_EXPORTS void imshow( const string& winname, const Mat& mat ); diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index 2f0c5047c..4c4c35e04 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -57,9 +57,33 @@ extern "C" { * Basic GUI functions * \****************************************************************************************/ //YV -//-----------New for QT +//-----------New for Qt +/* For font */ +enum { CV_FONT_LIGHT = 25,//QFont::Light, + CV_FONT_NORMAL = 50,//QFont::Normal, + CV_FONT_DEMIBOLD = 63,//QFont::DemiBold, + CV_FONT_BOLD = 75,//QFont::Bold, + CV_FONT_BLACK = 87 //QFont::Black +}; + +enum { CV_STYLE_NORMAL = 0,//QFont::StyleNormal, + CV_STYLE_ITALIC = 1,//QFont::StyleItalic, + CV_STYLE_OBLIQUE = 2 //QFont::StyleOblique +}; +/* ---------*/ + +//for color cvScalar(blue_component, green_component, red\_component[, alpha_component]) +//and alpha= 0 <-> 0xFF (not transparent <-> transparent) +CVAPI(CvFont) cvFont_Qt(const char* nameFont, int pointSize CV_DEFAULT(-1), CvScalar color = cvScalarAll(0), int weight CV_DEFAULT(CV_FONT_NORMAL), int style CV_DEFAULT(CV_STYLE_NORMAL), int spacing CV_DEFAULT(0)); + +CVAPI(void) cvAddText( CvArr* img, const char* text, CvPoint org, CvFont *arg2); + CVAPI(void) cvDisplayOverlay(const char* name, const char* text, int delayms); CVAPI(void) cvDisplayStatusBar(const char* name, const char* text, int delayms); + +typedef void (CV_CDECL *CvOpenGLCallback)(void* userdata); +CVAPI(void) cvCreateOpenGLCallback( const char* window_name, CvOpenGLCallback callbackOpenGL, void* userdata CV_DEFAULT(NULL)); + 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[]); diff --git a/modules/highgui/src/precomp.hpp b/modules/highgui/src/precomp.hpp index ad35839f5..0d8764d35 100644 --- a/modules/highgui/src/precomp.hpp +++ b/modules/highgui/src/precomp.hpp @@ -170,7 +170,6 @@ void cvSetModeWindow_W32(const char* name, double prop_value); void cvSetModeWindow_GTK(const char* name, double prop_value); void cvSetModeWindow_CARBON(const char* name, double prop_value); - //for QT #if defined (HAVE_QT) double cvGetModeWindow_QT(const char* name); diff --git a/modules/highgui/src/window.cpp b/modules/highgui/src/window.cpp index 25ae51e4d..a1dd61cb6 100644 --- a/modules/highgui/src/window.cpp +++ b/modules/highgui/src/window.cpp @@ -189,11 +189,23 @@ int startWindowThread() } #if defined (HAVE_QT) + +void addText( const Mat& img, const string& text, Point org, CvFont font) +{ + CvMat _img = img; + cvAddText( &_img, text.c_str(), CvPoint(org),&font); +} + void displayStatusBar(const string& name, const string& text, int delayms) { cvDisplayStatusBar(name.c_str(),text.c_str(), delayms); } +void createOpenGLCallback(const string& name, OpenGLCallback callback, void* param) +{ + cvCreateOpenGLCallback(name.c_str(),callback, param); +} + void displayOverlay(const string& name, const string& text, int delayms) { cvDisplayOverlay(name.c_str(),text.c_str(), delayms); diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index e11f3f766..770aea694 100755 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -51,10 +51,44 @@ static bool multiThreads = false; static int last_key = -1; QWaitCondition key_pressed; QMutex mutexKey; - static const unsigned int threshold_zoom_img_region = 15;//the minimum zoom value to start displaying the values' grid //end static and global + + +CV_IMPL CvFont cvFont_Qt(const char* nameFont, int pointSize,CvScalar color,int weight,int style, int spacing) +{ + + /* + //nameFont <- only Qt + //CvScalar color <- only Qt (blue_component, green_component, red\_component[, alpha_component]) + int font_face;//<- style in Qt + const int* ascii; + const int* greek; + const int* cyrillic; + float hscale, vscale; + float shear; + int thickness;//<- weight in Qt + float dx;//spacing letter in Qt (0 default) in pixel + int line_type;//<- pointSize in Qt + */ + CvFont f = {nameFont,color,style,NULL,NULL,NULL,0,0,0,weight,spacing,pointSize}; + return f; +} + + + +CV_IMPL void cvAddText( CvArr* img, const char* text, CvPoint org, CvFont* font) +{ + QMetaObject::invokeMethod(&guiMainThread, + "putText", + Qt::AutoConnection, + Q_ARG(void*, (void*) img), + Q_ARG(QString,QString(text)), + Q_ARG(QPoint, QPoint(org.x,org.y)), + Q_ARG(void*,(void*) font)); +} + double cvGetRatioWindow_QT(const char* name) { double result = -1; @@ -299,10 +333,10 @@ CV_IMPL int icvInitSystem() new QApplication(parameterSystemC,parameterSystemV); wasInitialized = 1; - qDebug()<<"init done"<setQuitOnLastWindowClosed ( false );//maybe the user would like to access this setting } +void GuiReceiver::putText(void* arg1, QString text, QPoint org, void* arg2) +{ + CV_Assert(arg1); + + IplImage* img = (IplImage*)arg1; + + //for now, only support QImage::Format_RGB888 + if (img->depth !=IPL_DEPTH_8U || img->nChannels != 3) + return; + + CvFont* font = (CvFont*)arg2; + + + + QImage qimg((uchar*) img->imageData, img->width, img->height,QImage::Format_RGB888); + QPainter qp(&qimg); + if (font) + { + QFont f(font->nameFont, font->line_type/*PointSize*/, font->thickness/*weight*/); + f.setStyle((QFont::Style)font->font_face/*style*/); + f.setLetterSpacing ( QFont::AbsoluteSpacing, font->dx/*spacing*/ ); + //cvScalar(blue_component, green_component, red\_component[, alpha_component]) + //Qt map non-transparent to 0xFF and transparent to 0 + //OpenCV scalar is the reverse, so 255-font->color.val[3] + qp.setPen(QColor(font->color.val[2],font->color.val[1],font->color.val[0],255-font->color.val[3])); + qp.setFont ( f ); + } + qp.drawText (org, text ); + qp.end(); +} + void GuiReceiver::saveWindowParameters(QString name) { QPointer w = icvFindWindowByName( name.toLatin1().data() ); if (w) - w->writeSettings(); + w->writeSettings(); } void GuiReceiver::loadWindowParameters(QString name) @@ -511,7 +570,7 @@ void GuiReceiver::loadWindowParameters(QString name) QPointer w = icvFindWindowByName( name.toLatin1().data() ); if (w) - w->readSettings(); + w->readSettings(); } double GuiReceiver::getRatioWindow(QString name) @@ -625,13 +684,6 @@ void GuiReceiver::createWindow( QString name, int flags ) new CvWindow(name, flags); } -void GuiReceiver::refreshEvents() -{ - QAbstractEventDispatcher::instance(qApp->instance()->thread())->processEvents(QEventLoop::AllEvents); - //qDebug()<<"refresh ?"<processEvents(QEventLoop::AllEvents); -} - void GuiReceiver::timeOut() { _bTimeOut = true; @@ -805,7 +857,7 @@ void CvTrackbar::createDialog() bool ok= false; - //crash if I access the value directly to give them to QInputDialog, so do a copy first. + //crash if I access the values directly and give them to QInputDialog, so do a copy first. int value = slider->value(); int step = slider->singleStep(); int min = slider->minimum(); @@ -1142,15 +1194,14 @@ ViewPort::ViewPort(CvWindow* arg, int arg2, int arg3) positionCorners = QRect(0,0,size().width(),size().height()); on_mouse = NULL; mouseCoordinate = QPoint(-1,-1); - on_openGL = NULL; + on_openGL_draw3D = NULL; #if defined(OPENCV_GL) if ( mode_display == CV_MODE_OPENGL) { - QGLWidget* wGL = new QGLWidget(QGLFormat(QGL::SampleBuffers)); - setViewport(wGL); - + //QGLWidget* wGL = new QGLWidget(QGLFormat(QGL::SampleBuffers)); + setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); initGL(); } #endif @@ -1192,16 +1243,30 @@ void ViewPort::saveView() // Save it.. if (QString::compare(extension, "png", Qt::CaseInsensitive) == 0) + { image2Draw_qt_resized.save(fileName, "PNG"); + return; + } if (QString::compare(extension, "jpg", Qt::CaseInsensitive) == 0) + { image2Draw_qt_resized.save(fileName, "JPG"); + return; + } if (QString::compare(extension, "bmp", Qt::CaseInsensitive) == 0) + { image2Draw_qt_resized.save(fileName, "BMP"); + return; + } if (QString::compare(extension, "jpeg", Qt::CaseInsensitive) == 0) + { image2Draw_qt_resized.save(fileName, "JPEG"); + return; + } + + qDebug()<<"file extension not recognized, please choose between JPG, JPEG, BMP or PNG"; } } @@ -1289,10 +1354,11 @@ inline bool ViewPort::isSameSize(IplImage* img1,IplImage* img2) void ViewPort::updateImage(void* arr) { - if (!arr) - CV_Error(CV_StsNullPtr, "NULL arr pointer (in showImage)" ); - - IplImage* tempImage = (IplImage*)arr; + //if (!arr) + //CV_Error(CV_StsNullPtr, "NULL arr pointer (in showImage)" ); + CV_Assert(arr); + + IplImage* tempImage = (IplImage*)arr; if (!isSameSize(image2Draw_ipl,tempImage)) { @@ -1319,7 +1385,7 @@ void ViewPort::setMouseCallBack(CvMouseCallback m, void* param) void ViewPort::setOpenGLCallback(CvOpenGLCallback func,void* userdata) { - on_openGL = func; + on_openGL_draw3D = func; on_openGL_param = userdata; } @@ -1469,11 +1535,9 @@ void ViewPort::mouseMoveEvent(QMouseEvent *event) if (param_matrixWorld.m11()>1 && event->buttons() == Qt::LeftButton) { - QPointF dxy = (pt - positionGrabbing)/param_matrixWorld.m11(); - - positionGrabbing = event->pos(); - - moveView(dxy); + 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) @@ -1553,8 +1617,6 @@ void ViewPort::resizeEvent ( QResizeEvent *event) image2Draw_qt_resized = image2Draw_qt.scaled(this->width(),this->height(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation); 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); @@ -1590,11 +1652,16 @@ void ViewPort::paintEvent(QPaintEvent* event) draw2D(&myPainter); #if defined(OPENCV_GL) - if ( mode_display == CV_MODE_OPENGL && on_openGL) + if ( mode_display == CV_MODE_OPENGL && on_openGL_draw3D) { + myPainter.beginNativePainting(); + setGL(width(),height()); - draw3D(); + on_openGL_draw3D(on_openGL_param); + //draw3D(); unsetGL(); + + myPainter.endNativePainting(); } #endif @@ -1841,8 +1908,8 @@ void ViewPort::draw3D() //draw scene here glLoadIdentity(); - glTranslated(0.0, 0.0, -1.0); - // QVector3D p = convert(positionMouse); + glTranslated(10.0, 10.0, -1.0); + // QVector3D p = convert(mouseCoordinate); //glTranslated(p.x(),p.y(),p.z()); glRotatef( 55, 1, 0, 0 ); @@ -1859,12 +1926,12 @@ void ViewPort::draw3D() }; for (int i = 0; i < 6; ++i) { - glColor3ub( i*20, 100+i*10, i*42 ); - glBegin(GL_QUADS); - for (int j = 0; j < 4; ++j) { - glVertex3d(0.2 * coords[i][j][0], 0.2 * coords[i][j][1], 0.2 * coords[i][j][2]); - } - glEnd(); + glColor3ub( i*20, 100+i*10, i*42 ); + glBegin(GL_QUADS); + for (int j = 0; j < 4; ++j) { + glVertex3d(0.2 * coords[i][j][0], 0.2 * coords[i][j][1], 0.2 * coords[i][j][2]); + } + glEnd(); } } #endif diff --git a/modules/highgui/src/window_QT.h b/modules/highgui/src/window_QT.h index 9de74d602..b7d3dca37 100644 --- a/modules/highgui/src/window_QT.h +++ b/modules/highgui/src/window_QT.h @@ -88,13 +88,11 @@ enum { shortcut_zoom_normal = Qt::CTRL + Qt::Key_Z, shortcut_panning_up = Qt::CTRL + Qt::Key_Up, shortcut_panning_down = Qt::CTRL + Qt::Key_Down }; -//end enum -typedef void (CV_CDECL *CvOpenGLCallback)(void* userdata); +//end enum class CvWindow; class ViewPort; -//class CvTrackbar; class GuiReceiver : public QObject { @@ -118,7 +116,6 @@ public slots: void showImage(QString name, void* arr); void displayInfo( QString name, QString text, int delayms ); void displayStatusBar( QString name, QString text, int delayms ); - void refreshEvents(); void timeOut(); void toggleFullScreen(QString name, double flags ); double isFullScreen(QString name); @@ -129,6 +126,7 @@ public slots: void saveWindowParameters(QString name); void loadWindowParameters(QString name); void setOpenGLCallback(QString window_name, void* callbackOpenGL, void* userdata); + void putText(void* arg1, QString text, QPoint org, void* font); }; @@ -268,7 +266,7 @@ private: void* on_mouse_param; //for opengl callback - CvOpenGLCallback on_openGL; + CvOpenGLCallback on_openGL_draw3D; void* on_openGL_param; bool isSameSize(IplImage* img1,IplImage* img2);