Qt OpenGL framebuffer to image - qt

I'm drawing the framebuffer to an image, it used to work fine, however something broke and I have no idea what..
Any help would be great.
I get the error "QGLFramebufferObject: Framebuffer incomplete, missing attachment."
It seems to work intermittently.
VoxelEditor::VoxelEditor(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
makeCurrent();
catchFbo = new QGLFramebufferObject(PICTURE_SIZE, PICTURE_SIZE);
void VoxelEditor::renderToImage() {
saveGLState();
const int nrPics = 360 / DEGREES_BETWEEN_PICTURES;
for (int i = 0; i < nrPics; i++) {
catchFbo->bind();
glColorMask(true, true, true, true);
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_MULTISAMPLE);
glLoadIdentity();
GLfloat x = GLfloat(PICTURE_SIZE) / PICTURE_SIZE;
glFrustum(-x, +x, -1.0, +1.0, 1.0, 1000.0);
glViewport(0, 0, PICTURE_SIZE, PICTURE_SIZE);
drawScreenshot(i);
catchFbo->release();
QImage catchImage = catchFbo->toImage();
catchImage.save("object/test" + QString::number(i) + ".png");
}
glDisable(GL_MULTISAMPLE);
restoreGLState();
}

I solved this by putting the creation of the fbo in the rendertoimage call.
It seemed at creation it was valid and had the appropriate attachment, but at execution it failed..
Perhaps creating the fbo in the initializeGL call would work as well.

Have you check you buffer with isValid() method? Try to release buffer after call toImage() method.

Related

Can not print to paper in Qt

I can not print to paper for some reasone. So I have a functional printer. And I use the folowing code to print a qDialog and a few pictures out:
QPrinter printer;
QPainter painter;
painter.begin(&printer);
double xscale = printer.width() / double(window->width());
double yscale = printer.height() / double(window->height());
double scale = qMin(xscale, yscale);
painter.scale(scale, scale);
QPrintDialog printDialog(&printer, this);
if (printDialog.exec() == QDialog::Accepted) {
bool skip = true;
if(ui->generalInfos->isChecked()) {
//window is a QDialog I want to print out
window->render(&painter);
skip = false;
}
QList<Document *> docs;
if(worker) {
//a list with path to pictures
docs = worker->getDocuments();
}
for(auto document : docs) {
if(ui->Documents->isChecked(document->getID())) {
for(auto scan : document->getScans()) {
if(!skip) {
printer.newPage();
}
else {
skip = false;
}
painter.resetTransform();
const QImage image(scan);
const QPoint imageCoordinates(0,0);
xscale = printer.width() / double(image.width());
yscale = printer.height() / double(image.height());
scale = qMin(xscale, yscale);
painter.scale(scale, scale);
painter.drawImage(imageCoordinates,image);
}
}
}
}
painter.end();
and it doesn't work. Nothing is printed and Qt trows an error:
QWin32PrintEngine::newPage: EndPage failed (The parameter is incorrect.)
QWin32PrintEngine::end: EndPage failed (0x31210cf7) (The parameter is incorrect.)
can someone please help me?
If you simplify your code, you will probably find the solution.
So lets start with selecting the printer, then (afterwards!) start painting to the printer:
QPrinter printer;
QPrintDialog printDialog(&printer, this);
if (printDialog.exec() == QDialog::Accepted)
{
QPainter painter;
painter.begin(&printer);
window->render(&painter);
painter.end();
}
If this works, add more of your old code to the sketch above.
If it doesn't work, something else in your program or your environment (selected printer?) is wrong, so you need to extend your bug hunt beyond what you showed us here.

More than one QGLWidget simultaneous doesn't work for a video usage

I have a problem if I want to display a video using QGLWidget. With one instance it works, but it doesn't and widgets are black with multi-occurrence (usage in QGridLayout for example).
I subclass QGLWidget that way to play a video (by refreshing the QPixmap I want to show using my setCurrentImage method):
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
GLWidget(QGLWidget* shareWidget = 0, QWidget* parent = 0)
: QGLWidget(parent, shareWidget)
{
//...
// I do this because the QPixmap to refresh is produced in a different thread than UI thread.
connect(this, SIGNAL(updated()), this SLOT(update()));
}
//...
void setCurrentImage(const QPixmap& pixmap)
{
m_mutex.lock();
m_pixmap = pixmap;
m_mutex.unlock();
emit updated();
}
protected:
void initializeGL()
{
static const int coords[4][2] = {{ +1, -1 }, { -1, -1 }, { -1, +1 }, { +1, +1 }};
for(int j = 0; j < 4; ++j){
m_texCoords.append(QVector2D(j == 0 || j == 3, j == 0 || j == 1));
m_vertices.append(QVector2D(0.5 * coords[j][0], 0.5 * coords[j][1]));
}
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
#define PROGRAM_VERTEX_ATTRIBUTE 0
#define PROGRAM_TEXCOORD_ATTRIBUTE 1
QGLShader* vShader = new QGLShader(QGLShader::Vertex, this);
const char* szVShaderCode = /*...*/;
vShader->compileSourceCode(szVShaderCode);
QGLShader *fShader = new QGLShader(QGLShader::Fragment, this);
const char* szFShaderCode = /*...*/;
fShader->compileSourceCode(szFShaderCode);
m_pProgram = new QGLShaderProgram(this);
m_pProgram->addShader(vShader);
m_pProgram->addShader(fShader);
m_pProgram->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE);
m_pProgram->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE);
m_pProgram->link();
m_pProgram->bind();
m_pProgram->setUniformValue("texture", 0);
}
void paintGL()
{
qglClearColor(Qt::black);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// I use some uniform values to "modify" image
m_pProgram->setUniformValue(/*...*/);
//...
QMatrix4x4 m;
m.ortho(-0.5f, +0.5f, +0.5f, -0.5f, 4.0f, 15.0f);
m.translate(0.0f, 0.0f, -10.0f);
m_pProgram->setUniformValue("matrix", m);
m_pProgram->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
m_pProgram->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE);
m_pProgram->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, m_vertices.constData());
m_pProgram->setAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE, m_texCoords.constData());
glBindTexture(GL_TEXTURE_2D, m_texture);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
void resizeGL(int iWidth, int iHeight)
{
glViewport(0, 0, iWidth, iHeight);
}
private slots:
void update()
{
QPixmap pixmap;
m_mutex.lock();
pixmap = m_pixmap;
m_mutex.unlock();
m_texture = bindTexture(pixmap, GL_TEXTURE_2D);
updateGL();
}
private:
QMutex m_mutex;
QPixmap m_pixmap;
QVector<QVector2D> m_vertices;
QVector<QVector2D> m_texCoords;
QGLShaderProgram* m_pProgram;
};
Then, to simulate a multi thread rendering (each thread produces its own video images), I wrote these little classes.
The image producer class:
class ImageProducer : public QThread
{
Q_OBJECT
public:
ImageProducer(QGLWidget* pGLWidget)
: QThread(pGLWidget), m_pGLWidget(pGLWidget)
{
m_pixmap = QPixmap("fileName.jpg");
m_bMustStop = false;
}
protected:
void run()
{
while(!m_bMustStop){
static_cast<GLWidget*>(m_pGLWidget)->setCurrentImage(m_pixmap);
// Simulate a frame rate
msleep(1000 / /*FRAME_RATE*/);
}
}
private:
QGLWidget* m_pGLWidget;
QPixmap m_pixmap;
bool m_bMustStop;
};
And the rendering class:
#define ROWS 1
#define COLS 1
class Window : public QWidget
{
public:
Window()
{
QGridLayout* pMainLayout = new QGridLayout(this);
setLayout(pMainLayout);
for(int i = 0; i < ROWS; ++i){
for(int j = 0; j < COLS; ++j){
QGLWidget* pGLWidget = new GLWidget();
pMainLayout->addWidget(pGLWidget, i, j);
ImageProducer* pImageProducer = new ImageProducer(pGLWidget);
pImageProducer->start();
}
}
}
};
Ok stop with code samples ^^ Problem is with ROWS = 1 and COLS = 1 (see Window class) it works, but I have black widgets with other values... I'm lost, what do I miss?
Thanks!
EDIT: (context is always multi-GLWidget instance, all works fine with only one)
Strange thing I just discover: I overrode QGLWidget's mouseMoveEvent (so, in my GLWidget class) which simply calls updateGL();. And fact is when I press and move the mouse with the current code nothing happens. But if I replace (in my ImageProducer's run() method):
static_cast<GLWidget*>(m_pGLWidget)->setCurrentImage(m_pixmap);
By
static_cast<GLWidget*>(m_pGLWidget)->setCurrentImage(QPixmap("fileName.jpg"));
The image is refreshed in the current component as long as I move the mouse. When I release it, or do it in an other components, the background become black again.
I am writing down the answer after a chat with the OP, for the benefit of others. Here are the main topics that lead to a resolution of the issue.
Note: At the time of writing, the Qt OpenGL module is deprecated and its usage is discouraged. According to the official documentation the suggested approach is to use the OpenGL* classes in the GUI module.
Textures
The main issue with the code above is essentially due to the way the textures are handled.
First of all, the bindTexture() method does not bind in OpenGL terms, but actually create the OpenGL texture and upload the data passed as argument to it (QImage or QPixmap). That is confusing and can lead to serious issues. In the code posted by the OP, he is essentially leaking memory allocating a new texture at each frame update.
To ensure you are not leaking memory, you should at the least release the previously allocated texture, calling QGLWidget::deleteTexture.
However, it is worth to note that there are better approaches to avoid unnecessary memory fragmentation and inefficiency. In this case, the best approach is to allocate the texture once and simply update its content when necessary. This may not be possible directly with the API offered by the old Qt OpenGL module, but you can always mix Qt and native OpenGL code.
Context handling
Another issue is the way OpenGL context is handled. As a rule of thumb, one should always ensure the correct context is current before issuing commands to the OpenGL implementation. Sometimes, Qt does this for you automatically (i.e. before calling the paintGL() method).
In this case, we need to explicitly make the QGLWidget's context the current context before calling the bindTexture method, otherwise it will effect the last context that was made current. That is why only the last widget was showing something untill somewhone was triggering a makeCurrent call by interacting with the other widgets.
Threading
There are a couple of issues here. First of all, it is not safe to use a QPixmap object in a thread other than the GUI thread. QPixmap is designed to optimize pixmap blitting on screen. In this case, the pixmap is really just the frame to be uploaded to the OpenGL implementation, which handles all the rendering. So it is safe to use a QImage instead.
The other issue is that the GLWidget::setCurrentImage() and thus, the bindTexture method, are called directly from the run() method of the ImageProducer thread. This can't be because we need to make the widget context current, but it is not possible to call makeCurrent() from a thread other than the GUI thread (more details here).
A possible approach to solve this issue is to add a signal to ImageProducer to notify the frame has been updated, and connect this signal to the setCurrentImage() slot. Qt's signal-slot mechanism will ensure that the setCurrentImage is executed in the GLWidget thread, that is the GUI thread.
Code
Here are the suggested (and tested) modifications to the code posted above.
ImageProduer class
add the signal:
void imageUpdated(const QImage &image);
and emit it when the frame is updated:
void ImageProducer::run()
{
while(!m_bMustStop){
QImage frame(m_pixmap.width(), m_pixmap.height(), m_pixmap.format());
QPainter painter(&frame);
painter.drawImage(QPoint(), m_pixmap);
painter.setFont(QFont("sans-serif", 22));
painter.setPen(Qt::white);
painter.drawText(20, 50, QString("Frame: %1").arg(QString::number(_frameCount)));
painter.end();
emit imageUpdated(frame);
msleep(1000 / FRAME_RATE);
_frameCount++;
}
}
GLWidget class
ensure the setCurrentImage method handle the OpenGL context and destroy the old texture:
void GLWidget::setCurrentImage(const QImage& pixmap)
{
m_mutex.lock();
m_pixmap = pixmap;
m_mutex.unlock();
makeCurrent();
deleteTexture(m_texture);
m_texture = bindTexture(pixmap, GL_TEXTURE_2D);
doneCurrent();
emit updated();
}

How to set far clipping plane in QOpenGLWidget?

I am pretty new to Qt so sorry if this is a straight forward question.
I am using Qt 5.5 and trying to visualize a point cloud in QOpenGLWidget.
This is my header:
class PointCloudWindow : public QOpenGLWidget
{
public:
void setDepthMap(DepthMapGrabber* grabber);
protected:
void initializeGL();
void paintGL();
private:
QMatrix4x4 m_projection;
DepthMapGrabber* m_grabber;
};
and here is the corresponding cpp:
void PointCloudWindow::setDepthMap(DepthMapGrabber* grabber) {
m_grabber = grabber;
QTimer* updatePointCloud = new QTimer(this);
connect(updatePointCloud, SIGNAL(timeout()), SLOT(update()));
updatePointCloud->start();
}
void PointCloudWindow::initializeGL() {
glewInit(); // TODO: check for return value if error occured
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void PointCloudWindow::paintGL() {
m_grabber->getNextDepthFrame(); // TODO: check for return value if error occured
m_projection.setToIdentity();
m_projection.perspective(45.0f, width() / (float)height(), 0.01f, 100.0f);
if (m_grabber->getDepthMap()->cloud) {
glBegin(GL_POINTS);
glColor3f(0.8f, 0.8f, 0.8f);
for (UINT i = 0; i < m_grabber->getDepthMap()->size; ++i)
{
glVertex3f(m_grabber->getDepthMap()->cloud[i].X, m_grabber->getDepthMap()->cloud[i].Y, m_grabber->getDepthMap()->cloud[i].Z);
}
glEnd();
}
}
This is how my point cloud looks like after visualization:
My problem is that as you can see (monitor is cut in half for example) if a point has a z value, which is bigger, then 1.0 then it gets clipped of. I tried to set the near and far plane, but no effect. I searched through Google and tried several things, but was unable to figure out how this works in Qt. I manged to visualize this point cloud with OpenGL and GLUT before. Any help or explanation how to do this in Qt would be much appreciated!
m_projection is just a member variable in your class. It's not going to automatically "jump" into the OpenGL context. You've to explicitly load it into OpenGL. Normally you'd load a matrix like that into a uniform for use in a shader. But since you're not using shaders (booo! ;-) ) and use old, ugly and slow immediate mode (don't do that) you'll have to load it into the fixed function projection matrix.
glMatrixMode(GL_PROJECTION);
glLoadMatrixd(m_projection.constData());

OpenGL + Qt 4.8 is not drawing anything

I've been trying to use OpenGL in Qt with shaders and a simple vertex array. I basically want a plain to be drawn in the middle of the screen but nothing appears when I run the program. I'm basing my code in the "Texture" example of Qt, everything looks the same to me, but It's not working!
Here's the code of my glwidget.cpp:
#include "glwidget.h"
GLWidget::GLWidget(QWidget *parent):QGLWidget(parent)
{
timer.start(10);
//connect(&timer, SIGNAL(timeout()), this, SLOT(updateGL()));
Object aux;
QVector3D auxV;
auxV.setX(0.4); auxV.setY(0.4); auxV.setZ(1.0);
aux.vertices.append(auxV);
auxV.setX(0.4); auxV.setY(-0.4); auxV.setZ(1.0);
aux.vertices.append(auxV);
auxV.setX(-0.4); auxV.setY(-0.4); auxV.setZ(1.0);
aux.vertices.append(auxV);
auxV.setX(-0.4); auxV.setY(-0.4); auxV.setZ(1.0);
aux.vertices.append(auxV);
Objects.append(aux);
}
GLWidget::~GLWidget()
{
}
void GLWidget::initializeGL()
{
#define PROGRAM_VERTEX_ATTRIBUTE 0
printf("Objects Size: %d\nObj1 Size: %d\n", Objects.size(), Objects.at(0).vertices.size());
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
//printf("Version: %s\n", glGetString(GL_VERSION));
vShader= new QGLShader (QGLShader::Vertex, this);
vShader->compileSourceFile("../src/shaders/editorVshader.glsl");
fShader= new QGLShader (QGLShader::Fragment, this);
fShader->compileSourceFile("../src/shaders/editorFshader.glsl");
editor= new QGLShaderProgram (this);
editor->addShader(vShader);
editor->addShader(fShader);
editor->bindAttributeLocation("vertices", PROGRAM_VERTEX_ATTRIBUTE);
editor->link();
editor->bind();
}
void GLWidget::paintGL()
{
glClearColor(0.4765625, 0.54296875, 0.6171875, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -10.0f);
glVertexPointer(3, GL_FLOAT, 0, Objects.at(0).vertices.constData());
glEnableClientState(GL_VERTEX_ARRAY);
QMatrix4x4 auxM;
auxM.ortho(-0.5, 0.5, 0.5, -0.5, 4.0, -15.0);
auxM.translate(0.0f, 0.0f, -10.0f);
editor->setUniformValue("modelmatrix", auxM);
editor->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
//editor->enableAttributeArray(editor->attributeLocation("vertices"));
//editor->setAttributeArray(editor->attributeLocation("vertices"), Objects.at(0).vertices.constData(), 3);
editor->setAttributeArray (PROGRAM_VERTEX_ATTRIBUTE, Objects.at(0).vertices.constData());
glDrawArrays(GL_QUADS, 0, 4);
}
void GLWidget::resizeGL(int w, int h)
{
int side = qMin(w, h);
glViewport((w - side) / 2, (h - side) / 2, side, side);
//glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-0.5, 0.5, -0.5, 0.5, 4.0, -15.0);
glMatrixMode(GL_MODELVIEW);
updateGL();
}
And here are my vShader:
attribute highp vec4 vertices;
attribute highp mat4x4 modelmatrix;
void main (void)
{
gl_Position= modelmatrix*vertices;
}
And my fShader:
void main(void)
{
gl_FragColor= vec4(0.0, 0.1, 1.0, 1.0);
}
Do you see the error in there?
You are mixing OpenGLES1.1 (ex calls to glOrtho, glTranslate) and 2.0 (using shaders). Are you mixing the textures+overpainting examples ? You should instead take just one example that uses OpenGL / ES/ 1.1 or 2.0 like - http://qt-project.org/doc/qt-5.0/qtopengl/textures.html, then make changes and see how the code works.
I found what the problem was.
You're right, prabindh, I was mixing OpenGL versions, and the problem was related to that. After cleaning the code from OpenGL ES instructions, I also added the model, view and projection matrices in order to pass them to the shaders. It worked! Actually I think the plane was there all the time but I just couldn't see it because "the camera was aiming somewhere else".
But I wasn't mixing the examples, I based all my code in the textures example. I still can't understand why its code works and mine didn't. But anyway, everything went fine after that.
Thanks for your answers and your comments!

Integrating OpenCV with larger programs

Can anyone recommend a how-to guide or provide a brief overview of what's involved with integrating OpenCV with larger GUI-based programs? What are the popular ways to do it?
Particularly, processing video with OpenCV while doing video capture/preview without using HighGUI seems especially arcane. I hope someone can demystify this.
My particular configuration is with either Juce or Qt depending on what can be done. The cross platform thing is not critical -- if there is an awesome way of doing this in Windows, I might be convinced. The availability of community support is important.
I have heard that HighGUI is entirely for testing and unsuitable for real applications. Someone recommended the VideoInput library, but it is experimental.
Key points from answers:
Use Qt (because Qt is great and has a big community).
Open a new thread to run cv::VideoCapture in a loop and emit signal after frame capture. Use Qt's msleep mechanism, not OpenCV. So, we are still using OpenCV highgui for capture.
Convert cv::Mat to QtImage:
QImage qtFrame(cvFrame.data, cvFrame.size().width, cvFrame.size().height, cvFrame.step, QImage::Format_RGB888);
qtFrame = qtFrame.rgbSwapped();
Optional: Render with GLWidget. Convert QtImage to GLFormat with Qt built-in method:
m_GLFrame = QGLWidget::convertToGLFormat(frame);
this->updateGL();
Here is how I am doing it with Qt. You are welcome to use whatever may be useful to you :)
/// OpenCV_GLWidget.h
#ifndef OPENCV_GLWIDGET_H_
#define OPENCV_GLWIDGET_H_
#include <qgl.h>
#include <QImage>
class OpenCV_GLWidget: public QGLWidget {
public:
OpenCV_GLWidget(QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WindowFlags f = 0);
virtual ~OpenCV_GLWidget();
void renderImage(const QImage& frame);
protected:
virtual void paintGL();
virtual void resizeGL(int width, int height);
private:
QImage m_GLFrame;
};
#endif /* OPENCV_GLWIDGET_H_ */
/// OpenCV_GLWidget.cpp
#include "OpenCV_GLWidget.h"
OpenCV_GLWidget::OpenCV_GLWidget(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f) :
QGLWidget(parent, shareWidget, f)
{
// TODO Auto-generated constructor stub
}
OpenCV_GLWidget::~OpenCV_GLWidget() {
// TODO Auto-generated destructor stub
}
void OpenCV_GLWidget::renderImage(const QImage& frame)
{
m_GLFrame = QGLWidget::convertToGLFormat(frame);
this->updateGL();
}
void OpenCV_GLWidget::resizeGL(int width, int height)
{
// Setup our viewport to be the entire size of the window
glViewport(0, 0, width, height);
// Change to the projection matrix and set orthogonal projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void OpenCV_GLWidget::paintGL() {
glClear (GL_COLOR_BUFFER_BIT);
glClearColor (0.0, 0.0, 0.0, 1.0);
if (!m_GLFrame.isNull()) {
m_GLFrame = m_GLFrame.scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
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, GL_RGBA, m_GLFrame.width(), m_GLFrame.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, m_GLFrame.bits() );
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(0, m_GLFrame.height());
glTexCoord2f(0, 1); glVertex2f(0, 0);
glTexCoord2f(1, 1); glVertex2f(m_GLFrame.width(), 0);
glTexCoord2f(1, 0); glVertex2f(m_GLFrame.width(), m_GLFrame.height());
glEnd();
glDisable(GL_TEXTURE_2D);
glFlush();
}
}
This class handles the rendering of the image onto a promoted QWidget. Next, I created a thread to feed the widget. (I cheated using the Qt signal-slot architecture here because it was easy...may not be the best performer in the book, but it should get you started).
void VideoThread::run()
{
cv::VideoCapture video(0);
while(!m_AbortCapture)
{
cv::Mat cvFrame;
video >> cvFrame;
cv::Mat gray(cvFrame.size(), CV_8UC1);
cv::GaussianBlur(cvFrame, cvFrame, cv::Size(5, 5), 9.0, 3.0, cv::BORDER_REPLICATE);
cv::cvtColor(cvFrame, gray, CV_RGB2GRAY);
m_ThresholdLock.lock();
double localThreshold = m_Threshold;
m_ThresholdLock.unlock();
if(localThreshold > 0.0)
{
qDebug() << "Threshold = " << localThreshold;
cv::threshold(gray, gray, localThreshold, 255.0, cv::THRESH_BINARY);
}
cv::cvtColor(gray, cvFrame, CV_GRAY2BGR);
// convert the Mat to a QImage
QImage qtFrame(cvFrame.data, cvFrame.size().width, cvFrame.size().height, cvFrame.step, QImage::Format_RGB888);
qtFrame = qtFrame.rgbSwapped();
// queue the image to the gui
emit sendImage(qtFrame);
msleep(20);
}
}
Took me a bit to figure that out, so hopefully it will help you and others save some time :D
Create an openCV image to hold the image you have captured.
Do processing on it and then copy the data into the image you want to display (eg QImage)
You can optomise things by creating the opencv cv::Mat image to share the memory with the
QImage but since QImage generally uses ARGB and most image processing tasks are better done as greyscale or RGB it's probably better to copy images and convert between them using the opencv cvtColor() function
Then simply include include the opencv headers, and link with the opencv libs - there are guides on the opencv wiki for your particular environment

Resources