掘金 人工智能 05月31日 18:23
RapidOCR集成PP-OCRv5_rec_mobile模型记录
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文记录了RapidOCR集成PP-OCRv5_mobile_rec和PP-OCRv5_server_rec模型的详细过程,包括模型转换、精度测试以及最终的集成。通过PaddleX和RapidOCR框架,对比了不同模型格式和推理引擎的表现,为用户提供了选择和优化的参考。

🚀 **模型跑通与转换:** 首先,使用PaddleX验证PP-OCRv5_mobile_rec模型的功能,随后利用PaddleX提供的工具将PaddlePaddle模型转换为ONNX格式,为后续在RapidOCR中的应用做准备。

💡 **模型推理验证:** 在RapidOCR项目中测试ONNX模型,验证模型前后处理的兼容性。通过对比PP-OCRv4和PP-OCRv5 mobile det的配置差异,确认现有代码可以直接使用,并进行推理测试。

📊 **精度测试与对比:** 采用TextRecMetric对不同模型和框架组合进行精度测试。测试结果表明,ONNX模型与PaddlePaddle模型精度相近,但推理速度有所提升。同时,PP-OCRv5系列模型在特定场景下表现更优。

🛠️ **集成到RapidOCR:** 将字典文件写入ONNX模型,并修改RapidOCR代码进行适配,最终实现PP-OCRv5模型在RapidOCR框架中的集成。提供了详细的代码示例和操作步骤,方便用户复现。

该文章主要记录RapidOCR集成PP-OCRv5_mobile_rec和PP-OCRv5_server_rec模型记录的,涉及模型转换,模型精度测试等步骤。因公众号一经发表不能更改,详细完整记录请前往官方博客查看:rapidai.github.io/RapidOCRDoc…

引言

来自PaddleOCR官方文档

PP-OCRv5 是PP-OCR新一代文字识别解决方案,该方案聚焦于多场景、多文字类型的文字识别。在文字类型方面,PP-OCRv5支持简体中文、中文拼音、繁体中文、英文、日文5大主流文字类型,在场景方面,PP-OCRv5升级了中英复杂手写体、竖排文本、生僻字等多种挑战性场景的识别能力。在内部多场景复杂评估集上,PP-OCRv5较PP-OCRv4端到端提升13个百分点。

以下代码运行环境

1. 模型跑通

该步骤主要先基于PaddleX可以正确使用PP-OCRv5_mobile_rec模型得到正确结果。

该部分主要参考文档:docs

安装paddlex:

pip install "paddlex[ocr]==3.0.0"

测试PP-OCRv5_mobile_rec模型能否正常识别:

运行以下代码时,模型会自动下载到 /Users/用户名/.paddlex/official_models 下。

测试图:link

from paddlex import create_model# PP-OCRv5_server_rec 同理model = create_model(model_name="PP-OCRv5_mobile_rec")img_path = "images/general_ocr_rec_001.png"output = model.predict(input=img_path, batch_size=1)for res in output:    res.print()    res.save_to_img(save_path="./output/")    res.save_to_json(save_path="./output/res.json")

预期结果如下,表明成功运行:

2. 模型转换

该部分主要参考文档: docs

转换PP-OCRv5_mobile_rec。PaddleX官方集成了paddle2onnx的转换代码:

paddlex --install paddle2onnxpip install onnx==1.16.0paddlex --paddle2onnx --paddle_model_dir models/official_models/PP-OCRv5_mobile_rec --onnx_model_dir models/PP-OCRv5_mobile_rec

输出日志如下,表明转换成功:

Input dir: models/official_models/PP-OCRv5_mobile_recOutput dir: models/PP-OCRv5_mobile_recPaddle2ONNX conversion starting.../Users/xxxx/miniconda3/envs/py310/lib/python3.10/site-packages/paddle/utils/cpp_extension/extension_utils.py:711: UserWarning: No ccache found. Please be aware that recompiling all source files may be required. You can download and install ccache from: <https://github.com/ccache/ccache/blob/master/doc/INSTALL.md>warnings.warn(warning_message)[Paddle2ONNX] Start parsing the Paddle model file...[Paddle2ONNX] Use opset_version = 14 for ONNX export.[Paddle2ONNX] PaddlePaddle model is exported as ONNX format now.2025-05-30 08:16:38 [INFO]      Try to perform constant folding on the ONNX model with Polygraphy.[W] 'colored' module is not installed, will not use colors when logging. To enable colors, please install the 'colored' module: python3 -m pip install colored[I] Folding Constants | Pass 1[I]     Total Nodes | Original:  1029, After Folding:   550 |   479 Nodes Folded[I] Folding Constants | Pass 2[I]     Total Nodes | Original:   550, After Folding:   550 |     0 Nodes Folded2025-05-30 08:16:40 [INFO]      ONNX model saved in models/PP-OCRv5_mobile_rec/inference.onnx.Paddle2ONNX conversion succeededCopied models/official_models/PP-OCRv5_mobile_rec/inference.yml to models/PP-OCRv5_mobile_rec/inference.ymlDone

3. 模型推理验证

验证PP-OCRv5_mobile_rec模型

该部分主要是在RapidOCR项目中测试能否直接使用onnx模型。要点主要是确定模型前后处理是否兼容。从PaddleOCR config文件中比较PP-OCRv4PP-OCRv5 mobile det文件差异:

从上图中可以看出,配置基本一模一样,因此现有rapidocr前后推理代码可以直接使用。

from rapidocr import RapidOCRmodel_path = "models/PP-OCRv5_mobile_rec/inference.onnx"dict_path = "models/PP-OCRv5_mobile_rec/ppocrv5_dict.txt"engine = RapidOCR(params={"Rec.model_path": model_path, "Rec.rec_keys_path": dict_path})img_url = "<https://img1.baidu.com/it/u=3619974146,1266987475&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=516>"result = engine(img_url)print(result)result.vis("vis_result.jpg")

4. 模型精度测试

测试集text_det_test_dataset包括卡证类、文档类和自然场景三大类。其中卡证类有82张,文档类有75张,自然场景类有55张。缺少手写体、繁体、日文、古籍文本、拼音、艺术字等数据。因此,该基于该测评集的结果仅供参考。

欢迎有兴趣的小伙伴,可以和我们一起共建更加全面的测评集。

该部分主要使用TextRecMetric和测试集text_rec_test_dataset来评测。

需要注意的是,PP-OCRv5_rec系列模型更加侧重一个模型解决简体中文、中文拼音、繁体中文、英文、日文5大主流文字类型,在场景方面,PP-OCRv5升级了中英复杂手写体、竖排文本、生僻字等多种挑战性场景。 当前测试集并未着重收集以上场景。因此以下指标会有些偏低。如需自己使用,请在自己场景下测试效果。

相关测试步骤请参见TextRecMetric的README,一步一步来就行。

⚠️注意:下面代码用的是即将发布rapidocr==3.0.0版本代码,想要复现的小伙伴,可以稍微等等。

其中,下面代码仅写了mobile模型测试,如果想测server模型,将 mobile 字段换为 server 即可。计算 pred.txt 代码如下:

(Exp1) PaddleX框架+Paddle格式模型

import timeimport cv2import numpy as npfrom datasets import load_datasetfrom tqdm import tqdmfrom paddlex import create_modelengine = create_model(model_name="PP-OCRv5_mobile_rec")dataset = load_dataset("SWHL/text_rec_test_dataset")test_data = dataset["test"]content = []for i, one_data in enumerate(tqdm(test_data)):    img = np.array(one_data.get("image"))    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)    t0 = time.perf_counter()    result = next(engine.predict(input=img, batch_size=1))    elapse = time.perf_counter() - t0    rec_text = result["rec_text"]    if len(rec_text) <= 0:        rec_text = ""        elapse = 0    gt = one_data.get("label", None)    content.append(f"{rec_text}\t{gt}\t{elapse}")with open("pred.txt", "w", encoding="utf-8") as f:    for v in content:        f.write(f"{v}\n")

(Exp2)RapidOCR框架+Paddle格式模型

import timeimport cv2import numpy as npfrom datasets import load_datasetfrom tqdm import tqdmfrom rapidocr import EngineType, OCRVersion, RapidOCRmodel_path = "models/official_models/PP-OCRv5_mobile_rec"dict_path = "models/PP-OCRv5_mobile_rec/ppocrv5_dict.txt"engine = RapidOCR(    params={        "Rec.model_dir": model_path,        "Rec.rec_keys_path": dict_path,        "Rec.engine_type": EngineType.PADDLE,        "Rec.ocr_version": OCRVersion.PPOCRV5,    })dataset = load_dataset("SWHL/text_rec_test_dataset")test_data = dataset["test"]content = []for i, one_data in enumerate(tqdm(test_data)):    img = np.array(one_data.get("image"))    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)    t0 = time.perf_counter()    result = engine(img, use_rec=True, use_cls=False, use_det=False)    elapse = time.perf_counter() - t0    rec_text = result.txts[0]    if len(rec_text) <= 0:        rec_text = ""        elapse = 0    gt = one_data.get("label", None)    content.append(f"{rec_text}\t{gt}\t{elapse}")with open("pred.txt", "w", encoding="utf-8") as f:    for v in content:        f.write(f"{v}\n")

(Exp3)RapidOCR框架+ONNXRuntime格式模型

import timeimport cv2import numpy as npfrom datasets import load_datasetfrom tqdm import tqdmfrom rapidocr import EngineType, OCRVersion, RapidOCRmodel_path = "models/PP-OCRv5_mobile_rec/inference.onnx"dict_path = "models/PP-OCRv5_mobile_rec/ppocrv5_dict.txt"engine = RapidOCR(    params={        "Rec.model_path": model_path,        "Rec.rec_keys_path": dict_path,    })dataset = load_dataset("SWHL/text_rec_test_dataset")test_data = dataset["test"]content = []for i, one_data in enumerate(tqdm(test_data)):    img = np.array(one_data.get("image"))    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)    t0 = time.perf_counter()    result = engine(img, use_rec=True, use_cls=False, use_det=False)    elapse = time.perf_counter() - t0    rec_text = result.txts[0]    if len(rec_text) <= 0:        rec_text = ""        elapse = 0    gt = one_data.get("label", None)    content.append(f"{rec_text}\t{gt}\t{elapse}")with open("pred.txt", "w", encoding="utf-8") as f:    for v in content:        f.write(f"{v}\n")

计算指标代码:

from text_rec_metric import TextRecMetricmetric = TextRecMetric()pred_path = "pred.txt"metric = metric(pred_path)print(metric)

指标汇总如下(以下指标均为CPU下计算所得):

Exp模型推理框架模型格式ExactMatch↑CharMatch↑Elapse↓
1PP-OCRv5_mobile_recPaddleXPaddlePaddle0.73230.91610.0778
2PP-OCRv5_mobile_recRapidOCRPaddlePaddle0.73550.91770.0772
3PP-OCRv5_mobile_recRapidOCRONNXRuntime0.73550.91770.0174
4PP-OCRv4_mobile_recRapidOCRONNXRuntime0.83230.9355-
5PP-OCRv5_server_recPaddleXPaddlePaddle0.80970.94240.0777
6PP-OCRv5_server_recRapidOCRPaddlePaddle0.81290.94310.0775
7PP-OCRv5_server_recRapidOCRONNXRuntime0.81290.94310.0655
8PP-OCRv4_server_recRapidOCRONNXRuntime0.79680.9381-
9PP-OCRv4_doc_server_recRapidOCRONNXRuntime0.80980.9444-

从以上结果来看,可以得到以下结论:

    Exp1和Exp2相比,指标差异不大,说明文本识别 前后处理代码可以共用 。Exp2和Exp3相比,mobile模型转换为ONNX格式后,指标几乎一致,说明 模型转换前后,误差较小,推理速度也有提升 。Exp3和Exp4相比,mobile整体指标弱于PP-OCRv4的。因为测评集集中在中英文的印刷体,手写体少些,因此仅供参考。Exp6和Exp7相比,指标差异不大,说明更换backbone后的文本识别模型转换为ONNX格式,精度没有影响。Paddle2ONNX工具太强了!Exp7和Exp8相比,PP-OCRv5 server模型有很大提升。当然,不排除训练用到了测评集数据。

最终建议:

上述表格中基于ONNXRuntime的结果已经更新到开源OCR模型对比中。

5. 集成到rapidocr中

该部分主要包括将字典文件写入ONNX模型、托管模型到魔搭和更改rapidocr代码适配等。

字典文件写入ONNX模型

该步骤仅存在文本识别模型中,文本检测模型没有这个步骤。

详细代码:

from pathlib import Pathfrom typing import List, Unionimport onnximport onnxruntime as ortfrom onnx import ModelProtodef read_txt(txt_path: Union[Path, str]) -> List[str]:    with open(txt_path, "r", encoding="utf-8") as f:        data = [v.rstrip("\n") for v in f]    return dataclass ONNXMetaOp:    @classmethod    def add_meta(        cls,        model_path: Union[str, Path],        key: str,        value: List[str],        delimiter: str = "\n",    ) -> ModelProto:        model = onnx.load_model(model_path)        meta = model.metadata_props.add()        meta.key = key        meta.value = delimiter.join(value)        return model    @classmethod    def get_meta(        cls, model_path: Union[str, Path], key: str, split_sym: str = "\n"    ) -> List[str]:        sess = ort.InferenceSession(model_path)        meta_map = sess.get_modelmeta().custom_metadata_map        key_content = meta_map.get(key)        key_list = key_content.split(split_sym)        return key_list    @classmethod    def del_meta(cls, model_path: Union[str, Path]) -> ModelProto:        model = onnx.load_model(model_path)        del model.metadata_props[:]        return model    @classmethod    def save_model(cls, save_path: Union[str, Path], model: ModelProto):        onnx.save_model(model, save_path)dicts = read_txt("models/PP-OCRv5_mobile_rec/ppocrv5_dict.txt")model_path = "models/PP-OCRv5_server_rec/inference.onnx"model = ONNXMetaOp.add_meta(model_path, key="character", value=dicts)new_model_path = Path(model_path).parent / "ch_PP-OCRv5_rec_server_infer.onnx"ONNXMetaOp.save_model(new_model_path, model)t = ONNXMetaOp.get_meta(new_model_path, key="character")print(t)print(len(t))

托管模型到魔搭

该部分主要是涉及模型上传到对应位置,并合理命名。注意上传完成后,需要打Tag,避免后续rapidocr whl包中找不到模型下载路径。

我这里已经上传到了魔搭上,详细链接参见:link

更改rapidocr代码适配

该部分主要涉及到更改default_models.yamlpaddle.py的代码来适配。

同时,需要添加对应的单元测试,在保证之前单测成功的同时,新的针对性该模型的单测也能通过。

我这里已经做完了,小伙伴们感兴趣可以去看看源码。

写在最后

至此,该部分集成工作就基本完成了。这部分代码会集成到rapidocr==3.0.0中。

版本号之所以从v2.1.0到v3.0.0,原因是:语义化版本号。我在集成过程中,发现v2.1.0中字段不太合理,做了一些改进,动了外部API,因此只能升大版本号。请大家在使用过程中,注意查看最新文档→ docs

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

RapidOCR PP-OCRv5 模型转换 精度测试
相关文章