在Qt6中截取视频帧图片

导入一个视频文件并截取某一帧

简单介绍

Qt 6的Qt Multimedia模块替换了Qt 5.x的Qt Multimedia模块。使用Qt 5的Qt Multimedia的现有代码可以通过有限的努力进行移植。

也就是可以用QVideoSink来获取视频单帧了

准备工作

引入Multimedia

CMake示例:

1
2
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Multimedia)
target_link_libraries(QtTest PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt6::Multimedia)

需要引用的头文件

1
2
3
#include <QMediaPlayer>
#include <QVideoSink>
#include <QVideoFrame>

使用教程

获取单帧

.h private添加

1
QMediaPlayer* m_player = nullptr;

.cpp使用样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "mainwindow.h"
#include "./ui_mainwindow.h"

#include <QFileDialog>

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_player = new QMediaPlayer(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QVideoSink* videoSink = new QVideoSink(this);
m_player->setVideoOutput(videoSink);
//加载视频文件
QString str = QFileDialog::getOpenFileName();
m_player->setSource(QUrl(str));
//连接 QVideoSink 的 videoFrameChanged 信号
connect(videoSink, &QVideoSink::videoFrameChanged, [&](const QVideoFrame &frame) {
//获取帧时间戳
m_player->setPosition(5000);
QImage image = frame.toImage(); //将 QVideoFrame 转换为 QImage
image.save("screenshot_at_5_seconds.png"); //保存图片
m_player->stop(); // 停止播放
}
});
// 开始播放视频
m_player->play();
}

获取多帧

.h中添加loop

1
QEventLoop loop;

如果需要循环获取,可以使用loop进行局部循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//循环七秒
for (int i = 0; i <= m_player->duration(); i += 7000)
{
m_player->setPosition(i);
//使用局部事件循环等待帧捕获
bool frameCaptured = false;
//连接视频帧捕获的信号
connect(videoSink, &QVideoSink::videoFrameChanged, this, [&](const QVideoFrame &frame) mutable {
if (!frameCaptured && frame.isValid()) {
frameCaptured = true; //第一次捕获后设置为 true
QImage image = frame.toImage();
ui->label->setPixmap(QPixmap::fromImage(image));
if (!image.isNull()) {
//保存图像为 jpg
image.save(QString::number(i) + ".jpg", "JPG");
}
//断开信号,停止等待
disconnect(videoSink, &QVideoSink::videoFrameChanged, this, nullptr);
}
});
//开启局部事件循环,等待帧捕获完成
loop.exec();
}

在Qt6中截取视频帧图片
https://zao-chen.github.io/2024/11/04/在Qt中截取视频帧图片/
作者
Zao_chen
发布于
2024年11月4日
许可协议