PaddleOCR 二次开发实战从零添加一个新算法模块数据、网络、后处理、损失、指标、优化器全链路指南【免费下载链接】PaddleOCRTurn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between images/PDFs and LLMs. Supports 100 languages.项目地址: https://gitcode.com/GitHub_Trending/pa/PaddleOCRPaddleOCR 将 OCR 算法按照数据加载与处理、网络、后处理、损失函数、指标评估、优化器六个环节进行模块化拆分每个环节都可以独立替换与组合从而以较低成本拼装出新的算法。本文以 docs/version2.x/algorithm/add_new_algorithm.md 为骨架结合当前仓库的源码实现与真实配置文件完整讲解在每个环节中新增自定义模块的步骤、代码范式与配置接入方式帮助读者掌握 PaddleOCR 二次开发的完整链路。适用前提本文针对仓库根目录下的ppocr/训练框架version2.x 算法文档对应的 PaddleOCR 训练代码新增模块均为训练流程中可插拔的 Python 组件通过 YAML 配置驱动实例化。1. 模块化设计总览一个算法在 PaddleOCR 中如何被拆解PaddleOCR 将一个算法从数据处理到模型训练分解为六个独立部分各部分解耦、可单独替换环节目录职责内置算法示例数据加载和处理ppocr/data图片读取、数据增强、label 制作DecodeImage、RecAug、MakeShrinkMap 等网络ppocr/modeling组网按 transforms→backbones→necks→heads 顺序执行DB、EAST、SAST、CRNN、Attention 相关模块后处理ppocr/postprocess解码网络输出得到文本框或识别文字DBPostProcess、CTCLabelDecode 等损失函数ppocr/losses计算网络输出与 label 的距离DBLoss、CTCLoss、AttentionLoss 等指标评估ppocr/metrics计算模型在当前 batch 上的性能DetMetric、RecMetric、ClsMetric 等优化器ppocr/optimizer训练网络内含学习率衰减与正则化Momentum、Adam、RMSProp 等从源码结构看训练框架在 tools/train.py 中通过各环节的build_*工厂函数将 YAML 配置逐段解析成实际对象。本文后续各节将按新增模块三步走的统一范式展开新建文件 → 实现类 → 在__init__.py中注册最后在配置文件中接入。2. 数据加载和处理新增数据增强 / label 变换模块数据处理由不同的 module 顺序组合而成负责图片读取、数据增强和 label 制作代码位于 ppocr/data。目录结构说明如下ppocr/data/ ├── imaug # 图片的读取、数据增强和label制作相关的文件 │ ├── label_ops.py # 对label进行变换的modules │ ├── operators.py # 对image进行变换的modules │ ├── ...... ├── __init__.py ├── lmdb_dataset.py # 读取lmdb数据集的dataset └── simple_dataset.py # 读取以 image_path\tgt 形式保存的数据集的dataset仓库内置了大量图像与 label 操作模块如DecodeImage、DetLabelEncode、RecAug、MakeBorderMap、MakeShrinkMap、KeepKeys等均可在 ppocr/data/imaug/init.py 中查看到完整注册列表。对于未内置的模块按以下步骤添加步骤 1新建模块文件。在 ppocr/data/imaug 文件夹下新建文件如my_module.py。步骤 2实现模块类。一个数据模块是输入 dict、输出 dict的可调用对象核心约定是从data字典中取出image、label处理后写回class MyModule: def __init__(self, *args, **kwargs): # your init code pass def __call__(self, data): img data[image] label data[label] # your process code data[image] img data[label] label return data步骤 3注册模块。在 ppocr/data/imaug/init.py 中导入新增模块。配置接入。数据处理的所有步骤以列表形式在配置文件的transforms字段中按顺序执行。真实配置见 configs/det/det_mv3_db.yml 中Train.dataset.transforms的写法接入自定义模块只需在列表中追加一项# angle class data process transforms: - DecodeImage: # load image img_mode: BGR channel_first: False - MyModule: args1: args1 args2: args2 - KeepKeys: keep_keys: [ image, label ] # dataloader will return list in this order从 ppocr/data/imaug/init.py 的create_operators实现可以看到其底层机制配置项被解析为一个 dict 只含一个键名的算子列表键名即模块类名通过eval(op_name)(**param)动态实例化随后transform(data, ops)依次把data传入每个算子并透传结果。因此新增模块的类名必须与配置中的键名严格一致且__call__必须返回 dict返回None会中断该样本的流水线。另外KeepKeys决定了 dataloader 最终返回的字段顺序训练与评估时请根据实际需要调整keep_keys。3. 网络新增 Transform / Backbone / Neck / Head 模块网络部分完成组网操作代码位于 ppocr/modeling。进入网络的数据将按照transforms → backbones → necks → heads的顺序依次通过四个部分├── architectures # 网络的组网代码 ├── transforms # 网络的图像变换模块 ├── backbones # 网络的特征提取模块 ├── necks # 网络的特征增强模块 └── heads # 网络的输出模块PaddleOCR 内置了 DB、EAST、SAST、CRNN 和 Attention 等算法相关的常用模块。四个部分的添加步骤完全一致下面以 backbones 为例步骤 1在 ppocr/modeling/backbones 文件夹下新建文件如my_backbone.py。步骤 2实现继承自paddle.nn.Layer的网络模块import paddle import paddle.nn as nn import paddle.nn.functional as F class MyBackbone(nn.Layer): def __init__(self, *args, **kwargs): super(MyBackbone, self).__init__() # your init code self.conv nn.xxxx def forward(self, inputs): # your network forward y self.conv(inputs) return y步骤 3在 ppocr/modeling/backbones/init.py 中导入新增模块。配置接入。四部分模块添加完成后在配置文件的Architecture段中分别指定即可Architecture: model_type: rec algorithm: CRNN Transform: name: MyTransform args1: args1 args2: args2 Backbone: name: MyBackbone args1: args1 Neck: name: MyNeck args1: args1 Head: name: MyHead args1: args1从源码角度补充两点关键约束model_type决定可用的 backbone 集合。ppocr/modeling/backbones/init.py 中的build_backbone(config, model_type)按det/table、rec/cls、e2e、kie等model_type分别维护support_dict配置中的name必须存在于当前model_type对应的支持列表中否则会抛出断言异常。因此新增的 backbone 不仅要注册导入还应确认其适用的任务类型。通道数沿流水线自动传递。ppocr/modeling/architectures/base_model.py 中的BaseModel按序构建四段模块并将上一段的out_channels自动注入下一段的in_channels各段均可选配置为None时跳过例如检测与分类任务通常不使用 Transform识别任务可选用 TPS 等变换。此外从该文件forward的实现可以看出Head会被传入targetsdata以支持训练阶段对中间层输出的蒸馏等需求网络输出既可以是 Tensor也可以是包含多分支输出的 dict。4. 后处理新增解码模块后处理用于解码网络输出获得文本框或识别文字代码位于 ppocr/postprocess。PaddleOCR 内置了 DB、EAST、SAST、CRNN 和 Attention 等算法相关的后处理模块完整列表见 ppocr/postprocess/init.py 的support_dict。步骤 1在 ppocr/postprocess 文件夹下新建文件如my_postprocess.py。步骤 2实现后处理类。后处理接收网络的原始输出preds与可选的label二者需要分别解码import paddle class MyPostProcess: def __init__(self, *args, **kwargs): # your init code pass def __call__(self, preds, labelNone, *args, **kwargs): if isinstance(preds, paddle.Tensor): preds preds.numpy() # you preds decode code preds self.decode_preds(preds) if label is None: return preds # you label decode code label self.decode_label(label) return preds, label def decode_preds(self, preds): # you preds decode code pass def decode_label(self, preds): # you label decode code pass步骤 3在 ppocr/postprocess/init.py 中导入新增模块。配置接入PostProcess: name: MyPostProcess args1: args1 args2: args2真实示例可参考 configs/det/det_mv3_db.yml 中的PostProcess段name: DBPostProcess含thresh、box_thresh、max_candidates、unclip_ratio等参数。注意 ppocr/postprocess/init.py 的build_post_process会先从配置中弹出name字段再以剩余参数实例化模块若name为None则直接返回None表示不需要后处理。__call__中label is None的判断保证了推理阶段无标签与训练/评估阶段有标签共用同一模块。5. 损失函数新增损失模块损失函数用于计算网络输出和 label 之间的距离代码位于 ppocr/losses。PaddleOCR 内置了 DB、EAST、SAST、CRNN 和 Attention 等算法相关的损失模块完整列表见 ppocr/losses/init.py 的support_dict。步骤 1在 ppocr/losses 文件夹下新建文件如my_loss.py。步骤 2实现损失类。损失接收网络输出predicts与 dataloader 返回的batchbatch[0]为图像、batch[1]为 label并以字典形式返回结果键名必须为lossimport paddle from paddle import nn class MyLoss(nn.Layer): def __init__(self, **kwargs): super(MyLoss, self).__init__() # you init code pass def __call__(self, predicts, batch): label batch[1] # your loss code loss self.loss(inputpredicts, labellabel) return {loss: loss}步骤 3在 ppocr/losses/init.py 中导入新增模块。配置接入Loss: name: MyLoss args1: args1 args2: args2真实示例参考 configs/det/det_mv3_db.yml 中的Loss段name: DBLoss并配置balance_loss、main_loss_type: DiceLoss、alpha: 5、beta: 10、ohem_ratio: 3等超参。若算法包含多个损失分量如检测任务常用 Dice 与 L1 的组合也可以参考仓库中的 ppocr/losses/combined_loss.py 与 ppocr/losses/det_db_loss.py 等实现在__call__内自行加权汇总后返回{loss: total_loss}。6. 指标评估新增评估模块指标评估用于计算网络在当前 batch 上的性能代码位于 ppocr/metrics。PaddleOCR 内置了检测、分类、识别、端到端、表格、KIE 等算法相关的指标模块完整列表见 ppocr/metrics/init.py 的support_dict。步骤 1在 ppocr/metrics 文件夹下新建文件如my_metric.py。步骤 2实现指标类。指标类需要实现__call__、get_metric、reset三个方法其中main_indicator用于在训练中挑选最优模型class MyMetric(object): def __init__(self, main_indicatoracc, **kwargs): # main_indicator is used for select best model self.main_indicator main_indicator self.reset() def __call__(self, preds, batch, *args, **kwargs): # preds is out of postprocess # batch is out of dataloader labels batch[1] cur_correct_num 0 cur_all_num 0 # you metric code self.correct_num cur_correct_num self.all_num cur_all_num return {acc: cur_correct_num / cur_all_num, } def get_metric(self): return metrics { acc: 0, norm_edit_dis: 0, } acc self.correct_num / self.all_num self.reset() return {acc: acc} def reset(self): # reset metric self.correct_num 0 self.all_num 0步骤 3在 ppocr/metrics/init.py 中导入新增模块。配置接入Metric: name: MyMetric main_indicator: acc真实示例参考 configs/det/det_mv3_db.yml 中的Metric段name: DetMetric、main_indicator: hmean。从实现看__call__每个 batch 被调用一次并累加统计量如correct_num/all_numget_metric在评估周期结束时汇总并返回以main_indicator为键的结果字典同时调用reset清空累计状态训练框架会依据该指标选择最优模型保存。7. 优化器新增优化器、学习率与正则化模块优化器用于训练网络内部还包含网络正则化和学习率衰减模块代码位于 ppocr/optimizer。PaddleOCR 内置了Momentum、Adam、RMSProp、Adadelta、AdamW等优化器见 ppocr/optimizer/optimizer.pyLinear、Cosine、Step、Piecewise、Const、OneCycle、MultiStepDecay、TwoStepCosine等学习率策略见 ppocr/optimizer/learning_rate.py以及L1Decay、L2Decay、CosineL2Decay等正则化模块见 ppocr/optimizer/regularizer.py。以新增 optimizer 为例步骤 1在 ppocr/optimizer/optimizer.py 中创建自己的优化器。步骤 2实现优化器类。推荐直接包装 Paddle 内置优化器类接收learning_rate与超参__call__接收模型参数并返回 Paddle 优化器实例from paddle import optimizer as optim class MyOptim(object): def __init__(self, learning_rate0.001, *args, **kwargs): self.learning_rate learning_rate def __call__(self, parameters): # It is recommended to wrap the built-in optimizer of paddle opt optim.XXX( learning_rateself.learning_rate, parametersparameters) return opt配置接入Optimizer: name: MyOptim args1: args1 args2: args2 lr: name: Cosine learning_rate: 0.001 regularizer: name: L2 factor: 0从 ppocr/optimizer/init.py 的build_optimizer实现可以看到优化器的完整构建顺序先构建学习率调度器 → 再构建正则化 → 最后构建优化器。其中lr.name支持在name缺省时默认使用Constregularizer.name若在 regularizer 模块中找不到会自动拼接Decay后缀即配置写L2时实际加载L2Decay见 ppocr/optimizer/regularizer.py同时支持通过clip_norm或clip_norm_global配置梯度裁剪。真实配置示例见 configs/det/det_mv3_db.yml 的Optimizer段name: Adam、lr.learning_rate: 0.001、regularizer: {name: L2, factor: 0}。8. 完整实战一个新增算法模块的落地清单将以上六个环节串起来在 PaddleOCR 中新增一个算法或为现有算法替换某个组件的完整操作清单如下确定改造范围分析新算法相对现有算法如 DB/CRNN的差异点明确需要新增或替换的环节逐环节编码按上述各节的三步范式在对应目录新建文件、实现类、在__init__.py中导入注册数据模块实现在 ppocr/data/imaug 下注册到ppocr/data/imaug/__init__.py网络模块实现在 ppocr/modeling 的 transforms/backbones/necks/heads 子目录下注册到对应的__init__.py后处理实现在 ppocr/postprocess注册到ppocr/postprocess/__init__.py损失实现在 ppocr/losses注册到ppocr/losses/__init__.py指标实现在 ppocr/metrics注册到ppocr/metrics/__init__.py优化器实现在 ppocr/optimizer/optimizer.py学习率在learning_rate.py、正则化在regularizer.py编写配置文件以仓库中已有的配置文件为模板如 configs/det/det_mv3_db.yml在Architecture、Loss、Optimizer、PostProcess、Metric、Train/Eval等段填入新模块的name与参数验证与训练配置正确后即可通过 tools/train.py 启动训练。需要注意各build_*工厂函数build_backbone、build_post_process、build_loss、build_metric、build_optimizer都会校验name是否存在于support_dict模块类名与配置键名必须完全一致。9. 常见问题与注意事项模块未被识别 / 报 only support ... 断言错误name未正确导入注册或该模块不属于当前model_typebackbone 场景对应的支持列表。请检查对应__init__.py的导入语句与support_dict。dataloader 返回字段顺序错乱数据模块流水线以KeepKeys指定的keep_keys顺序返回训练代码如损失函数取batch[1]依赖该顺序新增数据模块后请同步确认keep_keys。regularizer.name写L2却找不到类构建逻辑会自动追加Decay后缀L2等价于L2Decay这是正常行为无需修改。损失必须返回 dict 且键为loss训练循环依赖该约定返回其他结构会导致训练报错。模块参数均通过配置传入build_*工厂在实例化时会pop掉name字段其余配置项以**kwargs形式传给构造函数因此新增模块的__init__应使用*args, **kwargs兼容未知参数避免因配置文件多出字段而报错。至此读者已掌握 PaddleOCR 六环节模块化设计的全貌与新增模块三步走的完整方法论可以按需为检测、识别、分类等任务扩展自定义组件并将它们无缝接入现有训练与评估流程。【免费下载链接】PaddleOCRTurn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between images/PDFs and LLMs. Supports 100 languages.项目地址: https://gitcode.com/GitHub_Trending/pa/PaddleOCR创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
