How do you play video process with opencv in a complete Qt interface?
-
Greetings, I hope you can help us with this-
First we capture the video from a file or camera in cvcapture strutcture, weather from a camera or file. We get a ROI frome the first frame and apply it along to the rest of the frames. After we process the images with some bg substraction, filters and other stuff.
We were able to visualize the results in a window with cvshowimage in a window appart.
However, we made an interface and try to show the images (as a video) in a qlabel. Thei interface has other thins to show some inputs variables and output results. We´ve already converted the IplImae in a QImage (see this "page":http://wiki.forum.nokia.com/index.php/Using_OpenCV_with_Qt) so it can be displayed in the interface. When we capture just one frame of the video it works fine, but when we go into a loop (while) to process and show all frames as a video it doesn´t work.
The strangest thing is that when we aditionally create a window (cvnamedwindow) appart that is not even connected to the program, the video is shown (played) at the interface, and the window is shown but nothing is played in it (it´s blank), and the program gets stucked, playing the video but it won´t receive any orders.
We need to play the video already proccessed in the interface.
The code for the program is shown above. Thank you.
@
CvCapture *cap;
cap = cvCaptureFromCAM(0);
IplImage *frame;
frame = cvQueryFrame(cap);
play = true;// cvNamedWindow("video",0);
while(frame && play){ cvWaitKey(10); IplImage *img = cvCloneImage(frame); if (img->origin) { cvFlip(img); img->origin= 0; } QImage qimg; qimg = IplImage2QImage(img); ui->label->setPixmap(QPixmap::fromImage(qimg)); cvReleaseImage(&img); frame = cvQueryFrame(cap); } cvReleaseCapture(&cap);
}
@[EDIT: code formatting, please wrap in @-tags, Volker]
-
this is the rigth code, thank
@CvCapture *cap; cap = cvCaptureFromCAM(0);
IplImage *frame; frame = cvQueryFrame(cap);
play = true;
// cvNamedWindow(“video”,0);
while(frame && play){
cvWaitKey(10); IplImage *img = cvCloneImage(frame);
if (img->origin) {
cvFlip(img);
img->origin= 0;
}
QImage qimg;
qimg = IplImage2QImage(img);
ui->label->setPixmap(QPixmap::fromImage(qimg));
cvReleaseImage(&img);
frame = cvQueryFrame(cap);
}
cvReleaseCapture(&cap);@
-
Hi,
I tried it this way too but it was too slow for realtime processing. The best solution is using Qt's OpenGL Features.
You can either do texture mapping or drawPixels directly onto any OpenGL Object.
You will have to grab your frames, process them and then convert them to a QImage::Format.
With each frame you send you update the glTexture.
I made an Implementation with GLWidget (CVWidget) so you can use it like any other widget, even from within the gui creator.
You just add a cvWidget to your GUI and then you can send your frames to this widget.
Because of the GL-Rendering the performance when displaying is awesome. I'm working on further improving performance by using QtConcurrent and splitting every frame into pieces and pass each to another thread. But that's not finished yet.
But still, the OpenGL method is really great and if you are still interested I can show you the source for the cvWidget so u can use it. It's really simple.
D.
-
I'm interested in your widget S3dr1ck..
Can I have more information about this CVWidget?Thanks!
-
Sorry for answering that late, I just found my post and decided to ansewer, hope it will still be helpful:
@#ifndef CVWIDGET_H
#define CVWIDGET_H#include <QGLWidget>
#include <QtOpenGL>
#include <opencv2/opencv.hpp>
#include <opencv/highgui.h>
using namespace cv;class CVWidget : public QGLWidget
{
Q_OBJECT
public:
CVWidget();
void sendImage(Mat *img);
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
private:
QImage qframe;
};#endif // CVWIDGET_H@
@#include "cvwidget.h"
CVWidget::CVWidget() : QGLWidget(QGLFormat(QGL::SampleBuffers)) {
setMinimumSize(320,240);
}void CVWidget::initializeGL() {
glClearColor(0.0f,0.0f,0.0f,1.0f);
}
void CVWidget::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 like this
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...";
}void CVWidget::resizeGL(int w, int h) {
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode (GL_MODELVIEW);
// qDebug() << "Resizing...";
}void CVWidget::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();
}
@ -
[quote author="S3dr1ck" date="1337865732"]
void CVWidget::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();
}[/quote]Hi,
it should be@qframe = QImage((const unsigned char*)(img->ptr()), img->cols, img->rows, img->step, QImage::Format_RGB888).rgbSwapped(); @
instead.