this is a simple Qt+OpenCV+OpenGL integration. this entry will show you how you can capture webcam image using opencv and draw it in Qt apps using opengl texture on GLWidget. requires Qt & OpenCV 2.1 here is our main window code for query and process image from webcam query image from camera
void Opencv2Qt::processCam() {
if (this->capture.isOpened()) {
timer.restart();
Mat frame;
capture >> frame;
if (frame.data) {
this->processFrame(frame);
glWidget->sendImage(&frame);
ui->statusBar->showMessage("Running....");
QTimer::singleShot(25, this, SLOT(processCam()));
}
}
return;
}
lets do something with the frame, this is simple example how to change brightness and contrast
void Opencv2Qt::processFrame(Mat& img) {
const double brightness_gain = 0.5;
const double contrast_gain = 0.6;
Mat white(img.size(), CV_8UC3);
white=Scalar(255,255,255);
addWeighted(img, contrast_gain, white, 1,-128 + brightness_gain, img);
}
i used QTimer to query for new image every 20 milisecond, this is approximately 25-30 fps. enough for conventional webcam. more on how to draw our image to Qt after the jump this is the function to recieve cv::Mat image and convert to opengl image format we create a class for GLWidget
void GLWidget::sendImage(Mat* img) {
qframe = QImage((const unsigned char*)(img->data), img->cols, img->rows, img->step,
QImage::Format_RGB888).rgbSwapped();
qframe = QGLWidget::convertToGLFormat(qframe);
this->updateGL();
}
now we will paint our image using PaintGL() function in this example i use 2D texture to render the image. alternatively you can use glDrawPixels to draw the image.
void GLWidget::paintGL() {
glClear (GL_COLOR_BUFFER_BIT);
glClearColor (0.0,0.0,0.0,1.0);
if (!qframe.isNull()) {
qframe = qframe.scaled(this->size(), Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
// you can use glDrawPixels directly
// glDrawPixels(qframe.width(),qframe.height(), GL_RGBA, GL_UNSIGNED_BYTE, qframe.bits());
// or do 2D texture mapping
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,qframe.width(),qframe.height(),0);
glMatrixMode(GL_MODELVIEW);
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, qframe.width(), qframe.height(), 0, \
GL_RGBA, GL_UNSIGNED_BYTE, qframe.bits() );
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex2f(0,qframe.height());
glTexCoord2f(0,1); glVertex2f(0,0);
glTexCoord2f(1,1); glVertex2f(qframe.width(),0);
glTexCoord2f(1,0); glVertex2f(qframe.width(),qframe.height());
glEnd();
glDisable(GL_TEXTURE_2D);
// .... end
// some example of alpha blending
//glEnable(GL_DEPTH_TEST);
//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glColor4f(0.0f,1.0f,1.0f, 0.9f);
glFlush();
}
// qDebug() << "Drawing...";
}
...that's it, all done!
footnote:
- why use PaintGL instead of QPainter? oh well..the answer is simple it's fast and can be utilize for complex image processing rendering such as 3D augmented reality.
- note that this is direct implementation of image capturing from webcam using QTimer. for heavy processing job you might want to consider running processsCAM() and processingFrame() job on different thread.
- you may download opencv2Qt source code for details until then, happy coding and hope this code can be useful to someone :)