跳转到内容

PP-OCRv6 OCR 算法执行指南(RV1126B)

文档信息

项目内容
文档名PP-OCRv6 OCR 算法执行指南(RV1126B)
版本v1.0
目标开发板RV1126B 开发板
目标算法PP-OCRv6 OCR
目标功能日文图像 OCR
开发环境Ubuntu 22.04 Docker、RKNN Toolkit2 Docker、RV1126B 开发板
推荐模型PP-OCRv6_small_detPP-OCRv6_small_rec
开发板 IP192.168.10.85
板侧部署目录/userdata/ppocrv6_ocr_demo/

修订历史

版本日期内容
v1.02026-06-27初版。整理 PP-OCRv6 日文 OCR、ONNX/RKNN 转换与 RV1126B 部署流程。

例程相关资料下载

本教程使用的示例代码、模型、测试图像等相关资料可从以下链接下载。

04_ocr.zip

1. 概述

本文档说明如何在 RV1126B 开发板上执行 PP-OCRv6 OCR。整体流程是在 PC 或 Docker 环境中准备 PaddleOCR 模型,转换为 ONNX,再通过 RKNN Toolkit2 转换为 RV1126B 可执行的 RKNN 模型。板侧通过 RKNN Runtime 和 C++ 程序完成文字检测、文字区域裁剪、文字识别、CTC decode 和结果保存。

整体流程如下。

使用 PP-OCRv6 small 模型验证日文 OCR
固定 Paddle inference model
Paddle model → ONNX
ONNX → RKNN(target_platform=rv1126b)
将模型、字典、C++ 可执行文件部署到 RV1126B
通过 RKNN C API 执行 det / rec
保存 OCR 结果图片和文本

RV1126B 侧不运行完整 PaddleOCR Python 包,而是只使用 RKNN Runtime 执行模型。

2. 使用模型

用途模型名板侧 RKNN 文件说明
文字检测PP-OCRv6_small_detppocrv6_small_det_rv1126b_i8.rknn检测图像中的文字区域。
文字识别PP-OCRv6_small_recppocrv6_small_rec_rv1126b_fp_no_softmax.rknn将文字行图像识别为日文文本。

rec 模型使用去除最终 Softmax 后的 RKNN 模型。CTC decode 只需要每个时间步的最大类别,因此使用 Softmax 前 logits 与 Softmax 后概率的 argmax 结果一致。

3. 工作目录

示例工作目录如下。

Terminal window
/opt/linuxshare/work/rv1126b/jp/AI/demo/ai-algorithm/04_ocr/ppocrv6_jp_demo

目录结构示例:

ppocrv6_jp_demo/
├── samples/
├── output/
├── models/
│ ├── paddle/
│ ├── onnx/
│ ├── rknn/
│ └── rec/
├── scripts/
├── logs/
└── rv1126b-src/

4. Conda 环境与 PaddleOCR 准备

创建 PP-OCRv6 专用环境。

Terminal window
conda create -n ppocrv6 python=3.10 -y
conda activate ppocrv6

安装 PaddlePaddle 和 PaddleOCR。

Terminal window
python -m pip install --upgrade pip setuptools wheel
python -m pip install paddlepaddle==3.3.0 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/
python -m pip install paddleocr==3.7.0

确认安装结果。

Terminal window
python - <<'PY'
import paddle
import paddleocr
import sys
print("Python:", sys.version)
print("Paddle:", paddle.__version__)
print("PaddleOCR:", paddleocr.__version__)
print("CUDA:", paddle.is_compiled_with_cuda())
PY

图1 PP-OCRv6 日文 OCR 环境构建确认图片

5. 日文 OCR 测试图片

本次使用的日文测试图片如图2 所示。

图2 PP-OCRv6 日文 OCR 测试图片

放置测试图片。

Terminal window
mkdir -p samples
cp /path/to/jp_001.jpg ./samples/jp_001.jpg

6. 使用 PaddleOCR 验证日文 OCR

创建 scripts/test_ppocrv6_jp.py

import os
os.environ["FLAGS_use_mkldnn"] = "0"
os.environ["FLAGS_use_onednn"] = "0"
os.environ["PADDLE_PDX_ENABLE_MKLDNN_BYDEFAULT"] = "0"
os.environ["PADDLE_PDX_DISABLE_MODEL_SOURCE_CHECK"] = "True"
from paddleocr import PaddleOCR
ocr = PaddleOCR(
text_detection_model_name="PP-OCRv6_small_det",
text_recognition_model_name="PP-OCRv6_small_rec",
use_doc_orientation_classify=False,
use_doc_unwarping=False,
use_textline_orientation=False,
text_det_limit_side_len=736,
text_det_limit_type="max",
text_recognition_batch_size=1,
device="cpu",
)
results = ocr.predict("./samples/jp_001.jpg")
for res in results:
res.print()
res.save_to_img("./output")
res.save_to_json("./output")

执行:

Terminal window
python scripts/test_ppocrv6_jp.py

PaddleOCR Python 版可视化结果如图3 所示。

图3 PaddleOCR Python 版 OCR 可视化结果

7. 固定 Paddle 模型与导出字典

将自动下载的模型复制到工程目录。

Terminal window
mkdir -p models/paddle
cp -r ~/.paddlex/official_models/PP-OCRv6_small_det models/paddle/PP-OCRv6_small_det
cp -r ~/.paddlex/official_models/PP-OCRv6_small_rec models/paddle/PP-OCRv6_small_rec

rec 模型的字符表在 inference.ymlPostProcess.character_dict 中。为了方便 C++ 端读取,将其导出为一行一个字符的 txt 文件。

Terminal window
python - <<'PY'
import yaml
from pathlib import Path
yml_path = Path("./models/paddle/PP-OCRv6_small_rec/inference.yml")
out_path = Path("./models/rec/ppocrv6_rec_dict.txt")
out_path.parent.mkdir(parents=True, exist_ok=True)
cfg = yaml.safe_load(yml_path.read_text(encoding="utf-8"))
chars = cfg["PostProcess"]["character_dict"]
out_path.write_text("\n".join(map(str, chars)) + "\n", encoding="utf-8")
print("dict:", out_path)
print("chars:", len(chars))
PY

本次字典行数为:

18708

rec 模型输出类别数为 18710,差异的两个类别用于 CTC blank 和 space。

8. Paddle model 转 ONNX

使用 PaddleX 的 paddle2onnx 转换模型。

Terminal window
paddlex \
--paddle2onnx \
--paddle_model_dir ./models/paddle/PP-OCRv6_small_rec \
--onnx_model_dir ./models/onnx/PP-OCRv6_small_rec \
--opset_version 11

执行结果如图4 所示。

图4 PP-OCRv6 rec 模型 Paddle2ONNX 转换结果

ONNX 文件生成在:

models/onnx/PP-OCRv6_small_rec/inference.onnx

det 模型同样转换为 ONNX。

Terminal window
paddlex \
--paddle2onnx \
--paddle_model_dir ./models/paddle/PP-OCRv6_small_det \
--onnx_model_dir ./models/onnx/PP-OCRv6_small_det \
--opset_version 11

9. RKNN 转换环境

RKNN 转换在 RKNN Toolkit2 Docker 中完成。

Terminal window
docker run -t -i --privileged \
-v /dev/bus/usb:/dev/bus/usb \
-v /data/project/sales/csun/rv1126b/jp/AI/demo:/test \
rknn-toolkit2:2.3.2-cp38 /bin/bash

进入工作目录。

Terminal window
cd /test/ai-algorithm/04_ocr/ppocrv6_jp_demo

确认 RKNN Toolkit2 可用。

Terminal window
python - <<'PY'
from rknn.api import RKNN
print("RKNN Toolkit2 import OK")
PY

10. det 模型 RKNN 转换

det 模型标准使用 INT8 量化模型,输入固定为 1 x 736 x 736 x 3

生成量化校准列表。

Terminal window
DATASET_ROOT=./datasets/japanese_ocr_synthetic_dataset_v1_0
sed "s#^#japanese_ocr_synthetic_dataset_v1_0/# \
"${DATASET_ROOT}/labels/image_list.txt" \
> ./datasets/ppocrv6_det_calib.txt

由于 ppocrv6_det_calib.txt 位于 ./datasets/ 目录下,列表内部路径应相对于 ./datasets/。不要写成 ./datasets/japanese_ocr_synthetic_dataset_v1_0/...,否则会被解析成 ./datasets/datasets/...

det 转换脚本中固定动态输入。

ret = rknn.load_onnx(
model="./models/onnx/PP-OCRv6_small_det/inference.onnx",
inputs=["x"],
input_size_list=[[1, 3, 736, 736]],
)

执行转换。

Terminal window
python scripts/convert_ppocrv6_det_to_rknn.py 2>&1 \
| tee logs/convert_ppocrv6_det_to_rknn.log

结果如图5 所示。

图5 PP-OCRv6 det 模型 INT8 RKNN 转换结果

也可以生成 FP 模型用于精度对比。

Terminal window
python scripts/convert_ppocrv6_det_to_rknn_fp.py 2>&1 \
| tee logs/convert_ppocrv6_det_to_rknn_fp.log

图6 PP-OCRv6 det 模型 FP RKNN 转换结果

11. rec 模型 RKNN 转换与 Softmax 去除

普通转换后的 rec 模型在板侧最终 Softmax 执行时失败。普通转换日志如图7 所示。

图7 PP-OCRv6 rec 模型普通 RKNN 转换结果

板侧失败点为:

op name: exSoftmax13:Softmax.2
rknn_run failed

查看 ONNX 中的 Softmax 节点。

Terminal window
python - <<'PY'
import onnx
model = onnx.load("./models/onnx/PP-OCRv6_small_rec/inference.onnx")
for i, node in enumerate(model.graph.node):
if node.op_type == "Softmax" or "Softmax" in node.name:
print("index:", i)
print("op_type:", node.op_type)
print("name:", node.name)
print("input:", list(node.input))
print("output:", list(node.output))
print("-" * 80)
PY

结果中最终 Softmax 为:

index: 480
op_type: Softmax
name: Softmax.2
input: ['p2o.pd_op.add.79.0']
output: ['fetch_name_0']

因此将 p2o.pd_op.add.79.0 作为 RKNN 输出,去除最终 Softmax。

from pathlib import Path
from rknn.api import RKNN
ONNX_MODEL = "./models/onnx/PP-OCRv6_small_rec/inference.onnx"
RKNN_MODEL = "./models/rknn/ppocrv6_small_rec_rv1126b_fp_no_softmax.rknn"
REC_INPUT_SIZE = [1, 3, 48, 320]
REC_OUTPUT_NAME = "p2o.pd_op.add.79.0"
def main():
Path("./models/rknn").mkdir(parents=True, exist_ok=True)
rknn = RKNN(verbose=True)
rknn.config(
target_platform="rv1126b",
mean_values=[[127.5, 127.5, 127.5]],
std_values=[[127.5, 127.5, 127.5]],
optimization_level=3,
)
ret = rknn.load_onnx(
model=ONNX_MODEL,
inputs=["x"],
input_size_list=[REC_INPUT_SIZE],
outputs=[REC_OUTPUT_NAME],
)
if ret != 0:
raise RuntimeError("load_onnx failed")
ret = rknn.build(do_quantization=False)
if ret != 0:
raise RuntimeError("build failed")
ret = rknn.export_rknn(RKNN_MODEL)
if ret != 0:
raise RuntimeError("export_rknn failed")
rknn.release()
print("done:", RKNN_MODEL)
if __name__ == "__main__":
main()

执行转换。

Terminal window
python scripts/convert_ppocrv6_rec_to_rknn_no_softmax.py 2>&1 \
| tee logs/convert_ppocrv6_rec_to_rknn_no_softmax.log

结果如图8 所示。

图8 去除最终 Softmax 的 rec 模型 RKNN 转换结果

生成模型:

models/rknn/ppocrv6_small_rec_rv1126b_fp_no_softmax.rknn

12. 挂载 RV1126B 开发板

RV1126B 开发板 IP 为 192.168.10.85。宿主机执行:

Terminal window
sudo umount -l /mnt 2>/dev/null
sudo mount -t nfs \
-o vers=3,proto=tcp,mountproto=tcp,nolock,retrans=5,timeo=5 \
192.168.10.85:/ /mnt

挂载后通过 /mnt/userdata/ 向开发板复制模型、字典和执行程序。

13. 板侧 RKNN Runtime 处理原则

板侧已经配置好 RKNN Runtime:

/usr/lib/librknnrt.so
/usr/lib/librknn_api.so

因此不要向 demo 目录单独拷贝 librknnrt.so,也不要设置 LD_LIBRARY_PATH=./lib。旧版本 runtime 可能优先加载并导致异常。

确认命令:

Terminal window
find / -name 'librknn*.so*' 2>/dev/null

14. 板侧部署目录

板侧目录结构如下。

/userdata/ppocrv6_ocr_demo/
├── bin/
│ ├── test-rknn-model-smoke
│ └── test-ppocrv6-ocr
├── model/
│ ├── ppocrv6_small_det_rv1126b_i8.rknn
│ └── ppocrv6_small_rec_rv1126b_fp_no_softmax.rknn
├── dict/
│ └── ppocrv6_rec_dict.txt
└── test/
├── jp_001.jpg
├── ocr_result.txt
├── ocr_result.jpg
└── crops/

复制模型和字典。

Terminal window
sudo mkdir -p /mnt/userdata/ppocrv6_ocr_demo/{model,dict,test,bin}
sudo cp models/rknn/ppocrv6_small_det_rv1126b_i8.rknn \
/mnt/userdata/ppocrv6_ocr_demo/model/
sudo cp models/rknn/ppocrv6_small_rec_rv1126b_fp_no_softmax.rknn \
/mnt/userdata/ppocrv6_ocr_demo/model/
sudo cp models/rec/ppocrv6_rec_dict.txt \
/mnt/userdata/ppocrv6_ocr_demo/dict/
sudo cp samples/jp_001.jpg \
/mnt/userdata/ppocrv6_ocr_demo/test/

15. C++ 执行程序结构

板侧 C++ 代码使用一个 build.sh 生成两个可执行文件。

rv1126b-src/
├── build.sh
├── CMakeLists.txt
└── src/
├── rknn_model_smoke_test.cc
└── ppocrv6_ocr_demo.cc
可执行文件用途
test-rknn-model-smoke验证 .rknn 模型能否在板侧 rknn_initrknn_run
test-ppocrv6-ocr执行图像读取、det 推理、crop、rec 推理、CTC decode 和结果保存。

build.sh 使用 CURRENT_FOLDER=bin,将生成物复制到 $SYSROOT/userdata/ppocrv6_ocr_demo/bin/

Terminal window
./build.sh

16. det 模型 smoke test

板侧执行:

Terminal window
cd /userdata/ppocrv6_ocr_demo
./bin/test-rknn-model-smoke \
./model/ppocrv6_small_det_rv1126b_i8.rknn

执行结果如图9 所示。

图9 det 模型 RV1126B smoke test 结果

确认结果:

input: 1 x 736 x 736 x 3, INT8, NHWC
output: 1 x 1 x 736 x 736, INT8, NCHW
rknn_run OK
model smoke test OK

17. rec no-softmax 模型 smoke test

板侧执行:

Terminal window
cd /userdata/ppocrv6_ocr_demo
./bin/test-rknn-model-smoke \
./model/ppocrv6_small_rec_rv1126b_fp_no_softmax.rknn

执行结果如图10 所示。

图10 rec no-softmax 模型 RV1126B smoke test 结果

确认结果:

input: 1 x 48 x 320 x 3, FLOAT16, NHWC
output: 1 x 40 x 18710, FLOAT16
rknn_run OK
model smoke test OK

18. 板侧 OCR 执行

板侧执行:

Terminal window
cd /userdata/ppocrv6_ocr_demo
./bin/test-ppocrv6-ocr \
./model/ppocrv6_small_det_rv1126b_i8.rknn \
./model/ppocrv6_small_rec_rv1126b_fp_no_softmax.rknn \
./dict/ppocrv6_rec_dict.txt \
./test/jp_001.jpg \
./test

执行日志如图11 和图12 所示。

图11 RV1126B 上 PP-OCRv6 OCR 执行日志前半

图12 RV1126B 上 PP-OCRv6 OCR 执行日志后半

输出文件:

/userdata/ppocrv6_ocr_demo/test/ocr_result.txt
/userdata/ppocrv6_ocr_demo/test/ocr_result.jpg
/userdata/ppocrv6_ocr_demo/test/crops/

19. 日文 OCR 执行结果

本次板侧执行检测到 53 个文本区域。部分识别结果如下。

编号识别结果
0もちもち
1とろっと、後味のよい
2天然の
7焼きたて
10うま味のある
12飽きのこない
23スパイシー
37ふんわり
51後味すっきり
52とろける

板侧保存的 OCR 可视化结果如图13 所示。

图13 RV1126B 上保存的 OCR 可视化结果

ocr_result.txt 部分内容如下。

0 667 58 187 53 0.945086 もちもち
1 855 64 460 99 0.891344 とろっと、後味のよい
2 400 81 135 49 0.932682 天然の
7 922 148 314 82 0.935921 焼きたて
10 100 200 483 103 0.950072 うま味のある
37 409 505 389 105 0.917636 ふんわり
51 496 732 285 64 0.951753 後味すっきり
52 828 768 97 34 0.925347 とろける

20. 当前精度评价

v1.1 阶段,板侧 PP-OCRv6 执行链路已正常跑通。

det RKNN 推理:成功
rec no-softmax RKNN 推理:成功
CTC decode:成功
结果文本保存:成功
结果图片保存:成功

仍需优化的问题:

项目现象后续处理
文字识别口どけのよい 有时被识别为 ロどけのよい检查 crop 质量、识别模型和规则后处理。
检测框相邻多个词可能合并为一个大框。替换为 PaddleOCR 标准 DB postprocess。
后处理v1.1 C++ 检测后处理为简化版。增加 box_score_fastunclip、rotated box。

21. 面向产品级精度的数据集与追加训练方案

v1.4 不再只描述评估方向,而是补充到可以实际准备训练数据、标注数据,并对 PaddleOCR 系列检测模型和识别模型进行追加训练的程度。

产品级精度不能只依赖公共数据集。推荐把数据分为三类:

公共数据集
确认日文、多语言 OCR 的基础能力
合成数据
补足缺失字符、字体、竖排、低照度、反光、模糊等场景
RV1126B 实机拍摄数据
适配真实镜头、曝光、焦距、压缩噪声、安装角度和照明环境

对于 RV1126B 产品,最终精度强依赖真实摄像头、照明、安装距离和图像压缩条件。因此,公共数据集主要用于基础评估和辅助训练,最终产品判定必须以 RV1126B 实拍数据为准。

21.1 公共数据集与下载链接

下列数据集可用于基础评估、追加训练或泛化能力验证。实际使用前必须确认各数据集的许可证、研究/商用使用条件以及是否允许再分发。

用途数据集下载或参考地址推荐用途
多语言自然场景 OCRICDAR 2019 MLTICDAR 2019 RRC MLT Downloads多语言、复杂背景、倾斜、低分辨率文字的检测与识别评估。下载需要注册 RRC。
日文场景文字JPSC1400JPSC1400 Dataset Page / JPSC1400-20201218.zip使用真实环境拍摄的日文字符图像进行识别评估,适合做字符级弱点分析。
日文文档 OCR国立国会图书馆古典籍 OCR 学习用数据集ndl-lab/ndl-minhon-ocrdataset适合参考日文文档、竖排、古籍和劣化文档场景。由于和产品场景差异较大,不建议直接混入主训练集。
日文字符分类Kuzushiji / KMNIST 系列Kuzushiji Dataset可用于假名和汉字的字符级评估、混淆分析。若用于 PP-OCR 行识别训练,需要转换为行图像格式。
日文字符图像ETL Character DatabaseETL Character Database可用于手写/印刷日文字符基础评估、字符级混淆分析和合成数据参考。

使用公共数据集时,建议遵循以下原则:

不要只用公共数据集决定最终模型
公共数据集用于预评估、弱点分析和辅助训练
产品判定必须使用 RV1126B 实机拍摄数据
量化校正数据也应以实机拍摄图像为主

21.2 RV1126B 实机拍摄数据采集方案

提高产品精度的关键,是采集产品实际会看到的图像。至少应覆盖以下条件。

条件推荐内容
拍摄距离近距离、中距离、最大工作距离
角度正面、上下倾斜、左右倾斜、斜向拍摄
照明明亮环境、暗光、逆光、反射、局部照明
文字大小大字、普通字、小字、细字
背景白底、彩色背景、食品包装、金属、透明膜、印刷不均
模糊失焦、运动模糊、手持抖动
压缩摄像头输出 JPEG、视频流截帧
安装差异板卡个体差、镜头差、焦距差、隔着外壳拍摄

推荐数量如下。

目的推荐数量
初期验证200~500 张
det 追加训练500 张以上
rec 追加训练crop 图像 5,000 张以上
产品评估1,000 张以上
量化校正实机拍摄图像 200~500 张

实拍图像建议保存为以下目录结构。

datasets/ppocr_product/raw/rv1126b/
├── train/
│ ├── normal/
│ ├── low_light/
│ ├── reflection/
│ ├── blur/
│ └── small_text/
├── eval/
│ ├── normal/
│ ├── low_light/
│ ├── reflection/
│ ├── blur/
│ └── small_text/
└── README.md

22. 标注方案与推荐工具

22.1 推荐标注工具

PaddleOCR 系列模型追加训练时,优先推荐使用 PPOCRLabel。PPOCRLabel 是面向 OCR 的半自动标注工具,可以输出检测标签 Label.txt、识别标签 rec_gt.txt 和识别用裁剪图像 crop_img/

工具用途说明
PPOCRLabelOCR 检测与识别标注最推荐。输出格式接近 PaddleOCR / PaddleX,可同时整理检测和识别数据。
labelme不规则区域或多边形修正适合复杂区域补充标注,但需要转换为 PaddleOCR 格式。
CVAT团队标注适合多人审核、权限管理和质量控制。
自研 Web 工具产品专用工作流适合量产后持续收集误识别样本并回流训练。

PPOCRLabel 安装示例:

Terminal window
conda activate ppocrv6
python -m pip install PPOCRLabel
python -m pip install trash-cli

启动示例:

Terminal window
PPOCRLabel --kie True

启动后打开图像目录,确认并修正检测框和识别文字。完成后务必导出检测用 Label.txt 和识别用 rec_gt.txt

22.2 PPOCRLabel 输出文件

PPOCRLabel 工作目录示例:

datasets/ppocr_product/label_projects/rv1126b_jp_001/
├── images/
│ ├── jp_000001.jpg
│ ├── jp_000002.jpg
│ └── ...
├── Label.txt
├── fileState.txt
├── Cache.cach
├── rec_gt.txt
└── crop_img/
├── jp_000001_crop_0.jpg
├── jp_000001_crop_1.jpg
└── ...

检测标签 Label.txt 每一行保存图像路径和 JSON 格式检测结果。

images/jp_000001.jpg [{"transcription":"後味すっきり","points":[[496,732],[781,732],[781,796],[496,796]],"difficult":false}]

识别标签 rec_gt.txt 每一行保存 crop 图像路径和识别文本。

crop_img/jp_000001_crop_0.jpg 後味すっきり
crop_img/jp_000001_crop_1.jpg とろける

注意事项:

图像路径和标签之间必须使用 tab 分隔
日文标签必须保存为 UTF-8
空格、长音、标点、全角/半角写法需要统一
无法确认的文字不要强行猜测,应标记 difficult 或从训练集中排除

23. 训练用目录结构

PaddleOCR 训练时,不建议直接使用 PPOCRLabel 工作目录,而是整理成检测和识别两个训练目录。

train_data/japanese_ocr/
├── det/
│ ├── images/
│ │ ├── train/
│ │ └── val/
│ ├── train_label.txt
│ └── val_label.txt
├── rec/
│ ├── images/
│ │ ├── train/
│ │ └── val/
│ ├── rec_gt_train.txt
│ └── rec_gt_val.txt
└── dict/
└── ppocr_japanese_product_dict.txt

检测训练标签示例:

images/train/jp_000001.jpg [{"transcription":"後味すっきり","points":[[496,732],[781,732],[781,796],[496,796]],"difficult":false}]

识别训练标签示例:

images/train/jp_000001_crop_0.jpg 後味すっきり

识别字典 ppocr_japanese_product_dict.txt 必须包含所有训练标签中出现的字符。如果基于现有 PP-OCRv6_small_reccharacter_dict,应尽量保持原字符顺序,只谨慎补充缺失字符。改变字符顺序可能破坏已有权重和类别索引之间的对应关系。

24. 从 PPOCRLabel 数据生成训练数据

以下脚本可以从 PPOCRLabel 工作目录生成检测训练标签、识别训练标签和识别字典。该脚本已打包为 training-scripts/prepare_ppocr_dataset.py

Terminal window
python training-scripts/prepare_ppocr_dataset.py \
--ppocrlabel_dir datasets/ppocr_product/label_projects/rv1126b_jp_001 \
--out_dir train_data/japanese_ocr \
--val_ratio 0.1 \
--seed 42

生成后确认:

Terminal window
tree train_data/japanese_ocr -L 3
head -n 3 train_data/japanese_ocr/det/train_label.txt
head -n 3 train_data/japanese_ocr/rec/rec_gt_train.txt
wc -l train_data/japanese_ocr/dict/ppocr_japanese_product_dict.txt

多个标注项目可以一次性合并。

Terminal window
python training-scripts/prepare_ppocr_dataset.py \
--ppocrlabel_dir \
datasets/ppocr_product/label_projects/rv1126b_jp_001 \
datasets/ppocr_product/label_projects/rv1126b_jp_002 \
--out_dir train_data/japanese_ocr \
--val_ratio 0.1

25. 检测模型追加训练

当文字区域位置偏移、多个词被合并、小字漏检时,需要追加训练检测模型。

准备 PaddleOCR 仓库:

Terminal window
mkdir -p third_party
cd third_party
git clone https://github.com/PaddlePaddle/PaddleOCR.git
cd PaddleOCR
python -m pip install -r requirements.txt

确认可用的检测配置文件:

Terminal window
find configs -iname "*det*.yml" | sort | grep -E "OCRv5|OCRv4|OCRv3|DB"

如果当前 PaddleOCR 版本提供 PP-OCRv6 训练配置,则优先使用 PP-OCRv6 配置。若没有,则使用 PP-OCRv5 或 PP-OCRv4 的 DB 检测配置作为 fine-tune 基础。实际配置文件名会随 PaddleOCR 版本变化,因此必须先用 find 确认。

检测训练命令示例:

Terminal window
cd third_party/PaddleOCR
DET_CONFIG=configs/det/PP-OCRv5/PP-OCRv5_server_det.yml \
DATA_ROOT=../../train_data/japanese_ocr \
SAVE_DIR=../../output/train/det_product \
bash ../../training-scripts/train_det.sh

train_det.sh 会主要覆盖:

Global.save_model_dir
Train.dataset.data_dir
Train.dataset.label_file_list
Eval.dataset.data_dir
Eval.dataset.label_file_list
Optimizer.lr.learning_rate

单 GPU 或小数据量 fine-tune 时,学习率建议较小。

初始候选:1e-4
训练不稳定时:5e-5
非常小数据集:1e-5~2e-5

26. 识别模型追加训练

当出现 、长音、平假名/片假名、细字、小字、装饰字体等误识别时,需要追加训练识别模型。

确认可用的识别配置文件:

Terminal window
cd third_party/PaddleOCR
find configs -iname "*rec*.yml" | sort | grep -E "OCRv5|OCRv4|OCRv3|SVTR"

识别模型训练命令示例:

Terminal window
cd third_party/PaddleOCR
REC_CONFIG=configs/rec/PP-OCRv5/PP-OCRv5_server_rec.yml \
DATA_ROOT=../../train_data/japanese_ocr \
SAVE_DIR=../../output/train/rec_product \
DICT_PATH=../../train_data/japanese_ocr/dict/ppocr_japanese_product_dict.txt \
bash ../../training-scripts/train_rec.sh

识别训练的重要参数如下。

项目内容
character_dict_path训练字典,必须包含标签里的所有字符。
use_space_char需要识别空格时启用。
rec_image_shape本项目最终统一为 3,48,320
max_text_length长文本场景需要设置足够大。
学习率追加训练时应设小。

需要注意:本项目当前 PP-OCRv6_small_rec 的输出类别数为 18710。如果大幅改变字典,最终分类层维度会变化,已有权重可能无法直接复用。产品追加训练建议先在既有字典范围内提升精度,确有必要时再扩展字典。

27. 训练后模型评估

训练后必须在 PC 和 RV1126B 两侧评估。

PC 侧评价项目:

det precision / recall / hmean
rec accuracy
end-to-end OCR exact match
字符级正确率
低照度、反射、模糊、小字等条件分组正确率

PaddleOCR 评价命令示例:

Terminal window
cd third_party/PaddleOCR
python tools/eval.py \
-c configs/rec/PP-OCRv5/PP-OCRv5_server_rec.yml \
-o Global.checkpoints=../../output/train/rec_product/best_accuracy

产品评估建议拆分以下数据集:

评估集内容
public_eval从公共数据集构建的评估集
rv1126b_eval_normal正常照明实拍
rv1126b_eval_low_light暗光、低照度
rv1126b_eval_reflection反光、光泽面
rv1126b_eval_blur失焦、运动模糊
rv1126b_eval_small_text小字、远距离

28. 训练模型导出与 RKNN 转换

追加训练后,先导出为 Paddle inference model。

检测模型导出示例:

Terminal window
cd third_party/PaddleOCR
python tools/export_model.py \
-c configs/det/PP-OCRv5/PP-OCRv5_server_det.yml \
-o Global.checkpoints=../../output/train/det_product/best_accuracy \
Global.save_inference_dir=../../models/paddle/product_det

识别模型导出示例:

Terminal window
python tools/export_model.py \
-c configs/rec/PP-OCRv5/PP-OCRv5_server_rec.yml \
-o Global.checkpoints=../../output/train/rec_product/best_accuracy \
Global.save_inference_dir=../../models/paddle/product_rec

然后按照本文档前半部分的流程转换为 ONNX。

Terminal window
paddlex \
--paddle2onnx \
--paddle_model_dir ./models/paddle/product_rec \
--onnx_model_dir ./models/onnx/product_rec \
--opset_version 11

转换为 RV1126B RKNN 时遵守以下原则:

det:使用以实拍图片为主的 dataset 列表做 INT8 量化
rec:先转换为 FP no-softmax,确认可运行和精度
rec 量化:评估精度损失后再决定是否采用

29. 量化校正数据制作

det 的 INT8 量化强依赖校正数据。校正数据必须包含 RV1126B 实拍图片,而不是只使用公共数据集。

推荐结构:

datasets/ppocr_product/calib/
├── normal/
├── low_light/
├── reflection/
├── blur/
└── small_text/

生成 RKNN dataset 文件:

Terminal window
find datasets/ppocr_product/calib -type f \
\( -iname "*.jpg" -o -iname "*.png" \) \
| sort \
| sed "s#^datasets/##" \
> datasets/ppocrv6_product_det_calib.txt

如果 datasets/ppocrv6_product_det_calib.txt 放在 ./datasets/ 下,列表内路径应以 ./datasets/ 为基准,避免出现 datasets/datasets/... 的错误路径。

30. 产品精度改善闭环

产品上线后,应持续回收误识别图像并回流训练。

RV1126B 执行 OCR
保存低置信度、误识别、漏检图像
PPOCRLabel 复核和修正
追加到 train_data
fine-tune det / rec
ONNX / RKNN 转换
实机评估
作为产品模型发布

需要保存的失败样本包括:

检测漏检
多个词合并
文字区域被截断
口 / ロ、日 / 目、ー / 一 等混淆
小字误识别
反光和低照度导致的误识别

31. 本文档完成条件

本文档的完成条件如下。

可以确认公共数据集获取地址
可以使用 PPOCRLabel 创建检测和识别标签
可以从 PPOCRLabel 输出生成 PaddleOCR 训练目录
可以执行 det / rec 追加训练命令
可以导出训练后的 Paddle inference model
可以连接到既有 ONNX / RKNN 转换流程
可以使用 RV1126B 实拍数据进行评估和量化校正

32. 产品开发时的改进项

产品开发时处理:

优先级改进项
1实现 PaddleOCR 标准 DB postprocess
2增加 crop 透视变换和旋转文字处理
3增加识别分数和低置信度过滤
4增加 PPOCRLabel 输出自动质量检查
5自动生成实拍数据评估报告
6将训练模型 ONNX / RKNN 转换流程 CI 化
7生成 INT8 量化前后精度差异报告

33. 参考资料