使用Qt5和OpenCV做视频播放器

来源:互联网 发布:变声软件变成女人声 编辑:程序博客网 时间:2024/06/10 18:34

声明在前头:本文是查阅整合了众多网友的知识的基础上实现的。

首先,说在前头。通过实现了使用OpenCV做播放器的过程,才发现OpenCV真的不适合做播放器,至少是没有什么太多视频处理理论基础认识的初学者。实现过程中也是历尽千辛万苦,查阅很多资料。

使用环境是Qt5.7.0+VS2013+OpenCV2.4.13。在这里就不说环境搭建了,如果会使用动态库,这些步骤应该不是问题。但是写本文的原因是如何使用代码去实现。

废话不多说,直接上代码。


首先看头文件 OpenCVDemo3.h


#ifndef OPENCVDEMO3_H#define OPENCVDEMO3_H#include <QtWidgets/QWidget>#include "ui_OpenCVDemo3.h"//opencv头文件引用#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <QTimer>#include <QImage>using namespace cv;class OpenCVDemo3 : public QWidget{Q_OBJECTpublic:OpenCVDemo3(QWidget *parent = 0);~OpenCVDemo3();QImage  MatToQImage(const cv::Mat& mat);private slots:void onBtnClicked();void onTimeout();void onBtnFastClicked();void onBtnSlowClicked();private:Ui::OpenCVDemo3Class ui;VideoCapture capture; //用来读取视频结构QTimer timer;//视频播放的定时器int beishu;//调节播放速率int delay;//帧延迟时间};#endif // OPENCVDEMO3_H

下面是源文件OpenCVDemo3.cpp

#include "OpenCVDemo3.h"#include <QDebug>OpenCVDemo3::OpenCVDemo3(QWidget *parent): QWidget(parent), beishu(1),delay(0){ui.setupUi(this);connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(onBtnClicked()));connect(ui.pushButton_fast, SIGNAL(clicked()), this, SLOT(onBtnFastClicked()));connect(ui.pushButton_slow, SIGNAL(clicked()), this, SLOT(onBtnSlowClicked()));connect(&timer, SIGNAL(timeout()), this, SLOT(onTimeout()));}OpenCVDemo3::~OpenCVDemo3(){capture.release();}void OpenCVDemo3::onBtnFastClicked(){beishu = beishu * 2;timer.stop();timer.start(delay / beishu);}void OpenCVDemo3::onBtnSlowClicked(){beishu = beishu / 2;timer.stop();timer.start(delay / beishu);}void OpenCVDemo3::onBtnClicked(){//打开视频文件:其实就是建立一个VideoCapture结构capture.open("F:\\win32\\openCVDemo1\\OpenCVDemo2\\2.mp4");//检测是否正常打开:成功打开时,isOpened返回tureif (!capture.isOpened())ui.textEdit->append("fail to open!");//获取整个帧数long totalFrameNumber = capture.get(CV_CAP_PROP_FRAME_COUNT);ui.textEdit->append(QString::fromLocal8Bit("整个视频共 %1 帧").arg(totalFrameNumber));ui.label->resize(QSize(capture.get(CV_CAP_PROP_FRAME_WIDTH), capture.get(CV_CAP_PROP_FRAME_HEIGHT)));//设置开始帧()long frameToStart = 0;capture.set(CV_CAP_PROP_POS_FRAMES, frameToStart);ui.textEdit->append(QString::fromLocal8Bit("从第 %1 帧开始读").arg(frameToStart));//获取帧率double rate = capture.get(CV_CAP_PROP_FPS);ui.textEdit->append(QString::fromLocal8Bit("帧率为:第 %1 ").arg(rate));delay = 1000 / rate;timer.start(delay / beishu);}void OpenCVDemo3::onTimeout(){Mat frame;//读取下一帧if (!capture.read(frame)){ui.textEdit->append(QString::fromLocal8Bit("读取视频失败"));return;}QImage image=MatToQImage(frame);ui.label->setScaledContents(true);QSize qs = ui.label->rect().size();ui.label->setPixmap(QPixmap::fromImage(image).scaled(qs));ui.label->repaint();//这里加滤波程序long totalFrameNumber = capture.get(CV_CAP_PROP_POS_FRAMES);ui.textEdit->append(QString::fromLocal8Bit("正在读取第:第 %1 帧").arg(totalFrameNumber));}QImage OpenCVDemo3::MatToQImage(const cv::Mat& mat){// 8-bits unsigned, NO. OF CHANNELS = 1    if (mat.type() == CV_8UC1){QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);// Set the color table (used to translate colour indexes to qRgb values)    image.setColorCount(256);for (int i = 0; i < 256; i++){image.setColor(i, qRgb(i, i, i));}// Copy input Mat    uchar *pSrc = mat.data;for (int row = 0; row < mat.rows; row++){uchar *pDest = image.scanLine(row);memcpy(pDest, pSrc, mat.cols);pSrc += mat.step;}return image;}// 8-bits unsigned, NO. OF CHANNELS = 3    else if (mat.type() == CV_8UC3){// Copy input Mat   const uchar *pSrc = (const uchar*)mat.data;// Create QImage with same dimensions as input Mat    QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);return image.rgbSwapped();}else if (mat.type() == CV_8UC4){// Copy input Mat    const uchar *pSrc = (const uchar*)mat.data;// Create QImage with same dimensions as input Mat    QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);return image.copy();}else{return QImage();}}
最后运行的效果如图所示:

总结在最后:

首先使用OpenCV做播放视频的实例不少,很多网友都提供了源代码。但是往往大多数都是使用OpenCV自己的播放窗口,然后使用一个while循环来做。但是真正的使OpenCV和Qt结合在一起的大多是摄像头的代码。所以本文在整合网友资源的同时,加入了自己的想法,来实现播放本地视频。

然后,曾尝试使用多线程来解决播放问题,但是在尝试的过程中,发现不可行。所以果断放弃了。使用定时器是网上的一贯用法。但是有一些视频的fps信息和帧数信息不准确时,却会出现问题。

最后,本代码只是实现了视频的播放,但是视频中的音频信息却无法播放。所以这是不推荐使用它做播放器的原因。所以做视频播放器还是推荐FFMpeg和VLC,更专业些。


1 0
原创粉丝点击