RV1106 OCR 识别算法

发布于:2025-04-15 ⋅ 阅读:(34) ⋅ 点赞:(0)

  一 题记

目标是在某款 RV1106 低算力小板下跑通OCR文字识别算法,做个简单的应用,RK 官方模型库rk_model_zoo 有PP-OCR 的例子,但在 rv1106 上尚未支持。于是便打算折腾一吧。

二 方案甄选

参考国外某大佬的比较:

对比了几种方案, paddleOCR 在性能和精度上 应该算得上最优, 工程部署上的事情应该不是大问题。

hugging-face 的在线比较 : (PaddleOCR + EasyOcr + kerasOCR)

https://huggingface.co/spaces/pragnakalp/OCR-image-to-text

简单测试了一下,ppocr 在复杂的比如模糊的反光的照片下效果要好一些。

三 思路梳理

3.1 OCR 处理的通用流程

图像预处理(尺寸,归一化)=> 检测文字区域(OCR-DET) => 子图规一化(尺寸,角度变换) => 文字识别(OCR-REC)

  1. 其中 OCR-DET 和 OCR-REC 需要 预训练的算法模型来做
  2. 图像预处理是要将图像 调整到模型输入的大小,在 RKNN 平台,要固定输入图像的尺寸。
  3. 子图规一化,是将检测区域的子图像扣出来,拉成 横平竖直的规整图像。主要是做视角和尺寸的变换(仿射变换)。但 paddleOCR 可以识别 0 度和180度图像 , 90度和270度与不是模型的输入顺序,需要 通过 方向分类模型判断方向,旋转,然后再做仿射变换。

3.2 模型部署转换的流程

paddle模型 ==> 固定输入的onnx 模型 ==> rknn 模型

因为 rknn不支持动态输入,所以转 onnx 时要固定输入

其他tricks:

paddle 转 onnx模型本身是支持优化的,onnx 转 rknn 时工具也有针对rknn 平台的优化, 用类似 onnx-sim 工具再做优化价值不大。 不如实际 RKNN 跑起来做性能评估针对性的优化。

四 paddleOCR 转 rknn

4.1 基础环境

最好是用个 conda环境或 docker,python推荐 3.10 版本, 与其他 python包 依赖库版本冲突问题很难解决。

paddleOCR和 rknn_toolkit2 环境可以安装在一起

  • paddleOCR
pip install paddlepaddle paddle2onnx
  • rknn_toolkit2
git clone https://github.com/airockchip/rknn-toolkit2 
cd rknn-toolkit2 
pip install -r packages/x86_64/requirements_cp310-2.3.2.txt 
pip install packages/x86_64/rknn_toolkit2-2.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

4.2 下载模型

来源 : 

https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.9/doc/doc_ch/models_list.md

wget https://paddleocr.bj.bcebos.com/PP-OCRv4/chinese/ch_PP-OCRv4_det_infer.tar
wget https://paddleocr.bj.bcebos.com/PP-OCRv4/chinese/ch_PP-OCRv4_rec_infer.tar 
wget https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar

4.3 paddle2onnx

  • 检测模型
tar xf ch_PP-OCRv4_det_infer.tar 


MODEL=ch_PP-OCRv4_det_infer 
#export base model to onnx 
paddle2onnx --model_dir $MODEL \
 --model_filename inference.pdmodel \
 --params_filename inference.pdiparams \
 --save_file $MODEL/model.onnx \
 --opset_version 12 

# Seting fix input shape 
python -m paddle2onnx.optimize --input_model $MODEL/model.onnx \
 --output_model $MODEL/ch_ppocrv4_det.onnx \
 --input_shape_dict "{'x':[1,3,544, 960]}"

  • 识别模型
tar xf ch_PP-OCRv4_rec_infer.tar 
MODEL=ch_PP-OCRv4_rec_infer 
# export base model to onnx 

paddle2onnx --model_dir $MODEL \
 --model_filename inference.pdmodel \
 --params_filename inference.pdiparams \
 --save_file $MODEL/model.onnx \
 --opset_version 12 

# Seting fix input shape 
python -m paddle2onnx.optimize --input_model $MODEL/model.onnx \
 --output_model $MODEL/ch_ppocrv4_rec.onnx \
 --input_shape_dict "{'x':[1,3,48,320]}"

4.4 onnx2rknn

参考这里:

https://github.com/airockchip/rknn_model_zoo/issues/89

目前RK官方的例子里 ppocr-det 能转换成功,执行不成功, ppocr-rec 没有做 RV1106 转换脚本 ,试了魔改一下能转换成功, 但执行的时候提示有不支持的算子 (可能是ReduceMean的通道数问题)

下面来一一解决

4.4.1 PPOCR-Det 转 RKNN

使用这个脚本:

https://github.com/airockchip/rknn_model_zoo/blob/main/examples/PPOCR/PPOCR-Det/python/convert.py

python3 convert.py ch_ppocrv4_det.onnx rv1106 i8 ch_ppocrv4_det.rknn

推理时要修改一下 这个代码 :

https://github.com/airockchip/rknn_model_zoo/blob/main/examples/PPOCR/PPOCR-Det/cpp/rknpu2/ppocr_det.cc

  1. 模型输入输出要用 rknn_create_mem分配 cma 内存之后 调用 rknn_set_io_mem , rv1106 不支持虚拟地址 推理,参考 https://github.com/airockchip/rknn_model_zoo/blob/main/examples/yolov5/cpp/rknpu2/yolov5_rv1106_1103.cc
  2. 转换的模型 output_attr 的数据FMT 会读取错(可能 rknn的bug), 此时 要强制 output_attrs[0].fmt = NHWC,再设置rknn_set_io_mem 可以成功.

4.4.2 PPOCR-REC 转 RKNN

修改转换脚本 :

https://github.com/airockchip/rknn_model_zoo/blob/main/examples/PPOCR/PPOCR-Rec/python/convert.py

#默认打开量化 

DEFAULT_QUANT = True 

#提供量化数据集 

dataset='./dataset.txt' 

# 配置 
rknn.config(mean_values=[[127.5,127.5,127.5]], std_values=[[127.5,127.5,127.5]], target_platform=platform) 

# BUILD 
ret = rknn.build(do_quantization=do_quant, dataset=DATASET_PATH)

这样可以成功转换出模型, 同时需要修改推理代码:

参考 4.4.1 说明 修改:

https://github.com/airockchip/rknn_model_zoo/blob/main/examples/PPOCR/PPOCR-Rec/cpp/rknpu2/ppocr_rec.cc

 

到板子下执行

会报错:

E RKNN: unsupport cpu exNorm op, op name: exNorm:p2o.ReduceMean.0_2ln in current, please try updating to the latest version of the toolkit2 and runtime from: https://console.zbox.filez.com/l/I00fc3 (PWD: rknn) E RKNN: rknn fallback cpu failed

日志显示 ReduceMean 这个算子fallback 到 cpu 也没法兼容 , 白折腾了?

ps: 演砸了,后事如何 请看下回分解。。

4.5 ppocr-det 拆分后再转rknn

4.5.1 模型分析

使用 Netron 查看 ch_ppocrv4_rec.onnx, ReduceMean 出现在后小半部分,

考虑先把 onnx 拦腰斩断,前半部分转rknn , 后半部分用onnx 推理

找到了这条长蛇的七寸

4.5.2 使用 onnxutils 工具进行拆分

import onnx 

#first.onnx 
input_path = "ch_PP-OCRv4_rec_infer.onnx" 
output_path = "first.onnx" 
input_names = ["x"] 
output_names = ["Add.175"] 
onnx.utils.extract_model(input_path, output_path, input_names, output_names) 

#second.onnx 
input_path = "ch_PP-OCRv4_rec_infer.onnx" 
output_path = "second.onnx" 
input_names = ["Add.175"] 
output_names = ["softmax_2.tmp_0"] 
onnx.utils.extract_model(input_path, output_path, input_names, output_names)

4.5.3 拆分之后的处理

拆分之后 第一个模型输出为1x480x3x80 , 转 rknn , 输出为 1x480x3x80 int8 要转 fp32

第二个模型为 onnx 就用onnxruntime 来推理

4.5.4 转换后速度

first.rknn 推理时间 <40ms , second.onnx 用 onnxruntime 推理 100~200ms ( 英文模型时间会更短)

比起 ppocr-rec.onnx 直接用 onnxruntime推理 (> 2s 时间) 大大缩短了执行时间


网站公告

今日签到

点亮在社区的每一天
去签到