Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用QT+OpenCV实现多线程_C++_Multithreading_Qt_Opencv - Fatal编程技术网

C++ 使用QT+OpenCV实现多线程

C++ 使用QT+OpenCV实现多线程,c++,multithreading,qt,opencv,C++,Multithreading,Qt,Opencv,我正在编写一个简单的程序,它可以读取三个视频文件,三个摄像头在同一个房间里,使用三个不同的线程。我使用的代码如下所示: mainwindow.cpp 在开始的时候,同步是完美的工作,但后来看来,障碍不工作,线程没有等待对方 编辑3:已解决 似乎改变了 QThread::msleep(5); 到 解决了同步化的问题,尽管我并不真正理解其原因 即使没有背景减法,您也需要一些同步,以确保每个线程处理相同的帧数 在Qt中,最简单也是最正确的方法是删除无限循环,而是在所有线程发出信号帧完成后,调用每个线

我正在编写一个简单的程序,它可以读取三个视频文件,三个摄像头在同一个房间里,使用三个不同的线程。我使用的代码如下所示:

mainwindow.cpp

在开始的时候,同步是完美的工作,但后来看来,障碍不工作,线程没有等待对方

编辑3:已解决 似乎改变了

QThread::msleep(5);


解决了同步化的问题,尽管我并不真正理解其原因

即使没有背景减法,您也需要一些同步,以确保每个线程处理相同的帧数

在Qt中,最简单也是最正确的方法是删除无限循环,而是在所有线程发出信号帧完成后,调用每个线程的一个插槽来计算下一个映像

您可以进一步使用一些缓冲来预计算线程中的图像,并从该缓冲区加载它们。在该场景中,您可以执行以下操作:

Thread  1  processing frame  0
Thread  0  processing frame  0
Thread  2  processing frame  0
Thread  2  processing frame  1
Thread  1  processing frame  1
Thread  0  processing frame  1
Thread  2  processing frame  2
Thread  1  processing frame  2
Thread  0  processing frame  2
Thread  2  processing frame  3
Thread  1  processing frame  3
Thread  0  processing frame  3
Thread  2  processing frame  4
Thread  1  processing frame  4
Thread  0  processing frame  4
Thread  2  processing frame  5
Thread  0  processing frame  5
Thread  1  processing frame  5
Thread  2  processing frame  6
Thread  1  processing frame  6
Thread  2  processing frame  7
Thread  0  processing frame  6
Thread  1  processing frame  7
Thread  2  processing frame  8
Thread  0  processing frame  7
Thread  1  processing frame  8
Thread  2  processing frame  9
Thread  0  processing frame  8
Thread  1  processing frame  9
Thread  1  processing frame  10
Thread  2  processing frame  10
Thread  0  processing frame  9
Thread  1  processing frame  11
Thread  2  processing frame  11
Thread  0  processing frame  10
Thread  1  processing frame  12
只要有可用的缓冲区空间,您的每个线程就会在一个无止境的循环中填充他的缓冲区。如果缓冲区已满,线程将等待缓冲区空间释放

当gui显示并等待一段时间后,它会发送一个信号,该信号连接到每个线程的插槽,如SendMeaneImage

每个线程从其缓冲区发送下一个可用映像,或者等待无限循环或条件等待映像(如果缓冲区为空)。然后发出frameFinished信号并释放已使用的缓冲区空间

当每个线程发出信号后,显示所有图像,等待一段时间,然后再次发出SendMeanseImage

这还不是线程安全的,在从缓冲区读写时,您将有关键部分。对于每个缓冲区,创建一个QMutex并在从该缓冲区读取、写入或请求大小等时调用mutex.lock。之后立即调用mutex.unlock


当一个互斥锁被锁定,而另一个线程或甚至同一个线程试图再次锁定它时,该线程将在那里等待,直到另一个线程解锁互斥锁。这样,只有一个线程才能进入关键部分。

即使没有背景减法,您也需要一些同步,以确保每个线程处理相同的帧数。在Qt中,最简单也是最正确的方法是删除无限循环,而是在所有线程发出信号帧完成后,调用每个线程的一个插槽来计算下一个映像。您还可以进一步使用一些缓冲来预计算线程中的图像,然后从该缓冲区加载它们。我发现这个解决方案使用屏障在代码中创建线程应该等待的点。这意味着当最后一个线程到达屏障时,所有线程都将继续。我已经实现了这样的调用,等待是在发出frameFinished之前。你认为正确吗?试试看。可能会有用。我没读过,但听起来和我的方法很相似。
#ifndef BARRIER_H
#define BARRIER_H

#include <QMutex>
#include <QWaitCondition>
#include <QSharedPointer>

// Data "pimpl" class (not to be used directly)
class BarrierData
{
public:
    BarrierData(int count) : count(count) {}

    void wait() {
        mutex.lock();
        --count;
        if (count > 0)
            condition.wait(&mutex);
        else
            condition.wakeAll();
        mutex.unlock();
    }
private:
    Q_DISABLE_COPY(BarrierData)
    int count;
    QMutex mutex;
    QWaitCondition condition;
};

class Barrier {
public:
    // Create a barrier that will wait for count threads
    Barrier(int count) : d(new BarrierData(count)) {}
    void wait() {
        d->wait();
    }

private:
    QSharedPointer<BarrierData> d;
};

#endif // BARRIER_H
void Worker::readVideo()
{
    VideoCapture cap(filepath.toStdString());

    int framenumber = 0;
    if (! cap.isOpened()) {
        qDebug() << "Can't open video file " << filepath;
        emit finished(index);
        return;
    }

    Mat ActualFrame;
    while (true) {
        cap >> ActualFrame;

        if (ActualFrame.empty()) {
            // Empty frame to display when the video has finished
            ActualFrame = Mat(Size(720, 576), CV_8UC3, Scalar(192, 0, 0));
            emit frameFinished(ActualFrame, index);

            qDebug() << "Video finished";
            break;
        }

        // Background Subtraction
        BackgroundSubtraction(ActualFrame, BackgroundMask);

        QThread::msleep(5);
        barrier.wait();
        qDebug() << "Thread " << index << " processing frame " << framenumber ;
        emit frameFinished(ActualFrame.clone(), index);
        framenumber++;
    }
    emit finished(index);
}

void Worker::BackgroundSubtraction(Mat ActualFrame, Mat &BackgroundMask)
{
    pMOG2->apply(ActualFrame, BackgroundMask);
}
Thread  1  processing frame  0
Thread  0  processing frame  0
Thread  2  processing frame  0
Thread  2  processing frame  1
Thread  1  processing frame  1
Thread  0  processing frame  1
Thread  2  processing frame  2
Thread  1  processing frame  2
Thread  0  processing frame  2
Thread  2  processing frame  3
Thread  1  processing frame  3
Thread  0  processing frame  3
Thread  2  processing frame  4
Thread  1  processing frame  4
Thread  0  processing frame  4
Thread  2  processing frame  5
Thread  0  processing frame  5
Thread  1  processing frame  5
Thread  2  processing frame  6
Thread  1  processing frame  6
Thread  2  processing frame  7
Thread  0  processing frame  6
Thread  1  processing frame  7
Thread  2  processing frame  8
Thread  0  processing frame  7
Thread  1  processing frame  8
Thread  2  processing frame  9
Thread  0  processing frame  8
Thread  1  processing frame  9
Thread  1  processing frame  10
Thread  2  processing frame  10
Thread  0  processing frame  9
Thread  1  processing frame  11
Thread  2  processing frame  11
Thread  0  processing frame  10
Thread  1  processing frame  12
QThread::msleep(5);
QThread::msleep(35);