c++ - Qt C++ - 多线程视频帧转换

标签 c++ multithreading qt user-interface

我必须编写一个应用程序,在一个 Widget 中显示加载的视频,拉帧,转换它们,然后将它们放入另一个 Widget,最好是 QGraphicsView,并希望同步。同步它们非常重要。

我写了一个测试线程,主要内容是这样的:

void HSV::display() {
Ui::MainWindow ui; //1
int j=0;
QTimer *timer = new QTimer;
for(int i=1; i<4; i++){
    QString numer = QString::number(i);
    QImage imageTest(numer+".jpg");
    QGraphicsPixmapItem* test = new QGraphicsPixmapItem(QPixmap::fromImage(imageTest));
    QGraphicsScene* sceneHSV = new QGraphicsScene;
    sceneHSV->addItem(test);
    //2
    ui.graphicsViewKalibracjaHSV->setScene(sceneHSV);
    ui.graphicsViewKalibracjaHSV->fitInView(sceneHSV->sceneRect(),Qt::KeepAspectRatio);
    ui.graphicsViewKalibracjaHSV->show();
    timer->start(500);
    if(i==3) {
        i=1;
    }
    j++;
    if (j>40) {
        break;
    }
    }
}

这不是我需要的,但它只是一个测试。如果我把文字放在那里,它会很好地显示,继续显示。但是这些图像......当到达第一条 ui 行(//2 )时立即崩溃。我毫不怀疑这种做事方式真的很糟糕。

如果我删除位于//1 的 Ui::MainWindow ui;,它会告诉我 ui 未在此范围内声明

所以我的问题是,如何从单独的线程访问和修改主窗口中的 ui 元素?

编辑: 好的,一个更实际的想法。我将简单地将视频文件 URL 从 GUI 线程传递到工作线程,在那里执行所有操作并传回 2 个处理过的图像(对于每个视频帧),每个 QGraphicsView 一个。一张是正常的,有标记点,一张是变形的。我现在知道如何将内容从工作线程传递到 GUI 线程,但是如何将 QString 从 GUI 传递到工作线程,以及如何接收它?

最佳答案

简短的回答:你不能。

Qt 帮助:线程基础:

GUI Thread and Worker Thread

As mentioned, each program has one thread when it is started. This thread is called the "main thread" (also known as the "GUI thread" in Qt applications). The Qt GUI must run in this thread. All widgets and several related classes, for example QPixmap, don't work in secondary threads. A secondary thread is commonly referred to as a "worker thread" because it is used to offload processing work from the main thread.

你可以做什么:你可以在主线程中使用 ui,通过信号/槽系统将 QImage(或其他与 ui 无关的数据)传递到单独的线程,在那里处理它并传递它回来了。

更新(我该怎么做?我的意思是,在线程之间来回传递 QImage 并同时连续显示两个视频?– Petersaber)

我不是视频专家,但我可以给你提示。假设您有一个 Widget,它接受 QImage 并且必须显示它。 Processor 是一个对象,它处理图像并将其返回给 gui 线程。 Processor 应该派生自 QObject

Widget.h

class Widget : public QWidget, private Ui::Widget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    void enqueueImage(const QImage &img);

signals:
    void process(const QImage &img);

private:
    void showNextImage();

private slots:
    void onProcessed(const QImage &img);

private:
    QThread *mThread;
    QScopedPointer < Processor > mProcessor;
    QList < QImage > mImagesPool;
};

Widget.cpp

Widget::Widget(QWidget *parent) :
    QWidget(parent)
  , mThread(new QThread(this))
  , mProcessor(new Processor)
{
    setupUi(this);
    mProcessor->moveToThread(mThread);
    connect(this, SIGNAL(process(QImage)), mProcessor, SLOT(process(QImage)));
    connect(mProcessor, SIGNAL(processed(QImage)), SLOT(onProcessed(QImage)));
}

void Widget::enqueueImage(const QImage &img)
{
    mImagesPool.append(img);
    showNextImage();
}

void Widget::showNextImage()
{
    if (mImagesPool.isEmpty())
        return;
    emit process(mImagesPool.first());
}

void Widget::onProcessed(const QImage &img)
{
    if (mImagesPool.isEmpty())
        return;
    rawImage->setPixmap(QPixmap::fromImage(mImagesPool.takeFirst()));
    processedImage->setPixmap(QPixmap::fromImage(img));
    showNextImage();
}

处理器.cpp

void Processor::process(const QImage &img)
{
    QImage newImg = img;
    // Do stuff
    emit processed(newImg);
}

关于c++ - Qt C++ - 多线程视频帧转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30077177/

相关文章:

c++ - 在没有继承的情况下向 C++ 类添加功能

multithreading - 一个 Tcl 线程如何在另一个线程中引发事件?

Java-在for循环中创建线程时如何限制同时运行的线程数

qt - 第 : 1: Qt Quick emulation layer crashed 行

c++ - Qt QPainterpath.h 错误

c++ - 为什么 qmake -project 知道 hello.cpp 有 main 功能?

C++ Qt WriteProcessMemory

c++ - 如何在 Chrome Native Messaging Extension 的 native 应用程序中使用 native 主机消息

c++ - 如何处理错误警告 "Condition is always true",因为它实际上是由宏控制的

JAVAFX 如何更新 GUI 元素(节点)