Skip to content

Commit ee7dc4b

Browse files
committed
docs: add v5 convert
1 parent a295499 commit ee7dc4b

File tree

2 files changed

+235
-0
lines changed

2 files changed

+235
-0
lines changed
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
---
2+
title: RapidOCR集成PP-OCRv5_mobile_det模型记录
3+
date: 2025-05-26
4+
authors: [SWHL]
5+
categories:
6+
- 模型相关
7+
comments: true
8+
hide:
9+
- toc
10+
---
11+
12+
13+
> 该文章主要记录RapidOCR集成PP-OCRv5_mobile_det模型记录的,涉及模型转换,模型精度测试等步骤。
14+
15+
<!-- more -->
16+
17+
### 引言
18+
19+
### 以下代码运行环境
20+
21+
- OS: macOS Sequoia 15.5
22+
- Python: 3.10.14
23+
- PaddlePaddle: 3.0.0
24+
- paddle2onnx: 2.0.2.rc1
25+
- paddlex: 3.0.0
26+
- rapidocr: 2.1.0
27+
28+
### 1. 模型跑通
29+
30+
该步骤主要先基于PaddleX可以正确使用PP-OCRv5_mobile_det模型得到正确结果。
31+
32+
该部分主要参考文档:[docs](https://paddlepaddle.github.io/PaddleX/latest/module_usage/tutorials/ocr_modules/text_recognition.html#_3)
33+
34+
安装`paddlex`:
35+
36+
```bash linenums="1"
37+
pip install "paddlex[ocr]==3.0.0rc1"
38+
```
39+
40+
测试PP-OCRv5_mobile_det模型能否正常识别:
41+
42+
测试用图:
43+
44+
![alt text](../images/1.jpg)
45+
46+
!!! tip
47+
48+
运行以下代码时,模型会自动下载到 **/Users/用户名/.paddlex/official_models** 下。
49+
50+
```python linenums="1"
51+
52+
from paddleocr import PaddleOCR
53+
# 初始化 PaddleOCR 实例
54+
55+
ocr = PaddleOCR(
56+
use_doc_orientation_classify=False,
57+
use_doc_unwarping=False,
58+
use_textline_orientation=False)
59+
60+
# 对示例图像执行 OCR 推理
61+
result = ocr.predict(
62+
input="https://paddle-model-ecology.bj.bcebos.com/paddlex/imgs/demo_image/general_ocr_002.png")
63+
64+
# 可视化结果并保存 json 结果
65+
for res in result:
66+
res.print()
67+
res.save_to_img("output")
68+
res.save_to_json("output")
69+
```
70+
71+
预期结果如下,表明成功运行:
72+
73+
![alt text](../images/general_ocr_002_ocr_res_img.png)
74+
75+
### 2. 模型转换
76+
77+
该部分主要参考文档: [docs](https://paddlepaddle.github.io/PaddleX/latest/pipeline_deploy/paddle2onnx.html?h=paddle2onnx#22)
78+
79+
PaddleX官方集成了paddle2onnx的转换代码:
80+
81+
```bash linenums="1"
82+
paddlex --paddle2onnx --paddle_model_dir models/PP-OCRv5_mobile_det --onnx_model_dir models/PP-OCRv5_mobile_det
83+
```
84+
85+
输出日志如下,表明转换成功:
86+
87+
```bash linenums="1"
88+
Input dir: models/PP-OCRv5_mobile_det
89+
Output dir: models/PP-OCRv5_mobile_det
90+
Paddle2ONNX conversion starting...
91+
warnings.warn(warning_message)
92+
[Paddle2ONNX] Start parsing the Paddle model file...
93+
[Paddle2ONNX] Use opset_version = 7 for ONNX export.
94+
[Paddle2ONNX] PaddlePaddle model is exported as ONNX format now.
95+
2025-05-14 08:21:23 [INFO] Try to perform optimization on the ONNX model with onnxoptimizer.
96+
2025-05-14 08:21:23 [INFO] ONNX model saved in models/PP-OCRv5_mobile_det/inference.onnx.
97+
Paddle2ONNX conversion succeeded
98+
Done
99+
```
100+
101+
### 3. 模型推理验证
102+
103+
该部分主要是在RapidOCR项目中测试能否直接使用onnx模型。要点主要是确定模型前后处理是否兼容。从PaddleX[官方文档](https://paddlepaddle.github.io/PaddleX/latest/module_usage/tutorials/ocr_modules/text_recognition.html#_2)中可以看到:
104+
105+
> PP-OCRv5_mobile_det是在PP-OCRv4_server_rec的基础上,在更多中文文档数据和PP-OCR训练数据的混合数据训练而成,增加了部分繁体字、日文、特殊字符的识别能力,可支持识别的字符为1.5万+,除文档相关的文字识别能力提升外,也同时提升了通用文字的识别能力
106+
107+
以上说明了该模型与PP-OCRv4_server_rec模型结构相同,前后处理也相同。唯一做的就是添加了更多数据,扩展了字典个数,从6623扩展到15630个。因此,可以直接使用RapidOCR来快速推理验证。代码如下:
108+
109+
```python linenums="1"
110+
from rapidocr import RapidOCR
111+
112+
model_path = "models/PP-OCRv5_mobile_det/inference.onnx"
113+
key_path = "models/ppocrv4_doc_dict.txt"
114+
engine = RapidOCR(params={"Rec.model_path": model_path, "Rec.rec_keys_path": key_path})
115+
116+
img_url = "https://img1.baidu.com/it/u=3619974146,1266987475&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=516"
117+
result = engine(img_path)
118+
print(result)
119+
120+
result.vis("vis_result.jpg")
121+
```
122+
123+
![alt text](../images/vis_result.jpg)
124+
125+
### 4. 模型精度测试
126+
127+
该部分主要使用[TextRecMetric](https://github.com/SWHL/TextRecMetric)和测试集[text_rec_test_dataset](https://huggingface.co/datasets/SWHL/text_rec_test_dataset)来评测。
128+
129+
需要注意的是,**PP-OCRv5_mobile_det模型更加侧重生僻字和一些符号识别。** 当前测试集并未着重收集生僻字和一些符号的数据,因此以下指标会有些偏低。如需自己使用,请在自己场景下测试效果。
130+
131+
相关测试步骤请参见[TextRecMetric](https://github.com/SWHL/TextRecMetric)的README,一步一步来就行。我这里测试最终精度如下:
132+
133+
```json
134+
{'ExactMatch': 0.8097, 'CharMatch': 0.9444, 'avg_elapse': 0.0818}
135+
```
136+
137+
该结果已经更新到[开源OCR模型对比](./model_summary.md)中。
138+
139+
### 5. 集成到rapidocr中
140+
141+
该部分主要包括将字典文件写入到ONNX模型中、托管模型到魔搭、更改rapidocr代码适配等。
142+
143+
#### 字典文件写入ONNX模型
144+
145+
该步骤仅存在文本识别模型中,文本检测模型没有这个步骤。
146+
147+
??? info "详细代码"
148+
149+
```python linenums="1"
150+
from pathlib import Path
151+
from typing import List, Union
152+
153+
import onnx
154+
import onnxruntime as ort
155+
from onnx import ModelProto
156+
157+
158+
def read_txt(txt_path: Union[Path, str]) -> List[str]:
159+
with open(txt_path, "r", encoding="utf-8") as f:
160+
data = [v.rstrip("\n") for v in f]
161+
return data
162+
163+
164+
class ONNXMetaOp:
165+
@classmethod
166+
def add_meta(
167+
cls,
168+
model_path: Union[str, Path],
169+
key: str,
170+
value: List[str],
171+
delimiter: str = "\n",
172+
) -> ModelProto:
173+
model = onnx.load_model(model_path)
174+
meta = model.metadata_props.add()
175+
meta.key = key
176+
meta.value = delimiter.join(value)
177+
return model
178+
179+
@classmethod
180+
def get_meta(
181+
cls, model_path: Union[str, Path], key: str, split_sym: str = "\n"
182+
) -> List[str]:
183+
sess = ort.InferenceSession(model_path)
184+
meta_map = sess.get_modelmeta().custom_metadata_map
185+
key_content = meta_map.get(key)
186+
key_list = key_content.split(split_sym)
187+
return key_list
188+
189+
@classmethod
190+
def del_meta(cls, model_path: Union[str, Path]) -> ModelProto:
191+
model = onnx.load_model(model_path)
192+
del model.metadata_props[:]
193+
return model
194+
195+
@classmethod
196+
def save_model(cls, save_path: Union[str, Path], model: ModelProto):
197+
onnx.save_model(model, save_path)
198+
199+
200+
dicts = read_txt(
201+
"models/ppocrv4_doc_dict.txt"
202+
)
203+
model_path = "models/PP-OCRv5_mobile_det.onnx"
204+
model = ONNXMetaOp.add_meta(model_path, key="character", value=dicts)
205+
206+
new_model_path = "models/PP-OCRv5_mobile_det_with_dict.onnx"
207+
ONNXMetaOp.save_model(new_model_path, model)
208+
209+
t = ONNXMetaOp.get_meta(new_model_path, key="character")
210+
print(t)
211+
```
212+
213+
#### 托管模型到魔搭
214+
215+
该部分主要是涉及模型上传到对应位置,并合理命名。注意上传完成后,需要打Tag,避免后续rapidocr whl包中找不到模型下载路径。
216+
217+
我这里已经上传到了魔搭上,详细链接参见:[link](https://www.modelscope.cn/models/RapidAI/RapidOCR/files?version=v2.1.0)
218+
219+
#### 更改rapidocr代码适配
220+
221+
该部分主要涉及到更改[default_models.yaml](https://github.com/RapidAI/RapidOCR/blob/4d35ed272a1192afbcb95e823d99eb14c86b7893/python/rapidocr/default_models.yaml)[paddle.py](https://github.com/RapidAI/RapidOCR/blob/4d35ed272a1192afbcb95e823d99eb14c86b7893/python/rapidocr/inference_engine/paddle.py)的代码来适配。
222+
223+
同时,需要添加对应的单元测试,在保证之前单测成功的同时,新的针对性该模型的单测也能通过。
224+
225+
我这里已经做完了,小伙伴们感兴趣可以去看看源码。
226+
227+
#### 发布新版本
228+
229+
因为这次算是功能新增,按照语义化版本号来看,我们版本号需要从v2.0.7 → v2.1.0。
230+
231+
我只需要在github仓库中,打一个v2.1.0的tag,Github Action会自动跑所有单元测试,自动发版到pypi。
232+
233+
### 写在最后
234+
235+
至此,集成工作就基本完成了。
556 KB
Loading

0 commit comments

Comments
 (0)