gpt4 book ai didi

c++ - 使用 QT6 在 QVideoWidget 上绘制 QVideoFrame

转载 作者:行者123 更新时间:2023-12-05 05:48:07 31 4
gpt4 key购买 nike

我想用 QT6 逐帧处理网络摄像头的流。我在网上查过,但由于 QTMultimedia 使用 QT6 进行了大量修改,而且由于 QT6 非常新,所以所有可用的文档/问题都已过时。

因此,为了实现我的目标,我使用了一个 QMediaCaptureSession,并在 QMediaDevices::defaultVideoInput() 上设置了摄像头。我通过使用 m_session.setVideoOutput(ui->videowidget);QMediaCaptureSession 的视频输出设置为 QVideoWidget 来检查这是否有效,它工作正常,除了我无法处理帧(基本上,它在 QVideoWidget 上呈现我的网络摄像头)。

现在,据我对文档的理解,要处理帧,我必须使用 QVideoSink herethere .所以我用 m_session.setVideoSink(&mysink); 替换了 m_session.setVideoOutput(ui->videowidget);,其中 mysink 是一个 QVideoSink.

然后,因为我想处理帧,所以我将 mysinkvideoFrameChanged 信号连接到我想要的函数 processVideoFrame做两件事:

  1. 处理当前帧
  2. 在 UI 上呈现结果,最好是在 ui->videowidget

这就是我苦苦挣扎的地方。 我不明白如何使用paint functionQVideoFrame 以在 QVideoWidget 上呈现处理后的帧。更准确地说:

  • 我不明白应该如何实例化 QPainter。我尝试了一个简单的 new QPainter(ui->videowidget) 但它以 QWidget::paintEngine: Should no longer be called 异常结束并且没有呈现任何内容
  • 我不明白 QVideoFrame::paint 的第二个参数 rect 的实际含义是什么?

我做了一个MWE,代码在下面。

mwe_videosinkpainting.h

#ifndef MWE_VIDEOSINKPAINTING_H
#define MWE_VIDEOSINKPAINTING_H

#include <QMainWindow>
#include <QMediaCaptureSession>
#include <QMediaDevices>
#include <QCamera>
#include <QVideoSink>
#include <QPainter>

QT_BEGIN_NAMESPACE
namespace Ui { class MWE_VideoSinkPainting; }
QT_END_NAMESPACE

class MWE_VideoSinkPainting : public QMainWindow
{
Q_OBJECT

public:
MWE_VideoSinkPainting(QWidget *parent = nullptr);
~MWE_VideoSinkPainting();

private slots:
void processVideoFrame();


private:
Ui::MWE_VideoSinkPainting *ui;

QVideoSink mysink;
QMediaCaptureSession m_session;
QScopedPointer<QCamera> m_camera;
};
#endif // MWE_VIDEOSINKPAINTING_H

mwe_videosinking.cpp

#include "mwe_videosinkpainting.h"
#include "ui_mwe_videosinkpainting.h"

MWE_VideoSinkPainting::MWE_VideoSinkPainting(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MWE_VideoSinkPainting)
{
ui->setupUi(this);

m_camera.reset(new QCamera(QMediaDevices::defaultVideoInput()));
m_session.setCamera(m_camera.data());
//m_session.setVideoOutput(ui->videowidget);

connect(&mysink, &QVideoSink::videoFrameChanged, this, &MWE_VideoSinkPainting::processVideoFrame);

m_session.setVideoSink(&mysink);
m_camera->start();
}

MWE_VideoSinkPainting::~MWE_VideoSinkPainting()
{
delete ui;
}

void MWE_VideoSinkPainting::processVideoFrame()
{
QVideoFrame videoframe = mysink.videoFrame();
if(videoframe.map(QVideoFrame::ReadOnly))
{
//This is the part I'm struggling to understand and achieve
videoframe.paint(new QPainter(ui->videowidget), QRectF(0.0f,0.0f,100.0f,100.0f), QVideoFrame::PaintOptions());
videoframe.unmap();
}
}

main.cpp

#include "mwe_videosinkpainting.h"

#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MWE_VideoSinkPainting w;
w.show();
return a.exec();
}

ui_mwe_videosinkpainting.h(只是为了让您拥有完整的代码,它对问题没有任何值(value))

#ifndef UI_MWE_VIDEOSINKPAINTING_H
#define UI_MWE_VIDEOSINKPAINTING_H

#include <QtCore/QVariant>
#include <QtMultimediaWidgets/QVideoWidget>
#include <QtWidgets/QApplication>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

class Ui_MWE_VideoSinkPainting
{
public:
QWidget *centralwidget;
QGridLayout *gridLayout;
QVideoWidget *videowidget;
QHBoxLayout *horizontalLayout;
QMenuBar *menubar;
QStatusBar *statusbar;

void setupUi(QMainWindow *MWE_VideoSinkPainting)
{
if (MWE_VideoSinkPainting->objectName().isEmpty())
MWE_VideoSinkPainting->setObjectName(QString::fromUtf8("MWE_VideoSinkPainting"));
MWE_VideoSinkPainting->resize(800, 600);
centralwidget = new QWidget(MWE_VideoSinkPainting);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
gridLayout = new QGridLayout(centralwidget);
gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
videowidget = new QVideoWidget(centralwidget);
videowidget->setObjectName(QString::fromUtf8("videowidget"));
horizontalLayout = new QHBoxLayout(videowidget);
horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));

gridLayout->addWidget(videowidget, 0, 0, 1, 1);

MWE_VideoSinkPainting->setCentralWidget(centralwidget);
menubar = new QMenuBar(MWE_VideoSinkPainting);
menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 800, 21));
MWE_VideoSinkPainting->setMenuBar(menubar);
statusbar = new QStatusBar(MWE_VideoSinkPainting);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
MWE_VideoSinkPainting->setStatusBar(statusbar);

retranslateUi(MWE_VideoSinkPainting);

QMetaObject::connectSlotsByName(MWE_VideoSinkPainting);
} // setupUi

void retranslateUi(QMainWindow *MWE_VideoSinkPainting)
{
MWE_VideoSinkPainting->setWindowTitle(QCoreApplication::translate("MWE_VideoSinkPainting", "MWE_VideoSinkPainting", nullptr));
} // retranslateUi

};

namespace Ui {
class MWE_VideoSinkPainting: public Ui_MWE_VideoSinkPainting {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_MWE_VIDEOSINKPAINTING_H

最佳答案

答案很简单:您可以使用 setVideoSinksetVideoOutput

我在 OP 中给出的代码很好,您只需取消注释 setVideoOutput(ui->videowidget);mwe_videosinking.cpp 并调用 setVideoSink 在调用 setVideoOutput

之前

关于c++ - 使用 QT6 在 QVideoWidget 上绘制 QVideoFrame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70871954/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com