詳解 QT 框架中快速應(yīng)用OpenCV 基于視頻播放 下篇
QT 框架中快速應(yīng)用OpenCV 基于視頻播放是本篇介紹的內(nèi)容,接著上篇文章繼續(xù)介紹,詳解 QT 框架中快速應(yīng)用OpenCV 基于圖片 上篇,希望上篇文章對你有幫助,那么先來看本篇文章!
有些時候我們需要的是處理視頻文件,比如AVI,當(dāng)然也不過是圖像序列。在由于QT運行時的多線程機制導(dǎo)致sleep函數(shù)不好使,可以通過其提供的QTimer來控制視頻文件的播放。在給出例子之前要羅嗦兩句QT的信號/槽機制。MFC里面的消息映射固然很快,但是讓一個涉其未深的人閱讀起來會覺得很晦澀,QT通過signal/slot機制實現(xiàn)了消息交換。用signal喚起slot,比如點擊了button的clicked()事件是一個signal,當(dāng)這個事件發(fā)生之后可以喚起其他的操作,只要你將clicked消息和那個實際操作的槽連接起來了。
opencv里面有函數(shù)可以方便的讀取視頻幀,如果使用Widget播放視頻,如何控制幀率是一個很巧妙的地方,我使用一個QTimer控制時間(可以理解為幀率),并周期性的喚起讀取視頻幀的操作,然后在這個操作里面對widget進行重繪,或者模仿前面的方法,用一個QImage當(dāng)作共享區(qū)域,讓用來paintEvent用來顯示。
有了上面顯示圖像的基礎(chǔ),我改一下上面的代碼,給出一個例子:
- myWidget.h
- #ifndef MYWIDGET_H
- #define MYWIDGET_H
- #include <QtGui\QWidget>
- #include <QtGui\QPaintEvent>
- #include <QtGui\QImage>
- #include <QtCore\QTimer>
- #include <cv.h>
- #include <highgui.h>
- class myWidget : public QWidget
- {
- Q_OBJECT
- public:
- myWidget(const char *filename,QWidget *parent = 0);
- ~myWidget();
- protected:
- void paintEvent(QPaintEvent *e);
- private slots:
- void nextFrame();
- private:
- CvCapture *capture;
- IplImage *iplImg;
- IplImage *frame;
- QImage *qImg;
- QTimer *timer;
- };
- #endif
- myWidget.cpp
- #include "myWidget.h"
- #include <QtGui\QPainter>
- #include <QtCore\QPoint>
- myWidget::myWidget(const char *filename,QWidget *parent /* = 0 */) : QWidget(parent)
- {
- capture = cvCaptureFromFile(filename);
- if (capture)
- {
- frame = cvQueryFrame(capture);
- if (frame)
- this->resize(frame->width,frame->height);
- qImg = new QImage(QSize(frame->width,frame->height),
- QImage::Format_RGB888);
- iplImg = cvCreateImageHeader(cvSize(frame->width,frame->height),
- 8,3);
- iplImg->imageData = (char*)qImg->bits();
- timer = new QTimer(this);
- timer->setInterval(30);
- connect(timer,SIGNAL(timeout()),this,SLOT(nextFrame()));
- timer->start();
- }
- }
- myWidget::~myWidget()
- {
- cvReleaseImage(&iplImg);
- cvReleaseCapture(&capture);
- delete qImg;
- delete timer;
- }
- void myWidget::paintEvent(QPaintEvent *e)
- {
- QPainter painter(this);
- painter.drawImage(QPoint(0,0),*qImg);
- }
- void myWidget::nextFrame()
- {
- frame = cvQueryFrame(capture);
- if (frame)
- {
- if (frame->origin == IPL_ORIGIN_TL)
- {
- cvCopy(frame,iplImg,0);
- }
- else
- {
- cvFlip(frame,iplImg,0);
- }
- cvCvtColor(iplImg,iplImg,CV_BGR2RGB);
- this->update();
- }
- }
主函數(shù)里面調(diào)用
- int main(int argc,char* argv[])
- {
- QApplication app(argc,argv);
- char *filename = "test.avi";
- myWidget *mw = new myWidget(filename);
- mw->show();
- int re = app.exec();
- return re;
- }
由于接不截圖都看不出來,所以就不截圖。
后一個程序因為涉及到slots,所以添加了一個Q_OBJECT宏,編譯之前需要將myWidget.h程序moc一下
比如:
- moc myWidget.h –o moc_myWidget.cpp
這樣會在目錄下生成一個.cpp文件,make的時候加到源文件里一起make,或者編譯的時候添加到源文件列表中去。
知道如何使用QT來顯示圖像和播放視頻之后,在上述代碼里面插入處理圖像的代碼就很簡單了。顯示圖像的時候在構(gòu)造函數(shù)里面就可以插入處理代碼,當(dāng)然也可以在paintEvent函數(shù)里面進行處理,播放視頻的時候可以在nextFrame函數(shù)里面進行處理,有些預(yù)處理可以在構(gòu)造函數(shù)里面完成。
相比于MFC的代碼,QT的代碼結(jié)構(gòu)看上去,很明顯,更加優(yōu)美。
小結(jié):詳解 QT 框架中快速應(yīng)用OpenCV 基于視頻播放 下篇的內(nèi)容介紹完了,希望本文能幫你解決問題!