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