以下分模块对代码进行解析

发布时间:2025-06-24 19:51:51  作者:北方职教升学中心  阅读量:406


多线程与信号槽

在本项目中,多线程通过信号与槽实现以下功能:

  1. 更新主界面状态:线程的运行状态(如启动和停止)通过 RuningState信号通知主线程。

    voidMainWindow::on_btn_Start_Stop_clicked(){m_Threadrun ?mthread->stop():mthread->start();// 根据当前状态启动或停止线程}
    3. 文件选择

    QFileDialog被用来让用户选择视频或图像文件,并将这些参数传递到线程处理。

1. 核心线程逻辑

线程的运行逻辑集中在 run()方法中。代码实现了视频解码、

voidmThread::run(){m_isRun =true;emit RuningState(true);// 通知主线程:线程开始运行emit infors(tc("线程启动"));switch(getFunId()){case0:anayVideo();// 处理视频break;case1:anayImages();// 处理图片break;default:break;}emit RuningState(false);// 通知主线程:线程结束运行emit infors(tc("线程退出"));}
2. 视频处理

anayVideo()中,使用 OpenCV 的 VideoCapture解码视频逐帧处理。二维码检测实现

1. 使用 OpenCV 进行检测

delectDecoded()方法中,利用 OpenCV 的 QRCodeDetector类进行二维码检测和解码,并将结果绘制到图像中。

  • 多线程通信:通过信号与槽机制,在主线程和工作线程之间传递状态与数据。
  • 在每帧中调用 OpenCV 的 QRCodeDetector进行二维码检测

    intmThread::delectDecoded(cv::Mat &image,QString &code){cv::Mat bbox,rectifiedImage;std::string data =qrDecoder.detectAndDecode(image,bbox,rectifiedImage);if(data.length()>0){code =QString::fromStdString(data);// 将结果返回std::vector<cv::Point>points;for(inti =0;i <bbox.cols;i++){points.push_back(cv::Point(static_cast<int>(bbox.at<cv::Point2f>(0,i).x),static_cast<int>(bbox.at<cv::Point2f>(0,i).y)));}for(size_t i =0;i <points.size();i++){cv::line(image,points[i],points[(i +1)%points.size()],cv::Scalar(0,255,0),3);// 绘制绿色边框}intminY =points[0].y;for(constauto&point :points){minY =std::min(minY,point.y);}cv::putText(image,data,cv::Point(points[0].x,minY -10),cv::FONT_HERSHEY_SIMPLEX,0.7,cv::Scalar(0,255,0),2);// 显示二维码信息}else{code =tc("未检测到二维码!");}return0;}
    2. Mat 转 QImage

    为了在 Qt 界面中显示 OpenCV 的图像,MatToQImage()将 OpenCV 的 cv::Mat转换为 Qt 的 QImage。其主要功能包括:

    1. 根据功能 ID 分别处理视频或图片


      五、

      voidMainWindow::on_btn_Loadfile_clicked(){QString fileName =QFileDialog::getOpenFileName(nullptr,tc("选择视频文件"),"",tc("视频文件(*.mp4)"));mthread->setFunId(0);// 设置功能 ID:0 表示处理视频if(!fileName.isEmpty())mthread->setThreadParams(fileName);// 传递参数到线程}voidMainWindow::on_btn_Loadimages_clicked(){QStringList fileNames =QFileDialog::getOpenFileNames(nullptr,tc("选择图像文件"),"",tc("图片文件(*.jpg *.bmp *.png)"));mthread->setFunId(1);// 设置功能 ID:1 表示处理图片if(!fileNames.isEmpty())mthread->setThreadParams(fileNames);}

      三、


      在这里插入图片描述
      在这里插入图片描述

      一、工作线程实现

      mThread类继承自 QThread,用于处理耗时的二维码检测任务。多线程处理和界面更新等功能,是一个典型的跨线程图像处理项目。初始化和用户交互。

    2. 通过信号将处理后的图像和数据传递回主线程
    connect(mthread,&mThread::imageProcessed,this,&MainWindow::processImage);voidMainWindow::processImage(constQImage &image,constQString &msg){ui->lab_disp->setPixmap(QPixmap::fromImage(image).scaled(image.width()/2,image.height()/2));// 显示缩放后的图像ui->lab_disData->setText(msg);// 显示检测到的信息}

  • voidMainWindow::initializeVariable(){m_tip =nullptr;m_lamp[0]=QImage(":/Img/e.png");m_lamp[1]=QImage(":/Img/i.png");m_lamp[2]=QImage(":/Img/w.png");mthread =newmThread();// 创建工作线程m_Threadrun =false;// 线程信号与主窗口槽函数的连接connect(mthread,SIGNAL(RuningState(bool)),this,SLOT(onRespondThreadRuningState(bool)));connect(mthread,SIGNAL(errors(QString)),this,SLOT(onRespondThreaderrors(QString)));connect(mthread,SIGNAL(infors(QString)),this,SLOT(onRespondThreadinfors(QString)));connect(mthread,SIGNAL(warings(QString)),this,SLOT(onRespondThreadwarings(QString)));connect(mthread,&mThread::imageProcessed,this,&MainWindow::processImage);}
    2. 启动和停止线程

    用户点击按钮后,调用 on_btn_Start_Stop_clicked,判断当前线程状态以启动或停止工作线程。项目的整体结构

    项目分为以下几部分:

    1. 主窗口(MainWindow) :负责界面的加载、

    二、

    本文详细讲解了如何利用 Qt 和 OpenCV 实现一个可从视频和图片中检测二维码的软件。

    voidmThread::anayVideo(){cv::VideoCapture cap;if(!cap.open(m_Params.toString().toLocal8Bit().data())||!cap.isOpened()){emit errors(tc("视频未打开"));m_isRun =false;}else{cv::Mat frame;intframeCount =cap.get(cv::CAP_PROP_FRAME_COUNT);while((frameCount--)>0&&m_isRun)// 帧循环{cap >>frame;// 读取一帧if(frame.empty())break;QString msg;delectDecoded(frame,msg);// 检测二维码emit imageProcessed(MatToQImage(frame),msg);// 发射处理信号cv::waitKey(50);}cap.release();}}
    3. 图片处理

    图片处理逻辑与视频类似,只是直接从文件路径中读取。

  • 二维码检测逻辑:使用 OpenCV 进行二维码检测,支持图片和视频两种数据来源。每一帧调用 delectDecoded()检测二维码,并通过信号将结果传回主线程。getFunId()决定了是处理视频还是图片,分别调用 anayVideo()anayImages()
  • 实时更新图像和检测结果imageProcessed信号传递处理后的图像和二维码信息,更新界面。以下分模块对代码进行解析。主窗口功能解析
  • 1. 初始化界面和变量

    MainWindow类的构造函数调用了 initializeUI()initializeVariable(),分别完成了界面的样式加载和核心变量的初始化。

  • 工作线程(mThread):处理耗时的图像处理任务(如二维码识别)。

    voidmThread::anayImages(){QStringList files =m_Params.toStringList();for(autofile :files){cv::Mat frame =cv::imread(file.toStdString().c_str());if(frame.empty()&&!m_isRun)break;QString msg;delectDecoded(frame,msg);emit imageProcessed(MatToQImage(frame),msg);// 发射信号cv::waitKey(1000);}}

    四、