QT 框架中快速应用OpenCV 基于视频播放

来源:互联网 发布:数据采集器的作用 编辑:程序博客网 时间:2024/05/15 10:54
http://www.51cto.com/php/viewart.php?artID=271265

 

有些时候我们需要的是处理视频文件,比如AVI,当然也不过是图像序列。在由于QT运行时的多线程机制导致sleep函数不好使,可以通过其提供的QTimer来控制视频文件的播放。在给出例子之前要罗嗦两句QT的信号/槽机制。MFC里面的消息映射固然很快,但是让一个涉其未深的人阅读起来会觉得很晦涩,QT通过signal/slot机制实现了消息交换。用signal唤起slot,比如点击了button的clicked()事件是一个signal,当这个事件发生之后可以唤起其他的操作,只要你将clicked消息和那个实际操作的槽连接起来了。

opencv里面有函数可以方便的读取视频帧,如果使用Widget播放视频,如何控制帧率是一个很巧妙的地方,我使用一个QTimer控制时间(可以理解为帧率),并周期性的唤起读取视频帧的操作,然后在这个操作里面对widget进行重绘,或者模仿前面的方法,用一个QImage当作共享区域,让用来paintEvent用来显示。

有了上面显示图像的基础,我改一下上面的代码,给出一个例子:

  1. myWidget.h
  2. #ifndef MYWIDGET_H
  3. #define MYWIDGET_H
  4. #include <QtGui\QWidget>
  5. #include <QtGui\QPaintEvent>
  6. #include <QtGui\QImage>
  7. #include <QtCore\QTimer>
  8. #include <cv.h>
  9. #include <highgui.h>
  10. class myWidget : public QWidget
  11. {
  12. Q_OBJECT
  13. public:
  14. myWidget(const char *filename,QWidget *parent = 0);
  15. ~myWidget();
  16. protected:
  17. void paintEvent(QPaintEvent *e);
  18. private slots:
  19. void nextFrame();
  20. private:
  21. CvCapture *capture;
  22. IplImage *iplImg;
  23. IplImage *frame;
  24. QImage *qImg;
  25. QTimer *timer;
  26. };
  27. #endif
  28. myWidget.cpp
  29. #include "myWidget.h"
  30. #include <QtGui\QPainter>
  31. #include <QtCore\QPoint>
  32. myWidget::myWidget(const char *filename,QWidget *parent /* = 0 */) : QWidget(parent)
  33. {
  34. capture = cvCaptureFromFile(filename);
  35. if (capture)
  36. {
  37. frame = cvQueryFrame(capture);
  38. if (frame)
  39. this->resize(frame->width,frame->height);
  40. qImg = new QImage(QSize(frame->width,frame->height),
  41. QImage::Format_RGB888);
  42. iplImg = cvCreateImageHeader(cvSize(frame->width,frame->height),
  43. 8,3);
  44. iplImg->imageData = (char*)qImg->bits();
  45. timer = new QTimer(this);
  46. timer->setInterval(30);
  47. connect(timer,SIGNAL(timeout()),this,SLOT(nextFrame()));
  48. timer->start();
  49. }
  50. }
  51. myWidget::~myWidget()
  52. {
  53. cvReleaseImage(&iplImg);
  54. cvReleaseCapture(&capture);
  55. delete qImg;
  56. delete timer;
  57. }
  58. void myWidget::paintEvent(QPaintEvent *e)
  59. {
  60. QPainter painter(this);
  61. painter.drawImage(QPoint(0,0),*qImg);
  62. }
  63. void myWidget::nextFrame()
  64. {
  65. frame = cvQueryFrame(capture);
  66. if (frame)
  67. {
  68. if (frame->origin == IPL_ORIGIN_TL)
  69. {
  70. cvCopy(frame,iplImg,0);
  71. }
  72. else
  73. {
  74. cvFlip(frame,iplImg,0);
  75. }
  76. cvCvtColor(iplImg,iplImg,CV_BGR2RGB);
  77. this->update();
  78. }
  79. }

主函数里面调用

  1. int main(int argc,char* argv[])
  2. {
  3. QApplication app(argc,argv);
  4. char *filename = "test.avi";
  5. myWidget *mw = new myWidget(filename);
  6. mw->show();
  7. int re = app.exec();
  8. return re;
  9. }

后一个程序因为涉及到slots,所以添加了一个Q_OBJECT宏,编译之前需要将myWidget.h程序moc一下

比如:

  1. moc myWidget.h –o moc_myWidget.cpp

这样会在目录下生成一个.cpp文件,make的时候加到源文件里一起make,或者编译的时候添加到源文件列表中去。

知道如何使用QT来显示图像和播放视频之后,在上述代码里面插入处理图像的代码就很简单了。显示图像的时候在构造函数里面就可以插入处理代码,当然也可以在paintEvent函数里面进行处理,播放视频的时候可以在nextFrame函数里面进行处理,有些预处理可以在构造函数里面完成。

相比于MFC的代码,QT的代码结构看上去,很明显,更加优美。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 高敏肌钙蛋白t高怎么办 龟头沟槽里长疙瘩怎么办 肝郁气滞的体质怎么办 手指甲长在肉里怎么办 甲床与指甲脱离怎么办 指甲往肉里面长怎么办 指甲和肉分离是怎么办 大脚趾指甲空了怎么办 脚趾甲长在肉里怎么办 脚趾甲又厚又硬怎么办 小孩子咳嗽有痰怎么办%3f 支气扩张咳血怎么办小 背部第8块脊椎疼怎么办 坐时间长了背疼怎么办 新生儿总哭怎么办吐奶 婴儿吃饱了还哭怎么办 宝宝喉咙哭哑了怎么办 婴儿哭哑了嗓子怎么办 婴儿胖子哭哑了怎么办 孩子声音哭哑了怎么办 喝咖啡手抖心慌怎么办 累了就心慌发抖怎么办 经常头晕心慌胸闷乏力怎么办 在末地迷路了怎么办 在森林里迷路了怎么办 电热宝充电不热怎么办 保温壶按钮坏了怎么办 热水壶盖子坏了怎么办 充电暖宝宝不热怎么办 刚怀孕孕酮低该怎么办 小三怀孕了该怎么办 15学生怀孕了该怎么办 学东西慢悟性差怎么办 欠债不还怎么办有欠条 欠了几百万我该怎么办 玄凤鹦鹉感冒了怎么办 多肉爆出小崽怎么办 多肉红宝石爆崽怎么办 黑尾蜡嘴太怕人怎么办 凤眼菩提盘黑了怎么办 凤眼菩提盘花了怎么办