2

アプリケーション (opencv-opengl 統合) にマルチスレッドを追加したいのですが、この回答にある構造から始めています。今のところ、ビデオ フレームを取得してそれを MainWindow に送信するスレッドがあります。

私は少し検索しようとしましたが、それを明確にするものは何もなく、物事をより曖昧にするだけです.

サブクラス化するのではなく使用するという記事を読んだとしても、それを行うという別の記事をどこかで(公式の例の1つ以外)読んでいます。QThreadmoveToThread()

アプリケーションを実行してから閉じると、クラッシュします。アプリケーションを実行し、 を呼び出して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();
    }
}
4

1 に答える 1

0

をサブクラス化しないでくださいQThreadQObjectスロットを含むのサブクラスを作成します。このスロットには、無限ループの 1 回の反復のコードが含まれている必要があります (ループは削除する必要があります)。オブジェクトを作成し、QThreadを使用してオブジェクトをこのスレッドに移動しますmoveToThread。を作成しQTimer、それをオブジェクトのスロットに接続して、目的の間隔 (20 ミリ秒) で開始します。オブジェクトは他のスレッドに属しているため、そのスロットはそのスレッドで定期的に実行されます。実行を停止したい場合は、スレッド上でquit()andを呼び出します。wait()実行を停止します。

于 2013-07-29T22:17:16.807 に答える