Qt集成OpenCV使用PaddleOCR进行文字识别


前言

近期在进行OpenCV的学习,在查询相关资料的过程中发现了一个很好的项目,是关于Qt集成OpenCV使用PaddleOCR做文本检测与识别的,然后也是下载了大佬的开源项目来进行学习,并结合大佬写的博客进行配置,在其项目基础上进行了一些修改,优化了相关代码,详细内容见下文,大家可以参考学习,如有错误之处,欢迎大家批评指正。

项目效果
请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、下载Paddle_inference Windows C++预测库

从官网下载新的预测库:下载安装Windows预测库

请添加图片描述

解压后内容如下:
请添加图片描述

二、下载Demo程序

从大佬的github主页下载程序:QT-OCR-Demo
请添加图片描述

我编译的是其中的paddleOCR项目,内容如下:
请添加图片描述

三、编译Demo程序

我目前使用的是OpenCV 4.5.2,预测库也与大佬使用的不一样,一开始按照其博客内容进行修改,始终无法成功编译运行,于是自己重新整理了一下依赖项,在源码路径新建了一个SDK文件夹包含了OpenCV和预测库文件以及程序运行时需要的dll,最后也是成功运行,该SDK文件夹可在下文百度网盘链接中获取。(OpenCV也是需要配置的,可以查看我之前写的这篇文章进行参考:Window下Qt5.14_MinGW_64bit+CMake_3.24+OpenCV_4.5.1环境搭建

我的构建套件为MSVC_64bit Release,生成exe后需要在同级目录添加上述SDK的Dll文件夹内的dll,这样便运行成功了,修改程序的pro内容如下:
paddleOCRDemo.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

#定义编译选项
DEFINES += QT_DEPRECATED_WARNINGS

#生成程序名
TARGET = paddleOCRDemo

#指定生成的exe输出目录
DESTDIR = $$OUT_PWD

#设置字符
contains( CONFIG,"msvc" ):QMAKE_CXXFLAGS += /source-charset:utf-8 /execution-charset:utf-8
contains( CONFIG,"msvc" ):QMAKE_CFLAGS +=/source-charset:utf-8 /execution-charset:utf-8

#/MT:这个选项表示使用多线程静态链接库(Multithreaded)运行时库
CONFIG(debug, debug|release) {
    QMAKE_CXXFLAGS_DEBUG += /MTd
}
CONFIG(release, debug|release) {
    QMAKE_CXXFLAGS_RELEASE += /MT
}

#编译前执行复制操作
QMAKE_PRE_LINK += $(COPY_DIR) $$shell_path($$PWD/inference) $$shell_path($$OUT_PWD/inference) \
    && $(COPY) $$shell_path($$PWD/config.txt) $$shell_path($$OUT_PWD/config.txt) \
    && $(COPY) $$shell_path($$PWD/ppocr_keys_v1.txt) $$shell_path($$OUT_PWD/ppocr_keys_v1.txt)

#引入对应外部库的头文件及库文件
#OpenCV
INCLUDEPATH += $$PWD/SDK/OpenCV/Includes
DEPENDPATH += $$PWD/SDK/OpenCV/Includes
LIBS += -L$$PWD/SDK/OpenCV/Lib/ -lopencv_world452

#PaddleOCR
INCLUDEPATH += $$PWD/SDK/PaddleOCR/paddle/include
DEPENDPATH += $$PWD/SDK/PaddleOCR/paddle/include
LIBS += -L$$PWD/SDK/PaddleOCR/paddle/lib/ -lpaddle_inference

#PADDLE_PATH
PADDLE_PATH = $$PWD/SDK/PaddleOCR/third_party/install
INCLUDEPATH += $$PADDLE_PATH/cryptopp/include
INCLUDEPATH += $$PADDLE_PATH/gflags/include
INCLUDEPATH += $$PADDLE_PATH/glog/include
INCLUDEPATH += $$PADDLE_PATH/mkldnn/include
INCLUDEPATH += $$PADDLE_PATH/mklml/include
INCLUDEPATH += $$PADDLE_PATH/onnxruntime/include
INCLUDEPATH += $$PADDLE_PATH/paddle2onnx/include
INCLUDEPATH += $$PADDLE_PATH/protobuf/include
INCLUDEPATH += $$PADDLE_PATH/utf8proc/include
INCLUDEPATH += $$PADDLE_PATH/xxhash/include
LIBS += -L$$PADDLE_PATH/glog/lib -lglog
LIBS += -L$$PADDLE_PATH/mkldnn/lib -lmkldnn
LIBS += -L$$PADDLE_PATH/mklml/lib -lmklml -llibiomp5md
LIBS += -L$$PADDLE_PATH/onnxruntime/lib -lonnxruntime
LIBS += -L$$PADDLE_PATH/paddle2onnx/lib -lpaddle2onnx
LIBS += -L$$PADDLE_PATH/protobuf/lib -llibprotobuf
LIBS += -L$$PADDLE_PATH/xxhash/lib -lxxhash

SOURCES += \
        main.cpp \
        mainwindow.cpp \
        paddle/clipper.cpp \
        paddle/config.cpp \
        paddle/ocr_cls.cpp \
        paddle/ocr_det.cpp \
        paddle/ocr_rec.cpp \
        paddle/postprocess_op.cpp \
        paddle/preprocess_op.cpp \
        paddle/utility.cpp \

HEADERS += \
        mainwindow.h \
        paddle/clipper.h \
        paddle/config.h \
        paddle/ocr_cls.h \
        paddle/ocr_det.h \
        paddle/ocr_rec.h \
        paddle/postprocess_op.h \
        paddle/preprocess_op.h \
        paddle/utility.h \

FORMS += \
        mainwindow.ui

四、打印乱码问题

在运行示例时,发现控制台输出的文本为乱码,对此进行了修改,在h文件中添加相应的头文件,使用qDebug()代替原来的cout进行打印:

...
#include <QString>
#include <QDebug>
...
std::string tmp;
for (int i = 0; i < str_res.size(); i++) 
{
    //std::cout << str_res[i];
    tmp.append(str_res[i]);
}
result.push_back(tmp);
//std::cout << "\tscore: " << score << std::endl;
qDebug()<<QString::fromStdString(tmp)<<" 得分:"<<score;
...

请添加图片描述

五、我的示例代码

我重新修改了主界面的布局,相应的代码如下:
1.mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileDialog>
#include <QMessageBox>
#include <QDebug>

#include <string>
#include <vector>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

#include "paddle/config.h"
#include "paddle/ocr_det.h"
#include "paddle/ocr_rec.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void initWidget();

    QPixmap cvMatToPixmap(const cv::Mat imageMat);

private slots:
    void on_pb_selectImage_clicked();
    void on_pb_getText_clicked();

private:
    Ui::MainWindow *ui;

    cv::Mat m_showMat;   //界面显示图像
    PaddleOCR::DBDetector *m_det;       //文本检测模块
    PaddleOCR::CRNNRecognizer *m_rec;   //文本识别模块

};
#endif // MAINWINDOW_H

2.mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->initWidget();
}

MainWindow::~MainWindow()
{
    delete ui;
    delete m_det;
    delete m_rec;
}

//初始化界面
void MainWindow::initWidget()
{
    m_showMat = cv::Mat();
    this->setFixedSize(650,520);
    ui->cb_showRect->setChecked(false);

    //初始化PaddleOCR
    PaddleOCR::OCRConfig config("./config.txt");

    //文本检测对象
    m_det = new PaddleOCR::DBDetector(config.det_model_dir, config.use_gpu, config.gpu_id,
                                      config.gpu_mem, config.cpu_math_library_num_threads,
                                      config.use_mkldnn, config.max_side_len, config.det_db_thresh,
                                      config.det_db_box_thresh, config.det_db_unclip_ratio,
                                      config.visualize, config.use_tensorrt, config.use_fp16);

    //文本识别对象
    m_rec = new PaddleOCR::CRNNRecognizer(config.rec_model_dir, config.use_gpu, config.gpu_id,
                                          config.gpu_mem, config.cpu_math_library_num_threads,
                                          config.use_mkldnn, config.char_list_file,
                                          config.use_tensorrt, config.use_fp16);

}

//cv::Mat转QPixmap
QPixmap MainWindow::cvMatToPixmap(const cv::Mat imageMat)
{
    QImage showImage;
    if(imageMat.channels() > 1)
    {
        showImage = QImage((const uchar*)(imageMat.data),imageMat.cols,imageMat.rows,imageMat.step,QImage::Format_RGB888).rgbSwapped();   //彩色图
    }
    else
    {
        cv::Mat rgbMat;
        cv::cvtColor(imageMat,rgbMat,cv::COLOR_GRAY2BGR);
        showImage = QImage((const uchar*)(rgbMat.data),rgbMat.cols,rgbMat.rows,rgbMat.step,QImage::Format_RGB888).rgbSwapped();   //灰度图
    }
    return QPixmap::fromImage(showImage.scaled(ui->lb_show->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation));
}

//选择图像
void MainWindow::on_pb_selectImage_clicked()
{
    QString imageName = QFileDialog::getOpenFileName(this,"选择图像","E:/photo/OCRTest/","Image File(*.png *.jpg *.bmp)");
    if(!imageName.isEmpty())
    {
        m_showMat = cv::imread(imageName.toLocal8Bit().toStdString(),1);
        QPixmap showPixmap = cvMatToPixmap(m_showMat.clone());
        if(!showPixmap.isNull())
        {
            ui->tb_text->clear();
            ui->lb_show->setPixmap(showPixmap);
        }
    }
}

//识别文本
void MainWindow::on_pb_getText_clicked()
{
    if(m_showMat.empty())
    {
        QMessageBox::information(this,"提示","请先选择图像!");
        return;
    }
    ui->tb_text->clear();

    //返回检测框
    cv::Mat srcMat = m_showMat.clone();
    std::vector<std::vector<std::vector<int>>> boxes;
    cv::Mat dstMat = m_det->Run(srcMat,boxes);
    if(ui->cb_showRect->isChecked())
    {
        ui->lb_show->setPixmap(cvMatToPixmap(dstMat));
    }
    else
    {
        ui->lb_show->setPixmap(cvMatToPixmap(srcMat));
    }

    //获取文本
    std::vector<std::string> res = m_rec->Run(boxes,srcMat,nullptr);
    for(auto s:res)
    {
        ui->tb_text->append(s.data());
    }
}

3.mainwindow.ui
请添加图片描述

六、下载链接

OCR依赖项百度网盘链接:https://pan.baidu.com/s/1mgmFrCHR4JJ7ZxyYrhRkrA?pwd=xxcj
提取码:xxcj
注意:需要将官网下载的预测库解压到/SDK/PaddleOCR内,这里占内存空间太大,就没放在网盘内。


总结

在我的示例中Qt集成OpenCV使用PaddleOCR进行文本识别,可以看到识别效果也是不错的,这里十分感谢大佬的开源奉献。下面这些关于OCR文本识别的文章,其内容也很详细,大家可以学习一下。


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

参考文章:
QT使用PaddleOCR和百度OCR进行文字识别
使用qt+PaddleOCR做一个OCR软件demo
C++ | PaddleOCR+OpenCV实现文字识别步骤与代码演示

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值