效果如下所示:
首先说明我使用的环境和配置如下:
QT5.15.2+opencv4.5.2+VS2019+paddleocr2.6(截止到目前的最新版)+cpu部署
按照很多博主写过的那样进行部署编译:
先下载以下文件:
我是选择中英文超轻量PP-OCRV3的推理模型,三个都下载
paddleocr_inference
下载dirent-master
用来补充paddle-ocr2.6的头文件,进行编译参考博客链接:https://blog.youkuaiyun.com/Helloorl-C++文档类资源-优快云文库
然后就可以开始进行自己的编译了,将下载的文件放到如下所示的文件夹中:
我这里是将paddle_inference放到paddle_1中解压了。
下一步,打开cmake进行编译,如果没有安装的话,这里有参考地址:
CMake的安装(超级详细)_cmake安装_小码1111的博客-优快云博客
打开cmake
第一次点击configure,选择VS2019,x64
第二次点击configure,配置lib地址
第三次点击,如果配置完成即configure done,再点击generate
生成完成后,在之前创建的build下,打开ppocr.sln(官方建议release)
然后添加ppocr的项目包含头文件
这里注意还要添加dirent头文件,不然会报错,网上有相关链接!
先点击生成all_build,然后开始调试F5
会报错,但是不用管它
打开build文件
点击进去release(新的)
保证有红色框里面的dll文件,如果缺,可以搜索,复制粘贴过来。
接下来,在build文件夹下,cmd
首先输入CHCP 65001
Active code page: 65001
然后输入:
.\build\Release\ppocr.exe system --det_model_dir=.\build\Release\ch_PP-OCRv3_det_infer --rec_model_dir=.\build\Release\ch_PP-OCRv3_rec_infer --image_dir=.\build\Release\imgs\11.jpg --rec_char_dict_path=.\build\Release\ppocr_keys_v1.txt
就会看到能否预测。
预测成功后,开始部署到QT上
部署到QT上,首先新建一个QT程序。
因为编译的问题,需要添加:
pro文件如下:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
CONFIG(debug, debug|release) {
QMAKE_CXXFLAGS_DEBUG += /MTd
}
CONFIG(release, debug|release) {
QMAKE_CXXFLAGS_RELEASE += /MT
}
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp \
paddle_ocr_src/args.cpp \
paddle_ocr_src/clipper.cpp \
paddle_ocr_src/ocr_cls.cpp \
paddle_ocr_src/ocr_det.cpp \
paddle_ocr_src/ocr_rec.cpp \
paddle_ocr_src/paddleocr.cpp \
paddle_ocr_src/paddlestructure.cpp \
paddle_ocr_src/postprocess_op.cpp \
paddle_ocr_src/preprocess_op.cpp \
paddle_ocr_src/structure_table.cpp \
paddle_ocr_src/utility.cpp
HEADERS += \
mainwindow.h \
paddle_ocr_include/args.h \
paddle_ocr_include/autolog.h \
paddle_ocr_include/clipper.h \
paddle_ocr_include/ocr_cls.h \
paddle_ocr_include/ocr_det.h \
paddle_ocr_include/ocr_rec.h \
paddle_ocr_include/paddle_api.h \
paddle_ocr_include/paddleocr.h \
paddle_ocr_include/paddlestructure.h \
paddle_ocr_include/postprocess_op.h \
paddle_ocr_include/preprocess_op.h \
paddle_ocr_include/structure_table.h \
paddle_ocr_include/utility.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
#include everthing .h document;PWD stand for(current of pro's path)
INCLUDEPATH += $$PWD\..\3part\paddle_inference_install_dir\drient\include
INCLUDEPATH += $$PWD\..\3part\paddle_inference_install_dir\paddle\fluid\inference
INCLUDEPATH += $$PWD\..\3part\paddle_inference_install_dir\paddle\include
INCLUDEPATH += $$PWD\..\3part\\paddle_inference_install_dir\third_party\install\protobuf\include
INCLUDEPATH += $$PWD\..\3part\\paddle_inference_install_dir\third_party\install\glog\include
INCLUDEPATH += $$PWD\..\3part\\paddle_inference_install_dir\third_party\install\gflags\include
INCLUDEPATH += $$PWD\..\3part\\paddle_inference_install_dir\third_party\install\xxhash\include
INCLUDEPATH += $$PWD\..\3part\paddle_inference_install_dir\third_party\install\zlib\include
INCLUDEPATH += $$PWD\..\3part\paddle_inference_install_dir\third_party\install\onnxruntime\include
INCLUDEPATH += $$PWD\..\3part\paddle_inference_install_dir\third_party\install\paddle2onnx\include
INCLUDEPATH += $$PWD\..\3part\paddle_inference_install_dir\third_party\install\auto_log\include
INCLUDEPATH += $$PWD\..\3part\paddle_inference_install_dir\third_party\boost
INCLUDEPATH += $$PWD\..\3part\paddle_inference_install_dir\third_party\eigen3
INCLUDEPATH += $$PWD\..\3part\paddle_inference_install_dir\third_party\install\mklml\include
INCLUDEPATH += $$PWD\..\3part\paddle_inference_install_dir\third_party\install\mkldnn\include
#INCLUDEPATH += $$PWD\..\3part\opencv\include
#include everything .lib
LIBS += -L$$PWD\..\3part\paddle_inference_install_dir\paddle\lib -lpaddle_inference
LIBS += -L$$PWD\..\3part\paddle_inference_install_dir\third_party\install\mklml\lib -lmklml
LIBS += -L$$PWD\..\3part\paddle_inference_install_dir\third_party\install\mklml\lib -llibiomp5md
LIBS += -L$$PWD\..\3part\paddle_inference_install_dir\third_party\install\mkldnn\lib -lmkldnn
LIBS += -L$$PWD\..\3part\paddle_inference_install_dir\third_party\install\glog\lib -lglog
LIBS += -L$$PWD\..\3part\paddle_inference_install_dir\third_party\install\gflags\lib -lgflags_static
LIBS += -L$$PWD\..\3part\paddle_inference_install_dir\third_party\install\protobuf\lib -llibprotobuf
LIBS += -L$$PWD\..\3part\paddle_inference_install_dir\third_party\install\xxhash\lib -lxxhash
LIBS += -L$$PWD\..\3part\paddle_inference_install_dir\third_party\install\onnxruntime\lib -lonnxruntime
LIBS += -L$$PWD\..\3part\paddle_inference_install_dir\third_party\install\paddle2onnx\lib -lpaddle2onnx
#LIBS += -L$$PWD\..\3part\opencv -lopencv_world452
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "opencv2/core.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <vector>
#include <paddle_ocr_include/args.h>
#include <paddle_ocr_include/paddleocr.h>
#include <paddle_ocr_include/paddlestructure.h>
using namespace PaddleOCR;
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void check_params();
void ocr(std::vector<cv::String> &cv_all_img_names);
void structure(std::vector<cv::String> &cv_all_img_names);
private:
Ui::MainWindow *ui;
PaddleStructure *engine;
PPOCR *ocr_result;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
int argc;
char **argv;
qDebug()<<"1";
FLAGS_det_model_dir="../3part/model/ch_PP-OCRv3_det_infer";
FLAGS_image_dir="F:/Paddle_OCR/paddle2.6/PaddleOCR-2.6.0/deploy/cpp_infer/build/Release/imgs/";
FLAGS_rec_model_dir="../3part/model/ch_PP-OCRv3_rec_infer";
FLAGS_rec_char_dict_path="../3part/ppocr_keys_v1.txt";
check_params();
if (!Utility::PathExists(FLAGS_image_dir)) {
std::cerr << "[ERROR] image path not exist! image_dir: " << FLAGS_image_dir
<< endl;
exit(1);
}
std::vector<cv::String> cv_all_img_names{"F:/Paddle_OCR/paddle2.6/PaddleOCR-2.6.0/deploy/cpp_infer/build/Release/imgs/20.jpg"};//为了识别单张图片而弄的。
std::cout << "total images num: " << cv_all_img_names[0] << endl;
std::cout <<FLAGS_type<<endl;
ocr(cv_all_img_names);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::check_params()
{
if (FLAGS_det) {
if (FLAGS_det_model_dir.empty() || FLAGS_image_dir.empty()) {
std::cout << "Usage[det]: ./ppocr "
"--det_model_dir=/PATH/TO/DET_INFERENCE_MODEL/ "
<< "--image_dir=/PATH/TO/INPUT/IMAGE/" << std::endl;
exit(1);
}
}
if (FLAGS_rec) {
std::cout
<< "In PP-OCRv3, rec_image_shape parameter defaults to '3, 48, 320',"
"if you are using recognition model with PP-OCRv2 or an older "
"version, "
"please set --rec_image_shape='3,32,320"
<< std::endl;
if (FLAGS_rec_model_dir.empty() || FLAGS_image_dir.empty()) {
std::cout << "Usage[rec]: ./ppocr "
"--rec_model_dir=/PATH/TO/REC_INFERENCE_MODEL/ "
<< "--image_dir=/PATH/TO/INPUT/IMAGE/" << std::endl;
exit(1);
}
}
if (FLAGS_cls && FLAGS_use_angle_cls) {
if (FLAGS_cls_model_dir.empty() || FLAGS_image_dir.empty()) {
std::cout << "Usage[cls]: ./ppocr "
<< "--cls_model_dir=/PATH/TO/REC_INFERENCE_MODEL/ "
<< "--image_dir=/PATH/TO/INPUT/IMAGE/" << std::endl;
exit(1);
}
}
if (FLAGS_table) {
if (FLAGS_table_model_dir.empty() || FLAGS_det_model_dir.empty() ||
FLAGS_rec_model_dir.empty() || FLAGS_image_dir.empty()) {
std::cout << "Usage[table]: ./ppocr "
<< "--det_model_dir=/PATH/TO/DET_INFERENCE_MODEL/ "
<< "--rec_model_dir=/PATH/TO/REC_INFERENCE_MODEL/ "
<< "--table_model_dir=/PATH/TO/TABLE_INFERENCE_MODEL/ "
<< "--image_dir=/PATH/TO/INPUT/IMAGE/" << std::endl;
exit(1);
}
}
if (FLAGS_precision != "fp32" && FLAGS_precision != "fp16" &&
FLAGS_precision != "int8") {
cout << "precison should be 'fp32'(default), 'fp16' or 'int8'. " << endl;
exit(1);
}
}
void MainWindow::ocr(std::vector<cv::String> &cv_all_img_names)
{
PPOCR ocr=PPOCR();
qDebug()<<"here";
std::vector<std::vector<OCRPredictResult>> ocr_results = ocr.ocr(cv_all_img_names, FLAGS_det, FLAGS_rec, FLAGS_cls);
for (int i = 0; i < cv_all_img_names.size(); ++i) {
if (FLAGS_benchmark) {
cout << cv_all_img_names[i] << '\t';
if (FLAGS_rec && FLAGS_det) {
Utility::print_result(ocr_results[i]);
} else if (FLAGS_det) {
for (int n = 0; n < ocr_results[i].size(); n++) {
for (int m = 0; m < ocr_results[i][n].box.size(); m++) {
cout << ocr_results[i][n].box[m][0] << ' '
<< ocr_results[i][n].box[m][1] << ' ';
}
}
cout << endl;
} else {
Utility::print_result(ocr_results[i]);
}
} else {
cout << cv_all_img_names[i] << "\n";
Utility::print_result(ocr_results[i]);
if (FLAGS_visualize && FLAGS_det) {
cv::Mat srcimg = cv::imread(cv_all_img_names[i], cv::IMREAD_COLOR);
if (!srcimg.data) {
std::cerr << "[ERROR] image read failed! image path: "
<< cv_all_img_names[i] << endl;
exit(1);
}
std::string file_name = Utility::basename(cv_all_img_names[i]);
Utility::VisualizeBboxes(srcimg, ocr_results[i],
FLAGS_output + "/" + file_name);
}
cout << "***************************" << endl;
}
}
}
void MainWindow::structure(std::vector<cv::String> &cv_all_img_names)
{
PaddleOCR::PaddleStructure engine = PaddleOCR::PaddleStructure();
std::vector<std::vector<StructurePredictResult>> structure_results =
engine.structure(cv_all_img_names, false, FLAGS_table);
for (int i = 0; i < cv_all_img_names.size(); i++) {
cout << "predict img: " << cv_all_img_names[i] << endl;
for (int j = 0; j < structure_results[i].size(); j++) {
std::cout << j << "\ttype: " << structure_results[i][j].type
<< ", region: [";
std::cout << structure_results[i][j].box[0] << ","
<< structure_results[i][j].box[1] << ","
<< structure_results[i][j].box[2] << ","
<< structure_results[i][j].box[3] << "], res: ";
if (structure_results[i][j].type == "table") {
std::cout << structure_results[i][j].html << std::endl;
} else {
Utility::print_result(structure_results[i][j].text_res);
}
}
}
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
QT里面对于log文件有不兼容问题,因此我采取了注释掉打印部分功能,来避免
详情可以参考我上传的资料:
链接如下:paddle-ocr-2-6.rar-C++文档类资源-优快云文库
新的研究进展,利用paddleocr去识别多语种字符,对此进行部署。