PaddleOCR移植到RK3568
前言
这次的主要需求是在RK3568 进行OCR识别,识别一串数字,有已经尝试了传统图像处理的算法,但是无奈,限制还是太多了。我觉得适用性并不高,最终还是考虑得上OCR识别算法,这样就能极大的扩展整个识别领域。
也在网上搜索了一段时间,最终选中PaddleOCR,我也在windows 上尝试了一下,整个效果还可以,并且,应该可以移植到RK356X上面,这就比较有可行性了。
前置操作:
1、pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple/
2、注意,我这边编译的是FastDeploy的C++ 版本,如果要编译python版本的,就在/FastDeploy/python下面,但具体的编译流程会有略微差异。
3、可以参考这个嵌入式AI应用开发实战指南这个网站对这些写的很详细,但也有一些没更新的地方,我这边也同步会标记一下。
主要流程:
1、在Ubuntu PC上将模型进行转化。
1、使用Paddle2ONNX 将普通模型转onnx
2、使用RKTOOL_KIT2 将onnx转rknn模型
2、在RK3568上编译FastDeploy ,这是一个便于模型部署的工具库,里面包括了很多东西。
3、将编译出来的fastdeploy对应的库以及三方库,再拷贝出来,拷贝到指定的地方,运行fastdeplot-init.sh 进行环境变量的配置,然后就可以运行infer.cpp的推理demo了。
正文
一、基础介绍
1、RKNPU2
RKNPU2指的是Rockchip推出的RK356X以及RK3588系列芯片的NPU.目前FastDeploy已经初步支持使用RKNPU2来部署模型。
RKNPU2
2、FastDeploy
Paddle 的 FastDeploy 是百度开源的一个 推理部署工具箱,它的主要目的是让深度学习模型在多种硬件和平台上高效、快速地部署和运行。它是一个 模型部署工具库,支持从训练到部署的一站式流程,尤其适合使用 PaddlePaddle 或 ONNX 格式的模型进行跨平台部署。
make install 之后会有一系列头文件和库供调用,就可以用来进行OCR识别了。
3、librknn_api.so
librknn_api.so
是瑞芯微(Rockchip)提供的一个动态链接库(Shared Object),用于在其嵌入式平台(如 RK3588、RK3568、RK3399Pro 等)上部署和运行经过 RKNN Toolkit 转换的神经网络模型。
官方对应的运行时库
4、RKNN-Toolkit2
RKNN-Toolkit2 是瑞芯微(Rockchip)推出的一款用于其 NPU(神经网络处理单元)平台的深度学习模型开发工具套件。它主要运行于 PC(x86 或 ARM64 架构)上,提供模型转换、量化、推理、性能评估、内存分析和模型加密等功能,旨在帮助开发者高效地将主流深度学习模型部署到瑞芯微的 NPU 硬件上。
RKNN-Toolkit2 支持将以下主流深度学习框架的模型转换为 RKNN 格式,以便在瑞芯微的 NPU 上运行
- Caffe
- TensorFlow
- TensorFlow Lite
- ONNX
- DarkNet
- PyTorc
RKNN-Toolkit2是一套软件开发套件,供用户在PC和Rockchip NPU平台上进行模型转换、推理和性能评估。
RKNN-Toolkit-Lite2为Rockchip NPU平台提供Python编程接口,帮助用户部署RKNN模型,加速AI应用的落地。
RKNN Runtime 为 Rockchip NPU 平台提供 C/C++ 编程接口,帮助用户部署 RKNN 模型,加速 AI 应用的落地。
RKNPU内核驱动负责和NPU硬件交互,已经开源,可以在Rockchip内核代码中找到。
操作:RKNN-Toolkit2 操作
二、详细操作
1、在Ubuntu20.04中完成模型的转换
有需要加速的可以先行配置这个:
sudo pip config --global set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
a、安装Anaconda
1、可以直接下载
b、安装Ubuntu依赖库
sudo apt-get install libxslt1-dev zlib1g zlib1g-dev libglib2.0-0 libsm6 libgl1-mesa-glx libprotobuf-dev gcc g++
c、安装paddle2onnx
pip install paddle2onnx -i https://pypi.tuna.tsinghua.edu.cn/simple
-i https://pypi.tuna.tsinghua.edu.cn/simple
就是使用清华源进行加速了
d、安装最新的rknn-toolkit2工具
这个库的作用:将获得的onnx的模型转成rknn的模型
1、注意,一定要安装最新的,之前旧的会跟paddle2onnx那个库不匹配
2、去这里下载:
[GitHub - airockchip/rknn-toolkit2](https://github.com/airockchip/rknn-toolkit2)
不是网上搜索出来的第一个,那个会跟paddle2onnx 不匹配
不是这个噢[GitHub - rockchip-linux/rknn-toolkit2](https://github.com/rockchip-linux/rknn-toolkit2?tab=readme-ov-file)
请注意。
安装可以参考这个:野火嵌入式AI应用开发实战指南—基于LubanCat-RK系列板卡 文档
e、进行模型转换
1、下载模型
1、下载对应的模型,注意,这里都是在Ubuntu上进行操作
#新建一个文件夹
mkdir ppocr
cd ppocr
# 下载PP-OCRv3文字检测模型
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar
tar -xvf ch_PP-OCRv3_det_infer.tar
# 下载文字方向分类器模型
wget https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar
tar -xvf ch_ppocr_mobile_v2.0_cls_infer.tar
# 下载PP-OCRv3文字识别模型
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar
tar -xvf ch_PP-OCRv3_rec_infer.tar
第一个det模型在图片中检测文字的存在
第二个cls模型确定文字的方向
第三个rec模型识别文字的内容
注意,我们这里下载的都是v3的模型,可别下载成v4的了。
wget用不了的话,就直接下载拷贝进去也可以。
2、模型转onnx
paddle2onnx --model_dir ch_PP-OCRv3_det_infer \--model_filename inference.pdmodel \--params_filename inference.pdiparams \--save_file ch_PP-OCRv3_det_infer/ch_PP-OCRv3_det_infer.onnx paddle2onnx --model_dir ch_ppocr_mobile_v2.0_cls_infer \--model_filename inference.pdmodel \--params_filename inference.pdiparams \--save_file ch_ppocr_mobile_v2.0_cls_infer/ch_ppocr_mobile_v2.0_cls_infer.onnxpaddle2onnx --model_dir ch_PP-OCRv3_rec_infer \--model_filename inference.pdmodel \--params_filename inference.pdiparams \--save_file ch_PP-OCRv3_rec_infer/ch_PP-OCRv3_rec_infer.onnx
注意,这里的命令跟网上查到的略微不同,网上的已经old的了。不太适用了。但大差不差就是。
3、固定onnx模型的形状
这里需要注意的是,根据ubuntu系统上python版本的不同,python指令可能会替换为python3
我这里适用的还是python,你如果自己电脑上有2.0 和3.0的python可要注意
python -m paddle2onnx.optimize --input_model ch_PP-OCRv3_det_infer/ch_PP-OCRv3_det_infer.onnx \--output_model ch_PP-OCRv3_det_infer/ch_PP-OCRv3_det_infer.onnx \--input_shape_dict "{'x':[1,3,960,960]}"python -m paddle2onnx.optimize --input_model ch_ppocr_mobile_v2.0_cls_infer/ch_ppocr_mobile_v2.0_cls_infer.onnx \--output_model ch_ppocr_mobile_v2.0_cls_infer/ch_ppocr_mobile_v2.0_cls_infer.onnx \--input_shape_dict "{'x':[1,3,48,192]}"python -m paddle2onnx.optimize --input_model ch_PP-OCRv3_rec_infer/ch_PP-OCRv3_rec_infer.onnx \--output_model ch_PP-OCRv3_rec_infer/ch_PP-OCRv3_rec_infer.onnx \--input_shape_dict "{'x':[1,3,48,320]}"
到这就固定好onnx模型的形状了,如果你只想用cpu进行推理,其实这个到这里就可以了,不用后续的rnnk的转换步骤。
4、将onnx 转成rknn
1、在PC端也下载一下FastDeploy:https://github.com/PaddlePaddle/FastDeploy
2、将目录下的rknpu2_tools拷贝到~/PaddleOCR下面
3、接下来修改一下rknpu2_tools下面的config,后面适用里面的export.py进行输出
ppocrv3_rec.yaml
修改
mean:-- 127.5- 127.5- 127.5
std:-- 127.5- 127.5- 127.5
model_path: ./model/ch_PP-OCRv3_rec_infer/ch_PP-OCRv3_rec_infer.onnx
outputs_nodes:
do_quantization: False
dataset:
output_folder: "./model/ch_PP-OCRv3_rec_infer"
ppocrv3_det.yaml
修改
mean:-- 123.675- 116.28- 103.53
std:-- 58.395- 57.12- 57.375
model_path: ./model/ch_PP-OCRv3_det_infer/ch_PP-OCRv3_det_infer.onnx
outputs_nodes:
do_quantization: False
dataset:
output_folder: "./model/ch_PP-OCRv3_det_infer"
ppocrv3_cls.yaml
修改
mean:-- 127.5- 127.5- 127.5
std:-- 127.5- 127.5- 127.5
model_path: ./model/ch_ppocr_mobile_v2.0_cls_infer/ch_ppocr_mobile_v2.0_cls_infer.onnx
outputs_nodes:
do_quantization: False
dataset:
output_folder: "./model/ch_ppocr_mobile_v2.0_cls_infer"
主要就是看你模型怎么放,我模型是放在这里面
4、放好后,就可以开始转换了。
cd ~/PaddleOCR
python rknpu2_tools/export.py --config_path rknpu2_tools/config/ppocrv3_det.yaml --target_platform rk3568
python rknpu2_tools/export.py --config_path rknpu2_tools/config/ppocrv3_rec.yaml --target_platform rk3568
python rknpu2_tools/export.py --config_path rknpu2_tools/config/ppocrv3_cls.yaml --target_platform rk3568
分别执行这些语句
#当三条指令结束运行时,终端内容应该都是
D RKNN: [03:17:31.652] ----------------------------------------
D RKNN: [03:17:31.652] <<<<<<<< end: N4rknn21RKNNMemStatisticsPassE
I rknn buiding done.
W init_runtime: Target is None, use simulator!
Export OK!
#如果提示错误,说明你的rknn_toolkit2版本过时了,这时候要卸载旧的rknn_toolkit2,重新安装rknn_toolkit2
#这时候在每个模型的解压文件夹下就得到了rknn模型。
~/PaddleOCR/ch_ppocr_mobile_v2.0_cls_infer/ch_ppocr_mobile_v20_cls_infer_rk3568_unquantized.rknn
~/PaddleOCR/ch_PP-OCRv4_det_infer/ch_PP-OCRv3_det_infer_rk3568_unquantized.rknn
~/PaddleOCR/ch_PP-OCRv4_rec_infer/ch_PP-OCRv3_rec_infer_rk3568_unquantized.rknn
这个时候,你在Ubuntu20.04上的操作就结束了,你的目的已经达到,既搞了onnx 又得到rknn
2、在RK3568上编译FastDeploy
可以参考这个:飞桨(PaddlePaddle) FastDeploy
1、将你之前下载的FastDeploy 拷贝到任意一个目录,建议自己新建一个目录,我这边放在/ics下面
2、首先,你要先确定你的内存有多大,如果小于4g,我估计你得做一下swap交换分区,不然,估计悬,可能会出现各种各样的问题
怎么做可以参考这个,也挺简单的:Linux增大Swap分区,增加虚拟内存,以解决内存不足等问题
目前我这边弄完,可以说有6g左右,那就比较可以了。
3、接下来,重点来了,你如果直接开始cmake ,应该会报错:编译FastDeploy error: ‘string_view’ is not a member of ‘std’ os_string to_osstring(std::string_view utf8_str)
出现这个问题,这个问题的原因在目前我们下载下来的FastDeploy 里面代码用到了C++17的东西,但是CMakeLists.txt还是使用C++11,然后就报错了。这个时候需要修改一些CMakeLists.txt,再继续。(当然你可以先继续往下试一下,因为网上没有任何一篇文章讲到这个,也可能是我流程错误)
我这边做的修改是:
**在文件开头设置 C++17 标准**在 cmake_minimum_required(VERSION 3.10) 之后,添加以下代码:```
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
```这确保项目使用 C++17,并要求编译器支持此标准。**更新 GCC 版本检查**在文件末尾,找到 GCC 版本检查部分,将 "5.4.0" 改为 "7.0.0",并更新错误提示:
```
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "7.0.0")
message(FATAL_ERROR "FastDeploy requires GCC version >= 7.0.0 for C++17 support, but your version is ${CMAKE_CXX_COMPILER_VERSION}. Please upgrade your compiler or use -DCMAKE_CXX_COMPILER to specify a newer compiler.")
endif()
endif()
```这确保 GCC 版本至少为 7.0,支持 C++17。**清理非必要的 C++11 设置(可选)**在 if(NOT MSVC) 代码块中,可以移除或注释掉设置 C++11 的部分:```
if(NOT MSVC)
# 移除或注释掉以下部分
# if(NOT DEFINED CMAKE_CXX_STANDARD)
# set(CMAKE_CXX_STANDARD 11)
# endif()
set(CMAKE_CXX_FLAGS "-Wno-format -g0 -O3")
if(NEED_ABI0)
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
else()
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1) endif() endif(NOT MSVC)
```由于我们已在文件开头全局设置了 C++17,这一步可以使代码更清晰,但不是必须的。
几个部分贴下图:
这样弄完后,再继续下一步。
4、步骤是这样:
# 切换到源码目录下
cd FastDeploy# 创建一个编译目录,并切换到该目录下,执行cmake配置
mkdir build && cd buildcmake .. -DENABLE_ORT_BACKEND=ON \-DENABLE_RKNPU2_BACKEND=ON \-DENABLE_VISION=ON \-DRKNN2_TARGET_SOC=RK356X \-DCMAKE_INSTALL_PREFIX=${PWD}/fastdeploy-0.0.0# ENABLE_ORT_BACKEND 是指定是否编译集成ONNX Runtime后端
# ENABLE_RKNPU2_BACKEND 是指定否编译集成RKNPU2后端
# ENABLE_VISION 指定是否编译集成视觉模型的部署模块
# RKNN2_TARGET_SOC 指定目标设备,输入值为RK3588,RK356X,必须设置
# CMAKE_INSTALL_PREFIX 安装目录
# ORT_DIRECTORY 开启ONNX Runtime后端时,用于指定用户本地的ONNX Runtime库路径;如果不指定,编译过程会自动下载ONNX Runtime库(教程测试下载的版本是1.12.0)
# OPENCV_DIRECTORY 当ENABLE_VISION=ON时,用于指定用户本地的OpenCV库路径;如果不指定,编译过程会自动下载OpenCV库(教程测试下载的版本是3.4.14)# 编译,安装,如果是RK356X,指定-j4;如果是RK3588,指定-j8
make -j4make install# 最后安装在XXX/FastDeploy/build/fastdeploy-0.0.0目录下
cat@lubancat:~/FastDeploy-develop/build/fastdeploy-0.0.0$ ls
FastDeploy.cmake FastDeployConfig.cmake ThirdPartyNotices.txt fastdeploy_init.sh lib summary.cmake utils
FastDeployCSharp.cmake LICENSE VERSION_NUMBER include openmp.cmake third_libs utils.cmake
5、然后,我们该设置一下环境变量,否则我们待会要推理的example没办法找到这些库
# 临时配置
source ~/PaddleOCR/FastDeploy/build/fastdeploy-0.0.0/fastdeploy_init.sh# 永久配置
source ~/PaddleOCR/FastDeploy/build/fastdeploy-0.0.0/fastdeploy_init.sh
sudo cp ~/PaddleOCR/FastDeploy/build/fastdeploy-0.0.0/fastdeploy_libs.conf /etc/ld.so.conf.d/
sudo ldconfig
按照你的目录,进行对应修改喔。
3、在RK3568上使用模型进行推理
1、首先进入板子上刚刚编译完毕的FastDeploy文件夹下的/FastDeploy/examples/vision/ocr/PP-OCR/rockchip/cpp,创建一个新的文件夹build,回到cpp文件夹下,打开CMakeLists.txt,对include部分进行修改。
PROJECT(infer_demo C CXX)
CMAKE_MINIMUM_REQUIRED (VERSION 3.10)# 指定下载解压后的fastdeploy库路径
option(FASTDEPLOY_INSTALL_DIR "~/PaddleOCR/FastDeploy/build/fastdeploy-0.0.0")# 需要修改的地方!!!
# 需要手动在FastDeploy的build,也就是你进行编译FastDeploy时的那个文件夹下面找到FastDeploy.cmake这个文件!
include(~/PaddleOCR/FastDeploy/build/fastdeploy-0.0.0/FastDeploy.cmake)# 添加FastDeploy依赖头文件
include_directories(${FASTDEPLOY_INCS})add_executable(infer_demo ${PROJECT_SOURCE_DIR}/infer.cc)
# 添加FastDeploy库依赖
target_link_libraries(infer_demo ${FASTDEPLOY_LIBS})
2、cd到刚刚创建的FastDeploy/examples/vision/ocr/PP-OCR/rockchip/cpp/build文件夹下,进行如下操作:
cd ~/PaddleOCR/FastDeploy/examples/vision/ocr/PP-OCR/rockchip/cpp/build
# 使用编译完成的FastDeploy库编译infer_demo
cmake .. -DFASTDEPLOY_INSTALL_DIR=${PWD}/fastdeploy-rockchip
make -j
3、注意,此处编译完会生成一个叫infer_demo的程序,这个就是我们的ocr程序了,将刚刚在PC端编译的模型拷贝到当前文件夹。下载测试图片和字典文件
# 下载图片和字典文件
wget https://gitee.com/paddlepaddle/PaddleOCR/raw/release/2.6/doc/imgs/12.jpg
wget https://gitee.com/paddlepaddle/PaddleOCR/raw/release/2.6/ppocr/utils/ppocr_keys_v1.txt
也可以下载了,从PC端拷贝过去。
4、接下来,终于可以推理了:
图片名称自己改下,模型路径确定是对的。
//CPU推理
./infer_demo ./ch_PP-OCRv3_det_infer/ch_PP-OCRv3_det_infer.onnx \./ch_ppocr_mobile_v2.0_cls_infer/ch_ppocr_mobile_v2.0_cls_infer.onnx \./ch_PP-OCRv3_rec_infer/ch_PP-OCRv3_rec_infer.onnx \./ppocr_keys_v1.txt \./test11.png \0//NPU推理
./infer_demo ./ch_PP-OCRv3_det_infer/ch_PP-OCRv3_det_infer_rk3568_unquantized.rknn \./ch_ppocr_mobile_v2.0_cls_infer/ch_ppocr_mobile_v20_cls_infer_rk3568_unquantized.rknn \./ch_PP-OCRv3_rec_infer/ch_PP-OCRv3_rec_infer_rk3568_unquantized.rknn \./ppocr_keys_v1.txt \./test11.png\1
这是CPU推理输出的结果:
[INFO] fastdeploy/runtime/runtime.cc(326)::CreateOrtBackend Runtime initialized with Backend::ORT in Device::CPU.
[INFO] fastdeploy/runtime/runtime.cc(326)::CreateOrtBackend Runtime initialized with Backend::ORT in Device::CPU.
[INFO] fastdeploy/runtime/runtime.cc(326)::CreateOrtBackend Runtime initialized with Backend::ORT in Device::CPU.
det boxes: [[116,809],[252,749],[255,773],[120,833]]rec text: 115196-22-296 rec score:0.947411 cls label: 0 cls score: 1.000000Function execution time: 3015 microseconds.
Visualized result saved in ./vis_result.jpg
这是NPU推理输出的结果:
[INFO] fastdeploy/runtime/backends/rknpu2/rknpu2_backend.cc(81)::GetSDKAndDeviceVersion rknpu2 runtime version: 1.5.1b19 (32afb0e92@2023-07-14T12:46:17)
[INFO] fastdeploy/runtime/backends/rknpu2/rknpu2_backend.cc(82)::GetSDKAndDeviceVersion rknpu2 driver version: 0.9.6
index=0, name=x, n_dims=4, dims=[1, 960, 960, 3], n_elems=2764800, size=5529600, fmt=NHWC, type=FP16, qnt_type=AFFINE, zp=0, scale=1.000000, pass_through=0
index=0, name=fetch_name_0, n_dims=4, dims=[1, 1, 960, 960], n_elems=921600, size=1843200, fmt=NCHW, type=FP32, qnt_type=AFFINE, zp=0, scale=1.000000, pass_through=0
[INFO] fastdeploy/runtime/runtime.cc(367)::CreateRKNPU2Backend Runtime initialized with Backend::RKNPU2 in Device::RKNPU.
[INFO] fastdeploy/runtime/backends/rknpu2/rknpu2_backend.cc(81)::GetSDKAndDeviceVersion rknpu2 runtime version: 1.5.1b19 (32afb0e92@2023-07-14T12:46:17)
[INFO] fastdeploy/runtime/backends/rknpu2/rknpu2_backend.cc(82)::GetSDKAndDeviceVersion rknpu2 driver version: 0.9.6
index=0, name=x, n_dims=4, dims=[1, 48, 192, 3], n_elems=27648, size=55296, fmt=NHWC, type=FP16, qnt_type=AFFINE, zp=0, scale=1.000000, pass_through=0
index=0, name=fetch_name_0, n_dims=2, dims=[1, 2, 0, 0], n_elems=2, size=4, fmt=UNDEFINED, type=FP32, qnt_type=AFFINE, zp=0, scale=1.000000, pass_through=0
[INFO] fastdeploy/runtime/runtime.cc(367)::CreateRKNPU2Backend Runtime initialized with Backend::RKNPU2 in Device::RKNPU.
[INFO] fastdeploy/runtime/backends/rknpu2/rknpu2_backend.cc(81)::GetSDKAndDeviceVersion rknpu2 runtime version: 1.5.1b19 (32afb0e92@2023-07-14T12:46:17)
[INFO] fastdeploy/runtime/backends/rknpu2/rknpu2_backend.cc(82)::GetSDKAndDeviceVersion rknpu2 driver version: 0.9.6
index=0, name=x, n_dims=4, dims=[1, 48, 320, 3], n_elems=46080, size=92160, fmt=NHWC, type=FP16, qnt_type=AFFINE, zp=0, scale=1.000000, pass_through=0
index=0, name=fetch_name_0, n_dims=3, dims=[1, 40, 6625, 0], n_elems=265000, size=530000, fmt=UNDEFINED, type=FP32, qnt_type=AFFINE, zp=0, scale=1.000000, pass_through=0
[INFO] fastdeploy/runtime/runtime.cc(367)::CreateRKNPU2Backend Runtime initialized with Backend::RKNPU2 in Device::RKNPU.
[WARNING] fastdeploy/runtime/backends/rknpu2/rknpu2_backend.cc(420)::InitRKNNTensorMemory The input tensor type != model's inputs type.The input_type need FP16,but inputs[0].type is UINT8
[WARNING] fastdeploy/runtime/backends/rknpu2/rknpu2_backend.cc(420)::InitRKNNTensorMemory The input tensor type != model's inputs type.The input_type need FP16,but inputs[0].type is UINT8
[WARNING] fastdeploy/runtime/backends/rknpu2/rknpu2_backend.cc(420)::InitRKNNTensorMemory The input tensor type != model's inputs type.The input_type need FP16,but inputs[0].type is UINT8
det boxes: [[116,809],[252,749],[255,773],[120,833]]rec text: 115196-22-296 rec score:0.947791 cls label: 0 cls score: 1.000000Function execution time: 565 microseconds.
Visualized result saved in ./vis_result.jpg
4、指定OpenCV的版本对FastDeploy 重新编译
使用的cmake如下:
cmake .. -DENABLE_ORT_BACKEND=ON \-DENABLE_RKNPU2_BACKEND=ON \-DENABLE_VISION=ON \-DRKNN2_TARGET_SOC=RK356X \-DCMAKE_INSTALL_PREFIX=${PWD}/fastdeploy-0.0.0 \-DOPENCV_DIRECTORY=/ics/FastDeploy/opencv/lib/cmake/opencv4
参考这个链接:自定义OpenCV版本
opencv的结构需要是这样:
5、模型推理速度优化
1、剪切图片,将知道数字在哪个区域剪切下来,降低识别的范围。
2、使用轻量级模型进行识别
3、可以考虑去除部分方向模型检测,目的在于检测数字,不需要圈出。
三、遇到的问题
1、rec text: rec score:0.000000 cls label: 0 cls score: 0.581055 推理不出结果
问题原因是由于我使用V4的模型了,没有使用V3模型,导致一直推理不出结果。
2、译FastDeploy error: ‘string_view’ is not a member of ‘std’ os_string to_osstring(std::string_view utf8_str)
主要是C++11的问题。要使用C++17进行编译,估计FastDeploy 并没有修改好这个点。要修改CMakeLists.txt
3、在RK3568上使用conda,会导致RK3568 整个系统很卡顿,有可能是因为我的内存只有2g,不够用了。
四、将推理获取的库与文件使用Qt进行测试
流程还是比较简单的,主要就是放库文件的路径以及把该放的都放进去。
1、pro文件
INCLUDEPATH += $$PWD/thirdlib/fastdeploy/include
INCLUDEPATH += $$PWD/thirdlib/onnxruntime/include
INCLUDEPATH += $$PWD/thirdlib/opencv/include
INCLUDEPATH += $$PWD/thirdlib/paddle2onnx/include
INCLUDEPATH += $$PWD/thirdlib/rknpu2_runtime/includeLIBS += -L$$PWD/thirdlib/fastdeploy/lib -lfastdeploy
LIBS += -L$$PWD/thirdlib/onnxruntime/lib -lonnxruntime
LIBS += -L$$PWD/thirdlib/opencv/lib -lopencv_world
LIBS += -L$$PWD/thirdlib/paddle2onnx/lib -lpaddle2onnx
LIBS += -L$$PWD/thirdlib/rknpu2_runtime/lib -lrknnrt
2、MainWindows.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include "fastdeploy/vision.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();
protected:void _Init();void InitAndInfer(const std::string &det_model_file,const std::string &cls_model_file,const std::string &rec_model_file,const std::string &rec_label_file,const std::string &image_file,const fastdeploy::RuntimeOption &option,const fastdeploy::ModelFormat &format);
private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
3、MainWindows.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);_Init();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::_Init()
{fastdeploy::RuntimeOption option;fastdeploy::ModelFormat format;int iFlag = 1;if (iFlag == 0){option.UseCpu();format = fastdeploy::ONNX;}else if (iFlag == 1){option.UseRKNPU2();format = fastdeploy::RKNN;}QString sDetModelDir = "/model/ocr/paddle/model/ch_PP-OCRv3_det_infer/";QString sClsModelDir = "/model/ocr/paddle/ch_ppocr_mobile_v2.0_cls_infer/";QString sRecModelDir = "/model/ocr/paddle/ch_PP-OCRv3_rec_infer/";QString sDetModelName;QString sClsModelName;QString sRecModelName;if (iFlag == 0){sDetModelName = "ch_PP-OCRv3_det_infer.onnx";sClsModelName = "ch_ppocr_mobile_v2.0_cls_infer.onnx";sRecModelName = "ch_PP-OCRv3_rec_infer.onnx";}else{sDetModelName = "ch_PP-OCRv3_det_infer_rk3568_unquantized.rknn";sClsModelName = "ch_ppocr_mobile_v20_cls_infer_rk3568_unquantized.rknn";sRecModelName = "ch_PP-OCRv3_rec_infer_rk3568_unquantized.rknn";}QString sDetModel = sDetModelDir + sDetModelName;QString sClsModel = sClsModelDir + sClsModelName;QString sRecModel = sRecModelDir + sRecModelName;QString sLabelFile = "/model/ocr/paddle/key/ppocr_keys_v1.txt";
// auto im = cv::imread("/ics/test11.png");QString sImageFile = "/ics/test11.png";InitAndInfer(sDetModel.toStdString(), sClsModel.toStdString(), sRecModel.toStdString(), sLabelFile.toStdString(), sImageFile.toStdString(), option, format);
}void MainWindow::InitAndInfer(const std::string &det_model_file,const std::string &cls_model_file,const std::string &rec_model_file,const std::string &rec_label_file,const std::string &image_file,const fastdeploy::RuntimeOption &option,const fastdeploy::ModelFormat &format)
{auto det_params_file = "";auto cls_params_file = "";auto rec_params_file = "";auto det_option = option;auto cls_option = option;auto rec_option = option;if (format == fastdeploy::ONNX) {std::cout << "ONNX Model" << std::endl;}auto det_model = fastdeploy::vision::ocr::DBDetector(det_model_file, det_params_file, det_option, format);auto cls_model = fastdeploy::vision::ocr::Classifier(cls_model_file, cls_params_file, cls_option, format);auto rec_model = fastdeploy::vision::ocr::Recognizer(rec_model_file, rec_params_file, rec_label_file, rec_option, format);if (format == fastdeploy::RKNN) {cls_model.GetPreprocessor().DisableNormalize();cls_model.GetPreprocessor().DisablePermute();det_model.GetPreprocessor().DisableNormalize();det_model.GetPreprocessor().DisablePermute();rec_model.GetPreprocessor().DisableNormalize();rec_model.GetPreprocessor().DisablePermute();}det_model.GetPreprocessor().SetStaticShapeInfer(true);rec_model.GetPreprocessor().SetStaticShapeInfer(true);assert(det_model.Initialized());assert(cls_model.Initialized());assert(rec_model.Initialized());// The classification model is optional, so the PP-OCR can also be connected// in series as follows auto ppocr_v3 =// fastdeploy::pipeline::PPOCRv3(&det_model, &rec_model);auto ppocr_v3 =fastdeploy::pipeline::PPOCRv3(&det_model, &cls_model, &rec_model);// When users enable static shape infer for rec model, the batch size of cls// and rec model must to be set to 1.ppocr_v3.SetClsBatchSize(1);ppocr_v3.SetRecBatchSize(1);if (!ppocr_v3.Initialized()) {std::cerr << "Failed to initialize PP-OCR." << std::endl;return;}auto im = cv::imread(image_file);auto start = std::chrono::high_resolution_clock::now();fastdeploy::vision::OCRResult result;if (!ppocr_v3.Predict(im, &result)) {std::cerr << "Failed to predict." << std::endl;return;}std::cout << result.Str() << std::endl;// 记录结束时间auto end = std::chrono::high_resolution_clock::now();// 计算耗时(单位:毫秒)auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);std::cout << "Function execution time: " << duration.count() << " microseconds." << std::endl;auto vis_im = fastdeploy::vision::VisOcr(im, result);cv::imwrite("vis_result.jpg", vis_im);std::cout << "Visualized result saved in ./vis_result.jpg" << std::endl;
}
参考
1、FastDeploy RKNPU2 导航文档
2、PP-OCRv3 RKNPU2 C++部署示例
3、rknn_model_zoo 里面有具体的FPS
4、记录如何在RK3588板子上跑通paddle的OCR模型。重点是对齐rknntoolkit版本和板子上的librknnrt.so库
5、PaddleOCR_v4转换到瑞芯微RK3588
6、板端安装 rknpu2 驱动
7、嵌入式AI应用开发实战指南-PP-ORCv4
8、嵌入式AI应用开发实战指南-RKNN-Toolkit2
9、CPU部署库编译
如果对您有帮助,麻烦帮我点个赞噢!非常感谢,有什么问题可以评论区沟通~
接下来,就到了我们的经典环节: