c++ - 使用循环停止 QThread 的正确方法(从 opencv 读取视频)

标签 c++ multithreading qt opencv qthread

我想在我的应用程序中添加一些多线程(opencv-opengl 集成),我从 this answer 中找到的结构开始.现在只有一个线程可以抓取视频帧并将其发送到 MainWindow,仅此而已。

我试着搜索了一下,但没有任何东西能说清楚,只会让事情变得更加模糊。

即使我阅读了an article那说不要子类化 QThread 而是使用 moveToThread() 我在某处读了另一篇文章(one of the official example 之外)说要这样做。

如果我运行应用程序然后关闭它会崩溃。 如果我运行该应用程序并调用 endCapture 然后重新开始......它再次崩溃。

感谢各种帮助或评论!

这是 VideoThread.h:

#ifndef VIDEOTHREAD_H
#define VIDEOTHREAD_H

#include <QMutex>
#include <QImage>
#include <QThread>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

class VideoThread : public QThread
{
    Q_OBJECT
public:
    explicit VideoThread(QObject *parent = 0);
    ~VideoThread();

protected:
    void run();

private:
    cv::VideoCapture video;

    QMutex m_AbortCaptureLock;
    bool m_AbortCapture;

signals:
    void sendImage(QImage);

public slots:
    void endCapture();
};

#endif // VIDEOTHREAD_H

VideoThread.cpp:

#include "videothread.h"

#include <QDebug>

VideoThread::VideoThread(QObject *parent) :
    QThread(parent)
{
    qDebug() << "VideoThread > ctor.";
}

VideoThread::~VideoThread()
{
    qDebug() << "VideoThread > dtor";

    if(video.isOpened()) {
        video.release();
        qDebug() << "Camera successfully disconnected.";
    }
}

void VideoThread::run()
{
    m_AbortCapture = false;
    video = cv::VideoCapture(0);
    qDebug() << "VideoThread::run..";

    while(true)
    {
        m_AbortCaptureLock.lock();
        if (m_AbortCapture) {
            qDebug() << "VideoThread::run > abort capture..";
            break;
        }
        m_AbortCaptureLock.unlock();

        cv::Mat cvFrame;
        video >> cvFrame;
        if(cvFrame.empty()) continue;

        // convert the Mat to a QImage
        QImage qtFrame(cvFrame.data, cvFrame.size().width, cvFrame.size().height, cvFrame.step, QImage::Format_RGB888);
        qtFrame = qtFrame.rgbSwapped();

        // queue the image to the gui
        emit sendImage(qtFrame);
        msleep(20);
    }
}

void VideoThread::endCapture()
{
    qDebug() << "VideoThread::endCapture()";

    m_AbortCaptureLock.lock();
    m_AbortCapture = true;
    m_AbortCaptureLock.unlock();
}

这里是主要的:

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "opencv_glwidget.h"

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

    OpenCV_GLWidget *w = new OpenCV_GLWidget();
    w->setParent(this->centralWidget());

    connect(ui->checkBox, SIGNAL(toggled(bool)),
            this, SLOT(toggle(bool)));
    ui->checkBox->toggle();

    connect(&thread, SIGNAL(sendImage(QImage)),
            w, SLOT(renderImage(QImage)));
    thread.start();
}

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

void MainWindow::toggle(bool n)
{
    if(n) {
        thread.start();
    } else {
        thread.endCapture();
    }
}

最佳答案

不要继承QThread。创建包含插槽的 QObject 的子类。该插槽应包含无限循环一次迭代的代码(应删除循环)。创建一个 QThread 对象并使用 moveToThread 将您的对象移动到该线程。创建一个 QTimer,将它连接到对象的插槽并以所需的时间间隔(20 毫秒)启动它。由于该对象属于其他线程,因此它的槽将在该线程中定期执行。当你想停止执行时,在线程上调用 quit()wait()。它将停止执行。

关于c++ - 使用循环停止 QThread 的正确方法(从 opencv 读取视频),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17934898/

相关文章:

c++ - 如何确保在采用数组的 constexpr 函数中该数组以 NULL 结尾?

.net - 多核使用、线程、线程池

java - 如何创建 session 范围的线程安全对象实例?

Java volatile 变量问题

c++ - Qt 没有匹配函数供调用

c++ - 如何正确处理 win32 GUI 消息循环?

java - 社交网络架构、C++ Clients Neo4j 数据库之间有什么关系?

java - 在 linux 中从 C++ 执行 java

c++ - 如何将非透明背景切换为透明背景子窗口

c++ - Qt NetworkAccessManager 完成信号