拓冰建站拓冰建站
首页 / 资讯中心 / 正文

PaddleOCR实战指南:从环境搭建到自定义模型训练全流程

1. 为什么又是PaddleOCR一次选型思考与全景认知1.1 先说一个真实场景一堆证件照要全部提取关键信息我在做某个内部系统的时候接到过这样一个需求每天有上千张表格、票据、证件照片需要录入系统字段还特别规整就是姓名、身份证号、地址、金额这种。一开始大家想的是找商业OCR API但数据不能出内网这一条就毙掉了所有云端方案又试了开源的Tesseract结果大家在中文场景下应该都懂识别率惨不忍睹尤其是带点倾斜、光照不均匀的票据基本就是灾难。后来同事建议试试PaddleOCR我当时的反应是又一个深度学习全家桶估计部署起来要折腾半天。但实际用下来PaddleOCR确实把中文OCR这个事做到了开箱即用——从环境搭建、模型推理到自定义训练整套链路是完整的。这篇实战指南就围绕我踩过的坑和验证过的路径来写目标是让一个从没碰过PaddleOCR的人也能从零搭好环境、跑起推理、训出自己的模型。1.2 PaddleOCR到底做对了什么检测、方向分类、识别三段式要理解PaddleOCR的架构先要理解一个核心观点OCR不是单任务而是流水线。PaddleOCR把文字识别拆成了三个独立组件文本检测Detection先从图片里找出哪里有文字输出的是文本框坐标。对应PaddleOCR里的PP-OCRv4_det这类模型。方向分类Classification判断检测出来的文本区域是不是旋转了比如手机拍的照片是90度、180度颠倒的如果是就转正。对应PP-OCRv4_cls。文本识别Recognition把转正后的文本区域图像映射成字符串。对应PP-OCRv4_rec。为什么拆开而不是做成一个端到端模型原因很实际每个子任务独立优化、独立替换。在真实项目里你的文字检测可能很准但识别模型认不出特定字体或者识别模型很强大但检测把文字区域切碎了。三段式设计让你可以只重新训练其中一个环节其余保持不动这在工程上是非常务实的取舍。1.3 同场对比Tesseract、EasyOCR、PaddleOCR怎么选选型阶段我做了一张对比表这里直接分享给大家维度TesseractEasyOCRPaddleOCR中文识别精度一般需要大量调参尚可依赖PyTorch很高尤其在印刷体和自然场景环境安装难度低但依赖系统库中PyTorch环境中高PaddlePaddle框架需单独装自定义模型训练困难训练链路老旧不太友好完整配置文件驱动部署能力轻量适合简单场景一般支持Paddle Inference、ONNX、Android端侧社区活跃度一般一般高中文资料多如果你只是偶尔识别几张图EasyOCR够用如果追求极致的轻量部署Tesseract也不是不能忍。但如果你要处理中文为主的真实业务数据还要考虑后续精度不够时自己训模型PaddleOCR是综合成本最低的选项。2. 环境搭建全记录CPU版十分钟跑通GPU版三步一个坑2.1 创建独立环境尽量别在纯净环境硬装我第一次装PaddleOCR的时候直接往服务器的主Python环境里pip install paddlepaddle结果跟已有的TensorFlow冲突得一塌糊涂。后来学乖了统一用conda建独立环境这一步强烈建议不要跳过。conda create -n paddle python3.9 -y conda activate paddlePython版本建议选3.9或3.10PaddlePaddle对这两个版本的支持最稳。3.11不是不行但有些依赖编译容易出问题。装完之后先别急着装PaddleOCR本体先把PaddlePaddle框架装对这一步决定了后面所有的运行体验。2.2 CPU版与GPU版安装两条命令的区别与验证CPU版本最简单直接一条命令pip install paddlepaddle2.6.1GPU版本就要多花点心思了。PaddlePaddle的GPU版本需要和本机的CUDA版本对应。很多人一上来就pip install paddlepaddle-gpu装完进Python一跑发现提示找不到CUDA库其实大概率是版本不匹配。我的做法是先用nvidia-smi查看本机支持的CUDA版本比如显示CUDA Version: 11.8那就装对应的2.5.x或2.6.x版本# CUDA 11.8 对应 pip install paddlepaddle-gpu2.6.1 -i https://www.paddlepaddle.org.cn/packages/stable/cu118/装完验证这一步很关键别直接去跑OCR先确认框架本身工作正常import paddle paddle.utils.run_check()如果看到PaddlePaddle is installed successfully!框架就没问题了。如果卡住或者报错多半是CUDA和cuDNN版本不匹配。个人经验PaddlePaddle的GPU版比PyTorch的GPU版对版本更敏感实在搞不定就退而求其次用CPU版跑推理速度慢点但至少不会卡住整个项目。2.3 安装PaddleOCR版本锁定避免魔改框架装好之后安装PaddleOCR本体pip install paddleocr2.7.3这里强调一下版本锁定的重要性。PaddleOCR的API在2.x版本里有过不少调整网上很多教程是1.x时代的写法比如ocr.ocr(img_path)和2.x的ocr.predict()参数完全不同。如果你照着老教程写代码会碰到一堆莫名其妙的报错。安装完成后可以用一个极简脚本验证全链路from paddleocr import PaddleOCR ocr PaddleOCR(use_angle_clsTrue, langch, show_logFalse) result ocr.predict(test.jpg) print(result)第一次运行会自动下载检测、方向分类、识别三个模型网络慢的话会卡一阵。这里有个小技巧可以在命令行先手动指定下载目录或者直接去官网模型库把三个模型下载好放到本地目录再用det_model_dir、rec_model_dir、cls_model_dir参数指定避免每次初始化都去拉模型。3. 推理模型的选择逻辑训练模型、推理模型、预训练模型别搞混3.1 三种模型文件的本质区别这是我在PaddleOCR里踩过最大的坑也是新手最容易懵的地方。PaddleOCR有自己的训练框架训练过程中产出的是训练模型.pdparams和.pdopt这种模型不能直接用于部署推理要部署得先导出为推理模型inference.pdmodel和inference.pdiparams。打开PaddleOCR的模型库你会发现每个任务都有两种下载链接预训练模型pretrained model在公开数据集上训好的参数用来做微调fine-tune的起点。推理模型inference model导出后的部署格式直接用Paddle Inference引擎加载。刚开始用的时候我图省事直接下载了预训练模型然后想着用加载普通模型的paddle.jit.load方式去加载结果各种报错。后来才明白PaddleOCR的predict接口默认加载的是推理模型目录不是训练模型。3.2 核心API调用范式从init到predictPaddleOCR 2.7版本里推荐用predict方法替代老版本的ocr方法原因有两个一是predict支持批量推理性能更好二是返回值结构更清晰是OCRResult对象的列表。from paddleocr import PaddleOCR ocr PaddleOCR( det_model_dir./inference/ch_PP-OCRv4_det_infer/, rec_model_dir./inference/ch_PP-OCRv4_rec_infer/, cls_model_dir./inference/ch_ppocr_mobile_v2.0_cls_infer/, use_angle_clsTrue, langch, use_gpuTrue, show_logFalse ) result ocr.predict(./imgs/demo.jpg) for res in result: res.print() res.save_to_img(./output/result.jpg)use_angle_cls这个参数对应方向分类模块的开关。在识别手机拍摄的照片、扫描件时建议打开因为图片很可能是旋转的但如果你的图片本来就是程序生成的比如截图可以关掉能省下不少推理时间。这个细节很多人不注意但其实对精度和速度都有影响。3.3 加速与精度权衡能改的几个关键参数除了模型本身PaddleOCR推理时的参数配置也值得花时间调det_db_thresh检测阶段的二值化阈值默认0.3。这个值调小检测出的文本框会变多召回率提升但误检也可能增加调大则相反。det_db_box_thresh文本框筛选阈值默认0.6。如果检测出的框有大量背景可以适当调高。drop_score识别结果置信度阈值识别分数低于该值的会被丢弃。处理模糊图片时可以调低一点避免结果被过滤掉。rec_batch_num识别阶段的批大小GPU显存充足时可以提高例如设为6或8能显著加速批量推理。有个常见问题推理结果乱码或者大量空白这时候先看检测阶段出来的框对不对而不是直接调识别模型。你可以单独把检测结果可视化出来看框是不是歪的、是不是把背景也框进去了再决定下一步怎么调。这个排查思路比盲目改参数高效得多。4. 文字识别乱码与精度问题排查一份可复现的清单4.1 乱码的根因多数不在识别模型而在上游两个环节PaddleOCR文字识别乱码是很多人在搜索框里敲过的问题。我接过的咨询也不少其中百分之七八十的乱码问题根源不在识别模型本身而在检测或方向分类环节。举一个典型例子有张表格图片检测模块把一行文字切成了好几块识别模块拿到的就是半个字半个词拼出来的结果自然就是乱码。这种情况你去换更强的识别模型也白搭应该先优化检测。再比如图像竖向排版检测出来的文本框方向不对识别模型拿到的对象是旋转的结果也是乱七八糟。4.2 排查链路三步定位问题环节我总结的三步排查法照着做基本能定位到90%的问题第一步跑一次完整OCR打印中间结果。不要只听最终输出用ocr.predict返回的res对象里面包含了每个文本框的坐标和识别结果。先人眼检查框的位置是否精确贴合文字行。第二步跳过识别单独看检测和方向分类输出。PaddleOCR允许你单独执行ocr.predict(inputimg, methoddet)或methodrec。先用methoddet看检测框再用methodcls看方向分类后的图像最后才轮到methodrec。走到这一步基本能判断是哪个环节在捣乱。第三步检查图像预处理是否合理。一张分辨率只有200px的图片人眼看都费劲模型能识别出什么PaddleOCR内部虽然会做缩放但过小的分辨率丢失的信息是无法恢复的。通常建议图片文字区域的最小边不低于32像素分辨率过低就先做超分或者换原始图。4.3 实测案例一份扫描件识别结果全乱我之前处理过一批A4扫描件文字本身非常清晰但PaddleOCR识别的结果里中文全乱数字和英文却正确。这个现象很典型——说明识别模型工作正常只是中文语言模型没生效或者被输入图像误导了。排查过程里我先打印了检测框发现每个框只框住了单个文字而不是整行文字。也就是说检测模型把一行字拆成了二十多个单字框。检查原始扫描件发现文字间距特别大最终通过调整检测算法的参数把文本框聚合的阈值改了一下问题解决。这个案例说明一个道理中文场景下检测模块倾向于按连通域找到每个独立的字要注意设置好文本行聚合策略。PaddleOCR在检测后处理中有文本线构造逻辑det_db_unclip_ratio这个参数控制检测框向外扩展的比例适当增大可以帮相邻文字连成一个整体减小被切断的概率。4.4 多语言和特殊字体的处理PaddleOCR的语言参数lang选择ch时识别模型大概率是中文英文混合的。如果你主要识别纯英文建议换成en模型速度和精度都会有改善。如果识别的是繁体中文建议用chinese_cht日文、韩文也各有对应模型不需要自己训。还有一类容易出问题的是艺术字体比如海报上带描边、阴影的字。这种场景下识别模型性能下降是正常的。我的建议是先用常规模型跑对置信度低的区域做针对性处理比如图像增强再拿这些困难样本去微调识别模型而不是一开始就挑战极限场景。5. 自定义模型训练全流程从数据准备到导出部署5.1 数据准备与标注训练效果的分水岭如果现有的PP-OCR系列模型无法满足你的场景就该考虑自定义训练了。训练的第一件事不是调参是准备数据。PaddleOCR的训练数据分为两块检测数据和识别数据两者独立训练。检测数据标注格式如下PaddleOCR的det标注格式为[polygon] [transcription] [difficult]img_1.jpg [{transcription: 某某公司, points: [[45, 153], [178, 153], [178, 207], [45, 207]]}, ...]识别数据更简单每行是图片路径 标签文本img_001.jpg 某某公司 img_002.jpg 2024年度财务报表标注工具推荐PPOCRLabel它是PaddleOCR官方配套的标注工具安装很简单pip install PPOCRLabel PPOCRLabel --lang ch标注工作量很大但这里有一个经验不要追求一次性把所有数据都标完先标一两百张跑通训练流程再考虑扩数据。全流程跑通后你会更清楚哪些数据需要重点补哪些类别其实已经够了。5.2 配置文件改动关键就那几个字段PaddleOCR的训练基于YAML配置文件官方仓库在configs/det和configs/rec目录下分别有对应的配置模板。以识别模型ch_PP-OCRv4_rec.yml为例需要改动的地方是Global: epoch_num: 100 use_gpu: true save_model_dir: ./output/rec_ppocrv4/ pretrained_model: ./pretrain_models/ch_PP-OCRv4_rec_train/best_accuracy character_dict_path: ./ppocr/utils/ppocr_keys_v1.txt Train: dataset: name: SimpleDataSet data_dir: ./train_data/rec/ label_file_list: - ./train_data/rec/train.txt transforms: - RecAug: {} Eval: dataset: name: SimpleDataSet data_dir: ./train_data/rec/ label_file_list: - ./train_data/rec/eval.txtpretrained_model指向官方预训练模型的目录这是微调的关键在通用模型基础上训练收敛速度快得多精度也更高。character_dict_path是字符表路径如果你的业务里有特殊字符比如单位符号、生僻字需要在这个字典文件里追加。RecAug是数据增强开着有助于提升泛化但会拖慢训练速度。5.3 启动训练、评估与导出命令虽短坑不少配置改好后训练命令其实就一行python tools/train.py -c configs/rec/ch_PP-OCRv4_rec.yml评估python tools/eval.py -c configs/rec/ch_PP-OCRv4_rec.yml -o Global.checkpoints./output/rec_ppocrv4/best_accuracy模型导出python tools/export_model.py -c configs/rec/ch_PP-OCRv4_rec.yml -o Global.pretrained_model./output/rec_ppocrv4/best_accuracy Global.save_inference_dir./inference/rec_custom命令本身不复杂但有几个坑值得提醒数据集路径用相对路径别用绝对路径除非你确定团队里所有人的目录结构一模一样。否则换台机器跑就要改配置麻烦得很。训练日志里看loss和acc不要只看loss。loss下降不代表识别准确率在提升必须同时看eval阶段的准确率。显存溢出时先减小batch_size不要先调模型结构。batch_size调小后学习率也可以按比例调低这在训练里是常规操作。5.4 导出模型和PaddleOCR推理的衔接训练好的模型导出为推理模型后就可以直接替换掉官方下载的推理模型。把inference/rec_custom目录路径传给PaddleOCR的rec_model_dir就行。这里有一个很容易踩的坑导出位置和名称。导出的模型文件默认叫inference.pdmodel和inference.pdiparamsPaddleOCR会去指定目录里找这两个文件。如果你自己改了文件名或者目录层级不对推理时就会报无法找到模型文件之类的错。另外一个提醒字符字典必须保持一致。训练时改过character_dict_path的话推理时也必须用同一份字典。否则模型输出的是字符表里的索引但解析时按另一份字典去查结果一定是乱的。6. 训练与推理的进阶建议一些少有人提的经验6.1 检测和识别模型的配合关系很多人在自定义训练时把精力全放在识别模型上忽略了检测模型。但实际业务中检测框的位置直接决定了识别模型的输入质量。如果检测框把一句话拦腰截断识别模型再强也没用。建议训练时同时微调检测模型不要只训识别。尤其是票据、证件这种结构固定的图片检测模型的提升往往比识别模型更明显。6.2 用PaddleOCR的批处理能力提升效率在实际业务中OCR往往不是单张图片处理而是批量跑。predict接口支持传入图片目录results ocr.predict(./imgs/) for res in results: res.print()它会自动读取目录下所有图片并批量推理。这里注意它会递归查找子目录如果目录里有非图片文件可能会报错建议目录里只放待识别的图片。批处理配合rec_batch_num参数调整吞吐量能提升不少。6.3 常见报错速查表我把工作中经常碰到的报错整理成一张表能省掉不少排查时间报错信息大概率原因解决方案CUDA error: no kernel image availableGPU驱动与CUDA版本不匹配重装匹配版本的paddlepaddle-gpulibdevice not foundCUDA安装不完整设置FLAGS_cudnn_deterministicTrue或重装CUDACannot find inference.pdmodel推理模型文件路径不对检查_model_dir目录内容确认文件名正确KeyError: rec传入的模型类型与目录不匹配确认目录中是识别模型而不是检测模型Out of memory显存不足减小batch_size或rec_batch_numUnknown character字典文件中缺少该字符在字典中追加字符后重新训练6.4 模型量化与裁剪的简单思路当模型部署到手机或边缘设备时体积和推理速度就是硬指标。PaddleOCR提供了PaddleSlim工具集做量化裁剪但操作门槛偏高。我的建议是先把PP-OCRv4的mobile系列模型用起来它们是专门为端侧优化过的轻量模型如果精度不够再考虑用Slim做量化训练。另外tools/infer/predict_system.py的参数里有个use_fp16开启FP16推理可以显著提速代价是精度轻微下降适合对实时性要求高的场景。实测在GPU上能提速将近一倍多数场景下精度损失可接受。7. 实战后的几点内心话7.1 先跑通再优化别一上来就想训模型这条建议放在最后说是因为它最重要。很多新手走了一条弯路环境装到一半GPU版本配不明白就开始想训练自定义模型。其实PaddleOCR官方预训练模型在大量通用场景下已经够用先用官方模型跑通业务把检测、识别、方向分类的中间结果可视化出来找出精度瓶颈到底在哪一个环节再决定要不要训练——这才是最高效的路径。7.2 数据和标注的质量决定训练的上限我训练过两版识别模型第一版用500张自动生成的合成图片效果在测试集上表现尚可一到真实场景就掉链子第二版加了200张真实验收困难样本效果直接上了一个台阶。深度学习的通用规律在这里体现得淋漓尽致数据质量比模型大小重要真实样本比合成样本重要。7.3 保持简单别过度设计PaddleOCR的组件化和插件化设计很容易让人产生再加一个模型效果会不会更好的冲动。但在生产环境里每多一个环节就多一个故障点。实测下来干净图像用检测识别就够了只有旋转图像才需要开方向分类特定的字体或场景问题优先用图像预处理解决实在不行再走自定义训练路线。这套思路帮我省下了大量不值得花的调参时间建议你也试试。延续这个先简单后复杂的思路最后分享一个小技巧在模型迭代过程中始终保留一版固定的评估集三五百张代表性图片每次训练完先在评估集上跑一遍对比准确率变化再决定是否替换线上模型。这个习惯帮我避免了好几次新模型在测试集上提升了、线上却变差了的尴尬情况成本极低收益却非常大。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门