首发于:https://rapidai.github.io/RapidOCRDocs/latest/blog/2026/06/30/rapidocr-%E9%80%82%E9%85%8D-pp-ocrv6-rec-%E6%A8%A1%E5%9E%8B%E6%94%AF%E6%8C%81-paddle-pytorch-%E5%92%8C-mnn-%E8%AE%B0%E5%BD%95/
引言
rapidocr==3.9.0仅支持 ONNXRuntime 和 OpenVINO 两个推理引擎,PaddlePaddle, PyTorch, MNN 和 TensorRT 打算在下个版本(v3.9.1)都支持了。
本篇文章就是用来记录 RapidOCR PP-OCRv6 Rec 模型支持 PaddlePaddle, PyTorch, MNN 的过程,一是备忘,二是希望帮助需要的小伙伴们。
以下代码运行环境
- OS: macOS Tahoe 26.5.1
- Python: 3.10.14
- PaddlePaddle: 3.1.0
- paddle2onnx: 2.1.0
- paddlex: 3.7.1
- rapidocr: 3.9.0
- MNN: 3.2.5
- OpenVINO: 2026.2.1
- torch: 2.7.0
支持 PaddlePaddle
得益于原始模型就是 PaddlePaddle 格式,因此支持 PaddlePaddle 推理引擎较为容易,加上 @jaminmei 提的 PR #696。我这里做的工作少了许多,由衷地感谢。
importtimeimportcv2importnumpyasnpfromdatasetsimportload_datasetfromtqdmimporttqdmfromrapidocrimportEngineType,OCRVersion,RapidOCR# 依次跑三个规格的模型model_path="modelscope/paddle/PP-OCRv6/rec/PP-OCRv6_rec_medium"dict_path="modelscope/paddle/PP-OCRv6/rec/PP-OCRv6_rec_medium/ppocrv6_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=[]fori,one_datainenumerate(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]iflen(rec_text)<=0:rec_text=""elapse=0gt=one_data.get("label",None)content.append(f"{rec_text}\t{gt}\t{elapse}")withopen("pred.txt","w",encoding="utf-8")asf:forvincontent:f.write(f"{v}\n")fromtext_rec_metricimportTextRecMetric metric=TextRecMetric()pred_path="pred.txt"metric=metric(pred_path)print(metric)最终结果汇总到文章末尾了。
支持 PyTorch
PP-OCRv6 中,PaddleOCR 官方支持 safetensors 格式,支持用 transformers 库推理。经过我的调研,发现 safetensors 格式仅仅是权重,里面并没有具体网络结构。
经过社区小伙伴的提醒,我才发现 PP-OCRv6 已经集成到了 transformers 库了。我本以为这个事情就变得简单了。后来发现 transformers 中集成了很多模型的推理,想要单独抠出 PP-OCRv6 的相关最小可执行代码,太难了。
我这里给出 transformers 库中如何使用 PP-OCRv6 rec 系列模型,代码来自 transformers 模型卡片。
fromioimportBytesIOimporthttpxfromPILimportImagefromtransformersimportAutoImageProcessor,AutoModelForTextRecognitionfromtransformers.image_utilsimportload_image model_path="PaddlePaddle/PP-OCRv6_small_rec_safetensors"model=AutoModelForTextRecognition.from_pretrained(model_path,device_map="auto")image_processor=AutoImageProcessor.from_pretrained(model_path)image_url="https://paddle-model-ecology.bj.bcebos.com/paddlex/imgs/demo_image/general_ocr_rec_001.png"image=load_image(image_url)inputs=image_processor(images=image,return_tensors="pt").to(model.device)outputs=model(**inputs)results=image_processor.post_process_text_recognition(outputs)forresultinresults:print(result)后来发现 PaddleOCR2Pytorch 中已经支持 PP-OCRv6 文本检测和识别模型了。哈哈哈。RapidOCR 之前支持的 PyTorch 推理,其模型都是来自这个仓库。有了这个,剩下工作就是集成和测试一下指标就可以了。感谢大佬的工作。
其中 Rec Tiny 模型,PaddleOCR2Pytorch 中实现的网络结构与 PaddleOCR 官方不同,因此我这里在rapidocr==3.9.1中,PP-OCRV6 Rec Tiny 模型指标效果很差。到现在我已经对齐了,还向 PaddleOCR2Pytorch 提了一个 PR #127。
评测代码:
importcv2importnumpyasnpfromdatasetsimportload_datasetfromtqdmimporttqdmfromrapidocrimportEngineType,ModelType,OCRVersion,RapidOCR model_path="models/PP-OCRv6_det_tiny.pth"engine=RapidOCR(params={"Det.ocr_version":OCRVersion.PPOCRV6,"Det.model_path":model_path,"Det.engine_type":EngineType.TORCH,})dataset=load_dataset("SWHL/text_det_test_dataset")test_data=dataset["test"]content=[]fori,one_datainenumerate(tqdm(test_data)):img=np.array(one_data.get("image"))img=cv2.cvtColor(img,cv2.COLOR_RGB2BGR)ocr_results=engine(img,use_det=True,use_cls=False,use_rec=False)dt_boxes=ocr_results.boxes dt_boxes=[]ifdt_boxesisNoneelsedt_boxes.tolist()elapse=ocr_results.elapse gt_boxes=[v["points"]forvinone_data["shapes"]]content.append(f"{dt_boxes}\t{gt_boxes}\t{elapse}")withopen("pred.txt","w",encoding="utf-8")asf:forvincontent:f.write(f"{v}\n")fromtext_det_metricimportTextDetMetric metric=TextDetMetric()pred_path="pred.txt"metric=metric(pred_path)print(metric)支持 MNN
# 安装pipinstallMNN==3.2.5# 转换MNNConvert-fONNX--modelFilemodelscope/onnx/PP-OCRv6/rec/PP-OCRv6_rec_medium.onnx--MNNModelmodelscope/mnn/PP-OCRv6/rec/PP-OCRv6_rec_medium.mnn--bizCodeMNN MNNConvert-fONNX--modelFilemodelscope/onnx/PP-OCRv6/rec/PP-OCRv6_rec_small.onnx--MNNModelmodelscope/mnn/PP-OCRv6/rec/PP-OCRv6_rec_small.mnn--bizCodeMNN MNNConvert-fONNX--modelFilemodelscope/onnx/PP-OCRv6/rec/PP-OCRv6_rec_tiny.onnx--MNNModelmodelscope/mnn/PP-OCRv6/rec/PP-OCRv6_rec_tiny.mnn--bizCodeMNN测试转换后的模型指标
importtimeimportcv2importnumpyasnpfromdatasetsimportload_datasetfromtqdmimporttqdmfromrapidocrimportEngineType,ModelType,OCRVersion,RapidOCR model_path="modelscope/mnn/PP-OCRv6/rec/PP-OCRv6_rec_tiny.mnn"dict_path="modelscope/paddle/PP-OCRv6/rec/PP-OCRv6_rec_tiny/ppocrv6_tiny_dict.txt"# model_path = "modelscope/torch/PP-OCRv6/rec/PP-OCRv6_rec_small.pth"# dict_path = "modelscope/paddle/PP-OCRv6/rec/PP-OCRv6_rec_small/ppocrv6_dict.txt"# model_path = "modelscope/torch/PP-OCRv6/rec/PP-OCRv6_rec_medium.pth"# dict_path = "modelscope/paddle/PP-OCRv6/rec/PP-OCRv6_rec_small/ppocrv6_dict.txt"engine=RapidOCR(params={"Rec.model_path":model_path,"Rec.rec_keys_path":dict_path,"Rec.ocr_version":OCRVersion.PPOCRV6,"Rec.engine_type":EngineType.MNN,"Rec.model_type":ModelType.TINY,})dataset=load_dataset("SWHL/text_rec_test_dataset")test_data=dataset["test"]content=[]fori,one_datainenumerate(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]iflen(rec_text)<=0:rec_text=""elapse=0gt=one_data.get("label",None)content.append(f"{rec_text}\t{gt}\t{elapse}")withopen("pred.txt","w",encoding="utf-8")asf:forvincontent:f.write(f"{v}\n")fromtext_rec_metricimportTextRecMetric metric=TextRecMetric()pred_path="pred.txt"metric=metric(pred_path)print(metric)最终结果汇总到文章末尾了。
不同推理引擎指标汇总
在这里将 ONNXRuntime, OpenVINO, PaddlePaddle, MNN 和 PyTorch 在 PP-OCRv6 Det 模型上指标和速度都汇总起来了,便于大家选用最合适的。
TensorRT 的指标等有时间再补哈!
各个推理引擎对应不同的模型,最终指标效果如下: