QT OpenCV多线程获取图像并在GUI主线程中显示

时间:2015-06-14 14:40:33

标签: c++ multithreading qt opencv qthread

基本理念

我正在开发一个带有4个USB摄像头的应用程序,必须从所有这些摄像头中取出帧,并以最佳fps显示在QLabel中。

即使我的处理器只有20%的利用率,从所有摄像机中逐帧获取帧也会导致帧速率降低。

我认为如何提高帧率?

使用多线程可以增加CPU利用率,并且可以有 4个线程每个从各个摄像头获取图像,发送信号并将图像发送回GUI线程(主线程)将显示图像转换为适当的标签。

当前设计:基于https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

Thread类继承自QObject,方法为:

class fetchCam1 : public QObject
{
    Q_OBJECT

public:
    fetchCam1(cv::VideoCapture cap);
    ~fetchCam1();

public slots:
    void process();
    cv::Mat returnCamFrame();

signals:
    void finished();
};

其实施:

fetchCam1::fetchCam1(cv::VideoCapture cap)
{
    this->cap = cap;
}

cv::Mat fetchCam1::returnCam1Frame()
{
    return src;
}

void fetchCam1::process() {
    // allocate resources using new here
    cap.read(src);
    emit finished();
}

在Main(GUI)线程中启动线程和辅助角色:

    The captureS1..S4, Is the VideoCapture object, also fetchCam1* worker1-4, 
    QThread* thread1-4; are defined as global variables.

thread1 = new QThread;
worker1 = new fetchCam1(captureS1);
worker1->moveToThread(thread1);
connect(thread1, SIGNAL(started()), worker1, SLOT(process()));
connect(worker1, SIGNAL(finished()), this, SLOT(updateCam1()));
connect(worker1, SIGNAL(finished()), worker1, SLOT(process()));
thread1->start();

thread2 = new QThread;
worker2 = new fetchCam1(captureS2);
worker2->moveToThread(thread2);
connect(thread2, SIGNAL(started()), worker2, SLOT(process()));
connect(worker2, SIGNAL(finished()), this, SLOT(updateCam2()));
connect(worker2, SIGNAL(finished()), worker2, SLOT(process()));
thread2->start();

thread3 = new QThread;
worker3 = new fetchCam1(captureS3);
worker3->moveToThread(thread3);
connect(thread3, SIGNAL(started()), worker3, SLOT(process()));
connect(worker3, SIGNAL(finished()), this, SLOT(updateCam3()));
connect(worker3, SIGNAL(finished()), worker3, SLOT(process()));
thread3->start();

thread4 = new QThread;
worker4 = new fetchCam1(captureS4);
worker4->moveToThread(thread4);
connect(thread4, SIGNAL(started()), worker4, SLOT(process()));
connect(worker4, SIGNAL(finished()), this, SLOT(updateCam4()));
connect(worker4, SIGNAL(finished()), worker4, SLOT(process()));
thread4->start();

每个都调用:

void MainWindow::updateCam1()
{
    cv::Mat src = worker1->returnCamFrame();
    QPixmap pixg = convertFromMat(src);
    ui->label_4s1->setPixmap(pixg);
}
void MainWindow::updateCam2()
{
    cv::Mat src = worker1->returnCamFrame();
    QPixmap pixg = convertFromMat(src);
    ui->label_4s2->setPixmap(pixg);
}
void MainWindow::updateCam3()
{
    cv::Mat src = worker1->returnCamFrame();
    QPixmap pixg = convertFromMat(src);
    ui->label_4s3->setPixmap(pixg);
}
void MainWindow::updateCam4()
{
    cv::Mat src = worker1->returnCamFrame();
    QPixmap pixg = convertFromMat(src);
    ui->label_4s4->setPixmap(pixg);
}

请帮我辨别我做错了什么?上面的代码确实启动并加载了前几帧,之后程序崩溃,没有任何错误。

此外,如果只使用一个线程从一个摄像头获取图像,则上述代码效果很好。

实施此方法的正确方法是什么?谢谢。

更新 崩溃:

我相信所有4台摄像机的帧都被快速取出,并且这会产生太多信号供主线程处理,这会导致溢出导致崩溃。 我相信某种同步可以帮助但我怎么能去做呢?

0 个答案:

没有答案