文章目录
- 一、opencv相关视频播放类
- 1. `cv::VideoCapture` 类
- 主要构造方法:
- 主要方法:
- 2. 视频播放基本流程
- 代码示例:
- 3. 获取和设置视频属性
- 4. 结合 FFmpeg 使用
- 5. OpenCV 视频播放的局限性
- 6. 结合 Qt 实现更高级的视频播放
- 总结
- 二、QT中的代码实现
opencv_7">一、opencv相关视频播放类
在 OpenCV 中,视频播放主要依赖 cv::VideoCapture
类来进行视频读取和播放,同时使用 cv::imshow
进行帧显示。下面是 cv::VideoCapture
相关的基本概念和用法解析。
1. cv::VideoCapture
类
cv::VideoCapture
用于从视频文件、摄像头或网络流中读取视频数据。它可以处理多种格式的视频文件,如 MP4、AVI、MKV 以及摄像头流数据。
主要构造方法:
cv::VideoCapture(); // 空构造函数,需要后续调用 open()
cv::VideoCapture(const std::string& filename); // 通过文件路径打开视频
cv::VideoCapture(int deviceID); // 通过设备 ID 打开摄像头
主要方法:
方法 | 作用 |
---|---|
bool open(const std::string& filename) | 打开视频文件 |
bool open(int deviceID) | 打开摄像头 |
bool isOpened() const | 检查是否成功打开 |
void release() | 释放资源 |
bool read(cv::Mat& frame) | 读取下一帧 |
bool grab() | 只抓取一帧数据 |
bool retrieve(cv::Mat& frame, int flag = 0) | 获取当前抓取的帧 |
double get(int propId) | 获取视频参数 |
bool set(int propId, double value) | 设置视频参数 |
2. 视频播放基本流程
一个基本的视频播放程序通常包含以下步骤:
- 打开视频文件或摄像头
- 逐帧读取并显示
- 监听键盘输入进行暂停、退出等操作
- 释放资源
代码示例:
#include <opencv2/opencv.hpp>
#include <iostream>int main() {cv::VideoCapture cap("video.mp4"); // 打开视频文件if (!cap.isOpened()) {std::cerr << "无法打开视频文件!" << std::endl;return -1;}cv::Mat frame;while (true) {cap >> frame; // 读取一帧if (frame.empty()) break; // 读取完毕则退出cv::imshow("Video Playback", frame);// 按 'q' 退出,延迟 30msif (cv::waitKey(30) == 'q') break;}cap.release();cv::destroyAllWindows();return 0;
}
3. 获取和设置视频属性
可以使用 get()
和 set()
获取或修改视频参数:
double fps = cap.get(cv::CAP_PROP_FPS); // 获取帧率
int width = cap.get(cv::CAP_PROP_FRAME_WIDTH); // 获取宽度
int height = cap.get(cv::CAP_PROP_FRAME_HEIGHT); // 获取高度
修改属性(仅部分参数可修改):
cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480);
4. 结合 FFmpeg 使用
OpenCV 默认使用系统自带的编解码器播放视频,可能不支持所有格式。可以让 OpenCV 依赖 FFmpeg 来解码:
- Windows 用户可以下载 FFmpeg 并设置环境变量。
- Linux/macOS 用户可以使用
apt install ffmpeg
或brew install ffmpeg
进行安装。
检查 OpenCV 是否支持 FFmpeg:
std::cout << "FFmpeg support: " << cv::getBuildInformation() << std::endl;
5. OpenCV 视频播放的局限性
- 性能问题:
cv::VideoCapture
读取和解码较慢,不如 FFmpeg 专用库快。 - 格式支持有限:依赖编译选项和系统解码器,部分格式可能不受支持。
- 音频播放问题:OpenCV 仅处理视频帧,不支持音频,需要额外结合 FFmpeg 处理。
6. 结合 Qt 实现更高级的视频播放
如果你在 C++/Qt 项目中使用 OpenCV,可以使用 QLabel
结合 QImage
进行视频播放:
#include <opencv2/opencv.hpp>
#include <QImage>
#include <QPixmap>
#include <QLabel>void displayFrame(cv::Mat frame, QLabel* label) {cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);QImage img(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);label->setPixmap(QPixmap::fromImage(img));
}
总结
cv::VideoCapture
是 OpenCV 进行视频播放的核心类,可以从文件、摄像头读取视频。- 基本流程 是打开视频 -> 逐帧读取 ->
cv::imshow()
显示 -> 监听cv::waitKey()
控制播放。 - 可以获取/设置视频属性,如帧率、宽高等。
- 性能有限,如果对播放速度、格式兼容性有较高要求,建议结合 FFmpeg 或 Qt 多媒体模块。
二、QT中的代码实现
#include "widget.h"
#include "ui_widget.h"
#include <QImage>
#include <QPixmap>
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent),ui(new Ui::Widget),label(new QLabel(this)),btnPlayPause(new QPushButton("暂停", this)), // 按钮默认显示“暂停”cap("/mnt/app/1.mp4"), // 本地视频路径timer(new QTimer(this)),isPlaying(true)
{ui->setupUi(this);setFixedSize(700, 550); // 固定窗口大小// 设置 QLabel 位置和大小label->setGeometry(10, 10, 640, 480);// 设置播放/暂停按钮btnPlayPause->setGeometry(300, 500, 100, 40);connect(btnPlayPause, &QPushButton::clicked, this, &Widget::togglePlayback);// 检查视频文件是否打开成功if (!cap.isOpened()) {qWarning("无法打开视频文件!");return;}// 启动定时器,每 30ms 更新一帧(大约 33 FPS)connect(timer, &QTimer::timeout, this, &Widget::updateFrame);timer->start(30);
}Widget::~Widget()
{cap.release(); // 释放 OpenCV 资源delete timer;delete ui;
}void Widget::updateFrame()
{if (!isPlaying) return; // 如果暂停,则不更新帧cv::Mat frame;cap >> frame; // 读取一帧if (frame.empty()) {qWarning("视频播放结束!");timer->stop(); // 停止定时器return;}// OpenCV 默认是 BGR 颜色格式,转换为 RGBcv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);// 将 Mat 转换为 QImageQImage img(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);// 显示图像,并适配 QLabel 尺寸label->setPixmap(QPixmap::fromImage(img).scaled(label->size(), Qt::KeepAspectRatio));
}void Widget::togglePlayback()
{isPlaying = !isPlaying;btnPlayPause->setText(isPlaying ? "暂停" : "播放"); // 更新按钮文本
}
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QTimer>
#include <opencv2/opencv.hpp>QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void updateFrame(); // 更新视频帧void togglePlayback(); // 切换播放/暂停状态private:Ui::Widget *ui;QLabel *label; // 用于显示视频的QLabelQPushButton *btnPlayPause; // 播放/暂停按钮cv::VideoCapture cap; // OpenCV视频捕获对象QTimer *timer; // 用于定时刷新视频帧bool isPlaying; // 播放状态标记
};#endif // WIDGET_H