QOpenGLWidget strage result
-
I update my app, from QT4.8 to QT5.12. GLwidget is obsolete so I use QOpenGLWidget instead and I make a Subclass for drive my widget and webcam.
The problem:
When the GLwidget is active the rendering slows down to 5/10 fps and sometimes it shows instead that a whole image shows 8 identical images (or 6 I don't understand is very fast and like a noise). If, on the other hand, the same stream is on a window opened with opencv and GLwidget is not active (I have a page with GLwidget and a page for debugging) the video runs at 35fps without disturbances.
My cpp file:
#include "mainwindow.h" #include "ui_mainwindow.h" #include "glwidg.h" #include <QThread> #include <QtCore> #include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrentRun> #include <QFuture> #include <QFutureWatcher> #include <QtWidgets> #include <QtWidgets/QAction> #include <QtWidgets/QWidget> #include <QtWidgets/QWidgetAction> #include <QtWidgetsDepends> #include <QtWidgetsVersion> #include <QTableWidget> #include <QTableWidgetItem> #include <QTableWidgetSelectionRange> #include <QTableView> #include <opencv2/opencv.hpp> #include <opencv2/highgui.hpp> #include <iostream> #include <math.h> #include <stdio.h> #include <opencv2/opencv.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/core/core.hpp> #include <sstream> #include <string.h> #include <GL/glu.h> #include <GL/glut.h> #include <GL/freeglut.h> #include <GL/glu.h> #include <QtOpenGL/QGLWidget> #include <QtOpenGL/QtOpenGL> #include <QtOpenGL/QGLBuffer> #include <GLES3/gl3.h> #include <QOpenGLFunctions> #include <QtOpenGL/QGLBuffer> #include <QtOpenGL/QtOpenGL> #include <QTime> #include <QTimer> #include <QDebug> QImage camera000; GLuint texture[1]; QImage GL_formatt; QImage qform; QImage qform1; int cambio1 = 0; cv::Mat imma2; cv::Mat imma3; int play = 0; GLwidg::GLwidg(QWidget *parent) : QOpenGLWidget(parent) { this->setAttribute(Qt::WA_DeleteOnClose); update(); } int GLwidg::xAtPress = 0; int GLwidg::yAtPress = 0; int GLwidg::xsend = 0; int GLwidg::ysend = 0; cv::Point GLwidg::SendMousePoint(0,0); void GLwidg::mouseMoveEvent(QMouseEvent * event) { xAtPress = event->x(); yAtPress = event->y(); xsend = round(xAtPress*1.422222222); ysend = round(yAtPress*1.2); SendMousePoint = cv::Point(xsend, ysend); emit MousePoint(SendMousePoint); } void GLwidg::paintGL() { //makeCurrent(); glClear(GL_COLOR_BUFFER_BIT); if (cambio1 == 0) { qform1.load("/home/mine/images/image480.png"); qq1frame = qform1.scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } else { qq1frame = qform1.scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } qqframe = qq1frame.mirrored(false, true); if(!qqframe.isNull()) /* use for render image but when active */ { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); qqframe = qqframe.scaled(QSize(480,360), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); // or do 2D texture mapping glMatrixMode(GL_MODELVIEW); /**/ glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0,qqframe.width(),qqframe.height(),0); glMatrixMode(GL_MODELVIEW); //glDisable(GL_DEPTH_TEST); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D( GL_TEXTURE_2D, 0, 4, qqframe.width(), qqframe.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, qqframe.bits() ); glBegin(GL_QUADS); glTexCoord2f(0,0); glVertex2f(0,qqframe.height()); glTexCoord2f(0,1); glVertex2f(0,0); glTexCoord2f(1,1); glVertex2f(qqframe.width(),0); glTexCoord2f(1,0); glVertex2f(qqframe.width(),qqframe.height()); glEnd(); glDisable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glFlush(); } if(qqframe.isNull()) { qform1.load("/home/mine/images/image480.png"); qq1frame = qform1.scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } update(); //qDebug() << "x: " << qqframe.width() << "y: " << qqframe.height(); } void GLwidg::donextcam() /* never use*/ { update(); } void GLwidg::imma_orig_r1(QImage qi1) /* use for update widget with new image captured from other thread and processed from opencv computation */ { //qDebug() << "new image to render ....."; cambio1 = 1; qform1 = qi1; //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //makeCurrent(); //paintGL(); update(); } void GLwidg::stopcam1(bool st1) /* use only for stop webcam */ { if (st1) { cambio1 = 0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //paintGL(); update(); } else { cambio1 = 1; } }
I am afraid that my code for rendering on textures is wrong and therefore generates the problem I reported .... Could someone tell me if there is any weirdness?
gfx
-
The problem was not on QOpenGLWidget function .... but on Mat2Qimage function that send image to QOpenGLWidget .... Mat2Qimage fucntion require "cost" mat on input .... my old function:
void thread::Mat2QImage(cv::Mat const& src) { if(!src.empty()) { //cv::Mat test33; <<<<<---------- the error cvtColor(src, test33, COLOR_BGR2RGB); QImage dest33 = QImage((uchar*)test33.data, test33.cols, test33.rows, test33.step, QImage::Format_RGB888); emit _img(dest33); } }
when declare test33 as static cv::Mat all problem disappear .... probabily old opencv3.2, old QT4 can correctly convert image format without problem .... now the street is less large ....
-
Hi,
You are using a constructor that does not copy the data hence you likely have an object lifetime issue.
Ensure you generate a copy of the QImage before emitting it and you should be good to go.
Note that if you do not change the size of the image, you could make dest33 a member variable and then use it as a target for cvtColor.