当前位置: 首页 > news >正文

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部署库编译

如果对您有帮助,麻烦帮我点个赞噢!非常感谢,有什么问题可以评论区沟通~
接下来,就到了我们的经典环节:
在这里插入图片描述

http://www.xdnf.cn/news/255025.html

相关文章:

  • 文章三《机器学习基础概念与框架实践》
  • 【STM32】定时器输入捕获
  • 怎么实现动态提示词,并提升准确率
  • [面试]SoC验证工程师面试常见问题(二)
  • ps将图标变清晰-cnblog
  • MATLAB绘制局部放大图
  • 【Bootstrap V4系列】 学习入门教程之 组件-警告框(Alert)
  • 【DecAlign】用于解耦多模态表征学习的分层跨模态对齐
  • Spring AI:简化人工智能功能应用程序开发
  • 对称加密算法(AES、ChaCha20和SM4)Python实现——密码学基础(Python出现No module named “Crypto” 解决方案)
  • mysql索引及数据库引擎
  • 计算方法实验三 解线性方程组的直接方法
  • C++模板知识
  • 数据库系统概论|第五章:数据库完整性—课程笔记1
  • PostgreSQL 查看表膨胀情况的方法
  • 【算法基础】冒泡排序算法 - JAVA
  • w317汽车维修预约服务系统设计与实现
  • 藏语英语中文机器翻译入门实践
  • 仿腾讯会议——主界面设计创建房间加入房间客户端实现
  • 大模型压缩技术详解(2025最新进展)
  • python入门
  • kubernetes中离线业务编排详解JobCronJob之Job控制器CronJob
  • 云计算-容器云-部署jumpserver 版本2
  • 4.0/Q2,Charls最新文章解读
  • Android和iOS测试的区别有哪些?
  • CSS 架构与命名规范
  • 安装java11
  • cudaPointerGetAttributes详解
  • 如何利用dify 生成Fine‑tune 需要的Alpaca 格式数据
  • ShaderToy学习笔记 07.Phong光照模型