multithreaded Qt+OpenCV

multithreaded Qt+OpenCV

本文关键字:Qt+OpenCV multithreaded      更新时间:2023-10-16

我将使用OpenCV和MAT类型制作一个线程,该线程从网络摄像头相机中收回图像。然后,我将其转换为qimage,并使用信号将其发送到主线程。当我想在UI中的Qlabel对象中可视化它(转换为PixMap之后)时,我会得到此错误:

该程序意外完成。

这是我的相机课:相机。H:

#ifndef CAMERA_H
#define CAMERA_H
#include <QObject>
#include <QThread>
#include <QtCore>
#include <QtGui>
#include <opencv2/opencv.hpp>
using namespace cv;
class Camera: public QThread
{
    Q_OBJECT
public:
    Camera();
    void run();
    bool Stop = false;
signals:
    void ImgSignal(QImage*);
private:
public slots:

};
#endif // THREAD_H

camera.cpp:

#include "camera.h"
#include <iostream>
using namespace std;
Camera::Camera()
{
}
void Camera::run()
{
    VideoCapture cap;
    cap.open(0);
    while(1){
        Mat img;
        cap >> img;
        cvtColor(img,img,CV_BGR2RGB);
        QImage image = QImage((const uchar*)img.data,img.cols,img.rows,img.step,QImage::Format_RGB888);
        emit ImgSignal(&image);
        QThread::msleep(30);
    }
}

最后,我的onimgsignal功能将图像收回并将其传递给GUI:

void MainWindow::onImgSignal(QImage *img)
{
    QPixmap *p;
    p->fromImage(*img);
    ui->label->setPixmap(*p);
}

如果您帮助我,我会很高兴。谢谢!

编辑当我将PixMap Poiner更改为PixMap变量时,错误不会出现,但是PixMap变量为null。即使我单独加载图像也将是零的:

QPixmap p;
p.load("mark.png");
cout << p.isNull();
ui->label->setPixmap(p);

我的第一个预感是,某些指向某些对象/内存的指针同时被两个不同的线程偶然访问,从而违反了访问权限。因此,通过仅制作您传递的图像的副本,可能会解决这个问题(因此,这两个线程AR都无法同时访问同一图像的像素数据)。您可以做其他一些事情来解决:

首先,QT中的线程实现有点非常规。例如,像您所做的那样扩展QThread类的最佳实践并不是最佳实践,因为QThread实例将不是现场直播在新的OS级线程中。是的!这是真的。这导致了许多混乱来源,进而导致错误。要阅读有关如何在QT中正确执行线程的官方非官方指南,请查看这篇出色的文章。简短摘要:QThread类将充当居住在您实例化的执行线程中的"管理"类,因此第一个提示是学习此内容,并按照预期使用QThread类。

第二,QT应该在信号时间内猜测源和目的地是否处于相同的线程,但是我发现有时候,仅出于心灵的安心,付费是具体说明如何通过信号。这就是为什么我的代码充满此的原因:

if(!connect(this,SIGNAL(colorChanged(QColor)),&ob,SLOT(onColorChanged(QColor)),(Qt::ConnectionType) (Qt::QueuedConnection | Qt::UniqueConnection) )) {
    qWarning()<<"ERROR: Could not connect "<<ob.objectName();
}

请注意连接调用的最后一个参数,因为它指定了Qt::QueuedConnectionQt::UniqueConnection连接。Qt::QueuedConnection意味着它是"线程安全",因为它将信号存储在螺纹安全的FIFO中。Qt::UniqueConnection只是意味着连接两次将第二次生成错误,而不是创建两个连接(这可能导致难以跟踪的错误)。

第三,您是否在不使用QT的情况下启动任何线程?在这种情况下,应使用信号进行护理,因为除非您使用QT启动线程,否则它们可能无法正常工作。我认为上面的Qt::QueuedConnection技巧应该足够了,但我不知道。这是更多。哦,如果OpenCV曾经有意或在不知不觉地启动其自己的某些线程,那么他们将算作"线程在qt之外启动"

第四,您是否在调试器中运行此操作?在什么确切的时候崩溃了?这应该是您的第一步,顺便说一句。

第五,如果其他所有因素都未能将代码包裹在QMutex中,并使用QMutexLocker确保没有问题。或者,您可能会很花哨,并使用一些线程安全的容器或类似的线程。

PS:请让我知道您的票价!