欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Qt和Opencv實(shí)現(xiàn)二維碼解析

 更新時(shí)間:2024年11月22日 15:22:44   作者:極客晨風(fēng)  
這篇文章主要為大家詳細(xì)介紹了如何利用?Qt?和?OpenCV?實(shí)現(xiàn)一個(gè)可從視頻和圖片中檢測二維碼的軟件,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

本文詳細(xì)講解了如何利用 Qt 和 OpenCV 實(shí)現(xiàn)一個(gè)可從視頻和圖片中檢測二維碼的軟件。代碼實(shí)現(xiàn)了視頻解碼、多線程處理和界面更新等功能,是一個(gè)典型的跨線程圖像處理項(xiàng)目。以下分模塊對代碼進(jìn)行解析。

一、項(xiàng)目的整體結(jié)構(gòu)

項(xiàng)目分為以下幾部分:

主窗口 (MainWindow) :負(fù)責(zé)界面的加載、初始化和用戶交互。

工作線程 (mThread):處理耗時(shí)的圖像處理任務(wù)(如二維碼識別)。

二維碼檢測邏輯:使用 OpenCV 進(jìn)行二維碼檢測,支持圖片和視頻兩種數(shù)據(jù)來源。

多線程通信:通過信號與槽機(jī)制,在主線程和工作線程之間傳遞狀態(tài)與數(shù)據(jù)。

二、主窗口功能解析

1. 初始化界面和變量

MainWindow 類的構(gòu)造函數(shù)調(diào)用了 initializeUI() 和 initializeVariable(),分別完成了界面的樣式加載和核心變量的初始化。

void MainWindow::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 = new mThread();  // 創(chuàng)建工作線程
    m_Threadrun = false;

    // 線程信號與主窗口槽函數(shù)的連接
    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. 啟動(dòng)和停止線程

用戶點(diǎn)擊按鈕后,調(diào)用 on_btn_Start_Stop_clicked,判斷當(dāng)前線程狀態(tài)以啟動(dòng)或停止工作線程。

void MainWindow::on_btn_Start_Stop_clicked()
{
    m_Threadrun ? mthread->stop() : mthread->start(); // 根據(jù)當(dāng)前狀態(tài)啟動(dòng)或停止線程
}

3. 文件選擇

QFileDialog 被用來讓用戶選擇視頻或圖像文件,并將這些參數(shù)傳遞到線程處理。

void MainWindow::on_btn_Loadfile_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(nullptr, tc("選擇視頻文件"), "", tc("視頻文件(*.mp4)"));
    mthread->setFunId(0); // 設(shè)置功能 ID:0 表示處理視頻
    if (!fileName.isEmpty())
        mthread->setThreadParams(fileName); // 傳遞參數(shù)到線程
}

void MainWindow::on_btn_Loadimages_clicked()
{
    QStringList fileNames = QFileDialog::getOpenFileNames(nullptr, tc("選擇圖像文件"), "", tc("圖片文件(*.jpg *.bmp *.png)"));
    mthread->setFunId(1); // 設(shè)置功能 ID:1 表示處理圖片
    if (!fileNames.isEmpty())
        mthread->setThreadParams(fileNames);
}

三、工作線程實(shí)現(xiàn)

mThread 類繼承自 QThread,用于處理耗時(shí)的二維碼檢測任務(wù)。其主要功能包括:

根據(jù)功能 ID 分別處理視頻或圖片。

在每幀中調(diào)用 OpenCV 的 QRCodeDetector 進(jìn)行二維碼檢測。

通過信號將處理后的圖像和數(shù)據(jù)傳遞回主線程。

1. 核心線程邏輯

線程的運(yùn)行邏輯集中在 run() 方法中。getFunId() 決定了是處理視頻還是圖片,分別調(diào)用 anayVideo() 或 anayImages()。

void mThread::run()
{
    m_isRun = true;
    emit RuningState(true); // 通知主線程:線程開始運(yùn)行
    emit infors(tc("線程啟動(dòng)"));

    switch (getFunId()) {
    case 0:
        anayVideo(); // 處理視頻
        break;
    case 1:
        anayImages(); // 處理圖片
        break;
    default:
        break;
    }

    emit RuningState(false); // 通知主線程:線程結(jié)束運(yùn)行
    emit infors(tc("線程退出"));
}

2. 視頻處理

在 anayVideo() 中,使用 OpenCV 的 VideoCapture 解碼視頻逐幀處理。每一幀調(diào)用 delectDecoded() 檢測二維碼,并通過信號將結(jié)果傳回主線程。

void mThread::anayVideo()
{
    cv::VideoCapture cap;
    if (!cap.open(m_Params.toString().toLocal8Bit().data()) || !cap.isOpened())
    {
        emit errors(tc("視頻未打開"));
        m_isRun = false;
    }
    else
    {
        cv::Mat frame;
        int frameCount = cap.get(cv::CAP_PROP_FRAME_COUNT);
        while ((frameCount--) > 0 && m_isRun) // 幀循環(huán)
        {
            cap >> frame; // 讀取一幀
            if (frame.empty())
                break;

            QString msg;
            delectDecoded(frame, msg); // 檢測二維碼
            emit imageProcessed(MatToQImage(frame), msg); // 發(fā)射處理信號
            cv::waitKey(50);
        }
        cap.release();
    }
}

3. 圖片處理

圖片處理邏輯與視頻類似,只是直接從文件路徑中讀取。

void mThread::anayImages()
{
    QStringList files = m_Params.toStringList();
    for (auto file : 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); // 發(fā)射信號
        cv::waitKey(1000);
    }
}

四、二維碼檢測實(shí)現(xiàn)

1. 使用 OpenCV 進(jìn)行檢測

在 delectDecoded() 方法中,利用 OpenCV 的 QRCodeDetector 類進(jìn)行二維碼檢測和解碼,并將結(jié)果繪制到圖像中。

int mThread::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); // 將結(jié)果返回
        std::vector<cv::Point> points;
        for (int i = 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); // 繪制綠色邊框
        }
        int minY = points[0].y;
        for (const auto &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("未檢測到二維碼!");
    }

    return 0;
}

2. Mat 轉(zhuǎn) QImage

為了在 Qt 界面中顯示 OpenCV 的圖像,MatToQImage() 將 OpenCV 的 cv::Mat 轉(zhuǎn)換為 Qt 的 QImage。

五、多線程與信號槽

在本項(xiàng)目中,多線程通過信號與槽實(shí)現(xiàn)以下功能:

更新主界面狀態(tài):線程的運(yùn)行狀態(tài)(如啟動(dòng)和停止)通過 RuningState 信號通知主線程。

實(shí)時(shí)更新圖像和檢測結(jié)果:imageProcessed 信號傳遞處理后的圖像和二維碼信息,更新界面。

connect(mthread, &mThread::imageProcessed, this, &MainWindow::processImage);

???????void MainWindow::processImage(const QImage &image, const QString &msg)
{
    ui->lab_disp->setPixmap(QPixmap::fromImage(image).scaled(image.width() / 2, image.height() / 2)); // 顯示縮放后的圖像
    ui->lab_disData->setText(msg); // 顯示檢測到的信息
}

以上就是基于Qt和Opencv實(shí)現(xiàn)二維碼解析的詳細(xì)內(nèi)容,更多關(guān)于Qt Opencv二維碼解析的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語言實(shí)現(xiàn)職工工資管理系統(tǒng)的示例代碼

    C語言實(shí)現(xiàn)職工工資管理系統(tǒng)的示例代碼

    這篇文章主要為大家詳細(xì)介紹了C語言如何實(shí)現(xiàn)職工工資管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • C++傳值、傳址、傳引用的區(qū)別和選擇小結(jié)

    C++傳值、傳址、傳引用的區(qū)別和選擇小結(jié)

    參數(shù)傳遞有傳值、傳址和傳引用這三種,本文主要介紹了C++傳值、傳址、傳引用的區(qū)別和選擇小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07
  • 淺談2路插入排序算法及其簡單實(shí)現(xiàn)

    淺談2路插入排序算法及其簡單實(shí)現(xiàn)

    這篇文章主要介紹了淺談2路插入排序算法及其簡單實(shí)現(xiàn),雖算不上是常用的排序方法,但在數(shù)據(jù)庫等方面依然有用上的機(jī)會,需要的朋友可以參考下
    2015-08-08
  • 利用C++實(shí)現(xiàn)簡易的.ini配置文件解析器

    利用C++實(shí)現(xiàn)簡易的.ini配置文件解析器

    這篇文章主要為大家詳細(xì)介紹了如何基于C++編寫一個(gè)簡易的.ini配置文件解析器,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解一下
    2023-03-03
  • CentOS下Jsoncpp安裝配置的方法

    CentOS下Jsoncpp安裝配置的方法

    本文主要介紹了CentOS下Jsoncpp安裝配置的方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 基于c的for循環(huán)中改變變量值的問題

    基于c的for循環(huán)中改變變量值的問題

    本篇文章是對c語言的for循環(huán)中改變變量值的問題進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C語言實(shí)現(xiàn)的統(tǒng)計(jì)素?cái)?shù)并求和代碼分享

    C語言實(shí)現(xiàn)的統(tǒng)計(jì)素?cái)?shù)并求和代碼分享

    這篇文章主要介紹了C語言實(shí)現(xiàn)的統(tǒng)計(jì)素?cái)?shù)并求和代碼分享,來自PAT平臺(浙江大學(xué)計(jì)算機(jī)程序設(shè)計(jì)能力考試系統(tǒng))的一個(gè)題目,需要的朋友可以參考下
    2014-08-08
  • C/C++ Zlib庫封裝MyZip壓縮類的詳細(xì)過程

    C/C++ Zlib庫封裝MyZip壓縮類的詳細(xì)過程

    在軟件開發(fā)中,文件的壓縮和解壓縮是一項(xiàng)常見的任務(wù),而ZIP是一種被廣泛應(yīng)用的壓縮格式,本文將聚焦于一個(gè)簡化的C++實(shí)現(xiàn),通過分析代碼,我們將深入了解其設(shè)計(jì)和實(shí)現(xiàn)細(xì)節(jié),感興趣的朋友一起看看吧
    2023-11-11
  • QT編寫tcp通信工具(Client篇)

    QT編寫tcp通信工具(Client篇)

    這篇文章主要介紹了QT編寫tcp通信工具,適用于Client端,類似網(wǎng)上常見的網(wǎng)絡(luò)調(diào)試工具,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • C++實(shí)現(xiàn)延遲的方法詳解

    C++實(shí)現(xiàn)延遲的方法詳解

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)延遲的三個(gè)方法,文中的示例代碼講解詳細(xì),對我們深入了解C++有一定的幫助,感興趣的小伙伴可以學(xué)習(xí)一下
    2022-12-12

最新評論