QR扫码综合示例教程(九)Qt5.15.2+Qt6.2.1(widget)+opencv4.5.4实现扫码功能(多线程)

前言:

上篇教程就提到了,加入扫码后,程序会变的很卡顿,本教程通过多线程的方式,解决卡顿问题

同时这也可能是本系列教程的最后一篇widget的文档了

本教程是在 Qt5.15.2+Qt6.2.1(widget)+opencv4.5.4实现扫码功能 示例的基础上修改

一、修改处理类

类Tool_Process头文件修改如下
#include "opencv2/opencv.hpp"
#include <QObject>
#include <QImage>
#include <QTimerEvent>
#include <QMutex>

class Tool_Process : public QObject
{
    Q_OBJECT
public:
    explicit Tool_Process(QObject *parent = nullptr);
    ~Tool_Process();

    //添加待处理的图像
    void setImage(const QImage &image);
signals:
    //返回已解读的二维码数据
    void qrString(const QString string);

    //启动定时器
    void start();
protected:
    //处理定时器事件
    void timerEvent(QTimerEvent *event) override;
private:
    //二维码解码
    void process();
    //将QImgae对象转换为cv::Mat
    cv::Mat QImage2cvMat(QImage image);

    //启动定时器
    void onStart();

    //保存的图像
    QImage m_image;
    //定时器Id
    int m_timerId = -1;
    //互斥量
    QMutex m_mutex;

源文件修改的关键代码

以下代码是为类提供一个定时器,定时器会定时执行一次处理函数,处理已保存的图像

Tool_Process::~Tool_Process()
{
    if(m_timerId >= 0)
        killTimer(m_timerId);
}

/*!
 * \brief Tool_Process::onStart 启动定时器
 */
void Tool_Process::onStart()
{
    if(m_timerId < 0)
        m_timerId = startTimer(200);
}

/*!
 * \brief Tool_Process::timerEvent 处理定时器事件
 * \param event
 */
void Tool_Process::timerEvent(QTimerEvent *event)
{
    if(event->timerId() == m_timerId )
    {
        process();
        return;
    }
    QObject::timerEvent(event);
}

新添加的处理函数

/*!
 * \brief Tool_Process::process 二维码解码
 */
void Tool_Process::process()
{
    QImage image;
    {
        QMutexLocker locker(&m_mutex);
        if(m_image.isNull())
            return;
        image = m_image;
        m_image = QImage();
    }
    cv::QRCodeDetector  decoder;
    cv::Mat  mat,bbox,rect;
    mat=QImage2cvMat(image);
    if(decoder.detect(mat,bbox)){
        qDebug()<<"getQRCode";
         std::string result = decoder.decode(mat,bbox);

         const QString resultString = QString::fromStdString(result);
         qDebug() << "QRdecoder"<<resultString;
         if(!resultString.isEmpty())
             emit qrString(resultString);

    }
}

说明:

1.在程序运行时,主线程调用setImage()函数,不停注入新的图像,但处理类只保留最后一张图像

2.process()运行在新开的线程中,被定时触发,若有图像未处理,就处理掉

二、修改调用方式(使用多线程)

在主程序中,处理类的处理函数初始化修改下,将处理类放在新开的线程序中

以下代码供小伙伴们参考

//初始化处理类
        m_tool_Process = new Tool_Process;
        QThread *thread = new QThread;

        connect(m_tool_Process, &Tool_Process::destroyed, thread, &QThread::quit);
        connect(thread, &QThread::finished, thread, &QThread::deleteLater);
        connect(m_tool_Process, &Tool_Process::qrString,[this](const QString string){
            ui->lineEdit_result->setText(string);
        });

        m_tool_Process->moveToThread(thread);
        thread->start();

        emit m_tool_Process->start();

修改完成以上代码,就可以运行程序了,以下是笔者的运行结果

 可以很明显的感觉到,之前的卡顿感没了

本次教程源码下载

后记:

在Qt中,越来越多的使用qml,在写本教程时,同事曾建议直接使用qml。考虑到不小伙伴对qml不熟悉,笔者坚持先进行widget的例程。

今天因为搬家耽误了太多时间,具体的教程只能明天再写了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

꧁白杨树下꧂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值