PaddleOCR 中 CRNN 文本识别算法:原理、训练、评估与全流程部署实战
本文以 PaddleOCR 仓库中的 CRNN 算法文档为核心,系统讲解经典 CRNN(卷积循环神经网络)文本识别模型在 PaddleOCR 中的工程落地:从算法原理、官方复现精度与配置文件解析,到训练、评估、预测、Python/C++/Serving/Paddle2ONNX 的完整推理部署链路。读者读完将掌握基于 tools/train.py、tools/eval.py、tools/infer_rec.py、tools/export_model.py 和 tools/infer/predict_rec.py 驱动 CRNN 模型的全套实战方法,并能理解 DTRB 评测流程下英文模型与中文模型在输入尺寸、字符字典上的关键差异。
1. 算法简介与复现效果
CRNN(Convolutional Recurrent Neural Network)是 Shi、Bai、Yao 在 2015 年提出的端到端可训练文本识别网络,核心思想是用 CNN 提取图像特征、RNN(双向 LSTM)建模序列依赖、CTC 完成免对齐的序列转录,论文《An End-to-End Trainable Neural Network for Image-based Sequence Recognition and Its Application to Scene Text Recognition》发表于 IEEE(TPAMI 2017 正式刊出)。
PaddleOCR 参考 DTRB 文本识别训练与评估流程,使用 MJSynth 和 SynthText 两个合成文本识别数据集训练,并在 IIIT、SVT、IC03、IC13、IC15、SVTP、CUTE 数据集上评估,仓库文档中给出的复现效果如下:
| 模型 | 骨干网络 | Avg Accuracy | 配置文件 | 下载链接 |
|---|---|---|---|---|
| CRNN | Resnet34_vd | 81.04% | configs/rec/rec_r34_vd_none_bilstm_ctc.yml | rec_r34_vd_none_bilstm_ctc_v2.0_train.tar |
| CRNN | MobileNetV3 | 77.95% | configs/rec/rec_mv3_none_bilstm_ctc.yml | rec_mv3_none_bilstm_ctc_v2.0_train.tar |
说明:上表中的下载链接指向 PaddleOCR 官方发布的预训练权重(V2.0 英文模型),模型权重需自行下载后放入工作目录使用。
2. 环境配置
请先参考 运行环境准备 配置 PaddleOCR 运行环境,参考 项目克隆 克隆项目代码。PaddleOCR 依赖 PaddlePaddle 框架及 pyyaml、shapely、scikit-image、tqdm 等运行库,具体版本要求以 requirements.txt 为准。
3. CRNN 网络结构在 PaddleOCR 中的模块化实现
PaddleOCR 对代码进行了模块化设计,训练不同识别模型只需要更换配置文件。CRNN 在配置文件中通过 Architecture 字段组织为四段式结构,以 Resnet34_vd 骨干的 rec_r34_vd_none_bilstm_ctc.yml 为例:
Architecture:
model_type: rec
algorithm: CRNN
Transform:
Backbone:
name: ResNet
layers: 34
Neck:
name: SequenceEncoder
encoder_type: rnn
hidden_size: 256
Head:
name: CTCHead
fc_decay: 0
各模块与源码的对应关系如下:
- Backbone(视觉特征提取):
ResNet(34 层)或MobileNetV3(scale: 0.5, model_name: large)。CNN 部分负责从原始图像中提取高层视觉特征序列。 - Neck(序列编码):
SequenceEncoder,实现位于 ppocr/modeling/necks/rnn.py。它先将 CNN 特征通过Im2Seq重排为序列(encoder_type: rnn时),再送入双向 RNN 编码器EncoderWithRNN,hidden_size控制 LSTM 隐层维度(ResNet34 配置为 256,MobileNetV3 配置为 96)。源码中的support_encoder_dict还支持fc、svtr、lightsvtr、cascadernn等多种编码器,CRNN 默认使用rnn。 - Head(序列转录):
CTCHead,实现位于 ppocr/modeling/heads/rec_ctc_head.py。它对每个时间步的序列特征做nn.Linear全连接映射到字符类别空间(out_channels由字典大小决定),非训练模式下还会对输出做F.softmax(predicts, axis=2)得到概率分布。 - Loss(损失函数):
CTCLoss,实现位于 ppocr/losses/rec_ctc_loss.py,内部调用nn.CTCLoss(blank=0, reduction="none"),支持use_focal_loss可选开关。CTC 损失允许预测序列与标签序列长度不对齐,是 CRNN 免字符切分训练的关键。 - PostProcess(后处理解码):
CTCLabelDecode,实现位于 ppocr/postprocess/rec_postprocess.py,负责将 CTC 输出按“去重 + 去 blank”规则解码为最终文本。 - Metric(评测指标):
RecMetric,main_indicator: acc,即按整词/整行准确率评估。
数据链路侧,训练和评估阶段的数据增强与标签处理由 CTCLabelEncode 和 RecResizeImg 完成,后者按 RecResizeImg.image_shape 将图像归一化到固定尺寸。
4. 模型训练、评估与预测
训练不同识别模型仅需更换配置文件,完整流程请参考 文本识别训练教程。在完成数据准备后,便可启动训练。
4.1 训练
# 单卡训练(训练周期长,不建议)
python3 tools/train.py -c configs/rec/rec_r34_vd_none_bilstm_ctc.yml
# 多卡训练,通过 --gpus 参数指定卡号
python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/rec/rec_r34_vd_none_bilstm_ctc.yml
以 rec_r34_vd_none_bilstm_ctc.yml 为例,训练阶段的关键超参数如下:
| 配置项 | 取值 | 说明 |
|---|---|---|
Global.epoch_num |
72 | 总训练轮数 |
Global.save_model_dir |
./output/rec/r34_vd_none_bilstm_ctc/ |
模型保存目录 |
Global.save_epoch_step |
3 | 每 3 个 epoch 保存一次 |
Global.eval_batch_step |
[0, 2000] |
每 2000 次迭代执行一次评估 |
Global.cal_metric_during_train |
True | 训练过程中同步计算指标 |
Global.max_text_length |
25 | 最大文本长度 |
Global.use_space_char |
False | 字符集是否包含空格 |
Optimizer.name |
Adam | 优化器,lr: 0.0005,L2 正则 factor: 0 |
Train.dataset.name |
LMDBDataSet | 训练数据为 LMDB 格式 |
Train.loader.batch_size_per_card |
256 | 单卡 batch size |
Train.dataset.transforms.RecResizeImg.image_shape |
[3, 32, 100] |
输入图像尺寸(通道、高、宽) |
MobileNetV3 轻量版配置见 rec_mv3_none_bilstm_ctc.yml,其网络结构与上述一致,仅骨干替换为 MobileNetV3、hidden_size 降为 96,训练超参数(72 epoch、Adam、image_shape: [3, 32, 100])保持一致。
4.2 评估
# GPU 评估,Global.pretrained_model 为待测权重
python3 -m paddle.distributed.launch --gpus '0' tools/eval.py -c configs/rec/rec_r34_vd_none_bilstm_ctc.yml -o Global.pretrained_model={path/to/weights}/best_accuracy
评估使用 tools/eval.py,通过 -o 参数覆盖配置中的 Global.pretrained_model 指向待测权重(通常为训练过程中保存的 best_accuracy 快照),评估数据由配置中的 Eval.dataset 指定(验证集同样为 LMDBDataSet,shuffle: False、batch_size_per_card: 256)。
4.3 预测
# 预测使用的配置文件必须与训练一致
python3 tools/infer_rec.py -c configs/rec/rec_r34_vd_none_bilstm_ctc.yml -o Global.pretrained_model={path/to/weights}/best_accuracy Global.infer_img=doc/imgs_words_en/word_1.png
预测时通过 Global.infer_img 指定待识别图片,Global.pretrained_model 指定权重,且配置文件必须与训练时保持一致(保证输入尺寸、字典、网络结构匹配)。
5. 推理部署
5.1 Python 推理
首先将 CRNN 文本识别训练过程中保存的模型转换为 inference model。以基于 Resnet34_vd 骨干、使用 MJSynth 和 SynthText 两个英文合成数据集训练的模型为例,转换命令如下:
python3 tools/export_model.py -c configs/rec/rec_r34_vd_none_bilstm_ctc.yml -o Global.pretrained_model=./rec_r34_vd_none_bilstm_ctc_v2.0_train/best_accuracy Global.save_inference_dir=./inference/rec_crnn
tools/export_model.py 会读取配置文件中的网络结构,将训练权重固化为推理所需的模型与参数文件,并输出到 Global.save_inference_dir 指定目录(此处为 ./inference/rec_crnn)。
CRNN 文本识别模型推理,可以执行如下命令:
python3 tools/infer/predict_rec.py --image_dir="./doc/imgs_words_en/word_336.png" --rec_model_dir="./inference/rec_crnn/" --rec_image_shape="3, 32, 100" --rec_char_dict_path="./ppocr/utils/ic15_dict.txt"
执行命令后,上面图像的识别结果如下:
Predicts of ./doc/imgs_words_en/word_336.png:('super', 0.9999073)
注意:由于上述模型参考 DTRB 文本识别训练和评估流程,与超轻量级中文识别模型训练有两方面不同:
- 训练图像分辨率不同:上述英文模型训练时采用
[3, 32, 100]分辨率;而中文模型为了保证长文本识别效果,训练时采用[3, 32, 320]。预测推理程序默认形状参数是训练中文模型采用的[3, 32, 320],因此推理英文模型时,必须通过参数rec_image_shape显式设置为"3, 32, 100"。 - 字符列表不同:DTRB 论文实验仅针对 26 个小写英文字母和 10 个数字(共 36 个字符),所有大小写字符均转为小写,不在列表中的字符被忽略并视为空格。因此该模型未随附完整中文字典,而是通过如下方式生成字典:
self.character_str = "0123456789abcdefghijklmnopqrstuvwxyz"
dict_character = list(self.character_str)
因此推理时需要设置参数 rec_char_dict_path,指定英文字典 ./ppocr/utils/ic15_dict.txt(该文件位于 ppocr/utils/ic15_dict.txt)。
5.2 C++ 推理
准备好推理模型后,参考 cpp infer 教程 操作即可。C++ 推理工程位于 deploy/cpp_infer,其中文本识别后处理亦实现了 CTCLabelDecode,与 Python 侧解码逻辑保持一致,保证两端结果一致。
5.3 Serving 服务化部署
准备好推理模型后,参考 pdserving 教程 进行 Paddle Serving 服务化部署,包括 Python Serving 和 C++ Serving 两种模式。服务化示例代码位于 deploy/hubserving/ocr_rec,可在服务端以 HTTP 接口形式提供文本识别能力。
5.4 更多推理部署
CRNN 模型还支持以下推理部署方式:
- Paddle2ONNX 推理:准备好推理模型后,参考 paddle2onnx 教程 操作,可将 Paddle 推理模型导出为 ONNX 格式,接入 ONNX Runtime 等跨平台推理环境。
6. 常见问题
- 推理英文 CRNN 模型结果全乱码或为空:优先检查
--rec_image_shape是否设置为"3, 32, 100"(而非默认的[3, 32, 320]),以及--rec_char_dict_path是否指向 ppocr/utils/ic15_dict.txt。 - 训练与预测结果不一致:确认预测使用的配置文件与训练完全一致,尤其是
RecResizeImg.image_shape、字典路径与Architecture网络结构。 - 评估命令报找不到权重:
Global.pretrained_model应指向训练保存的best_accuracy前缀(即模型文件路径去掉.pdparams后缀)。 - 训练数据格式:CRNN 配置默认使用
LMDBDataSet,需准备 LMDB 格式的训练/验证数据,data_dir分别配置于Train.dataset.data_dir与Eval.dataset.data_dir。
引用
@ARTICLE{7801919,
author={Shi, Baoguang and Bai, Xiang and Yao, Cong},
journal={IEEE Transactions on Pattern Analysis and Machine Intelligence},
title={An End-to-End Trainable Neural Network for Image-Based Sequence Recognition and Its Application to Scene Text Recognition},
year={2017},
volume={39},
number={11},
pages={2298-2304},
doi={10.1109/TPAMI.2016.2646371}}
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust4.21 K637- DDeepSeek-V4.1-FlashDeepSeek-V4.1-Flash 是一个多模态混合专家(MoE)模型,拥有 5520 亿骨干参数,并支持最多一百万 token 的上下文长度。该模型原生支持图像和文本输入,并以自回归方式生成文本Python270
jforgamejforgame是一个一站式游戏服务器开发框架。包含游戏服务器开发所需要的各种组件,比如网关,socket服务端与客户端,自定义高效消息编解码,游戏热更新,游戏通用工具等等。包含游戏服,跨服,匹配服,后台管理系统等实现,同时提供大量业务案例以供学习。亦可用于其他socket应用,例如及时聊天等。Java321
fizz-gateway-nodeAn Aggregation API Gateway in Java . FizzGate 是一个基于 Java开发的微服务聚合网关,是拥有自主知识产权的应用网关国产化替代方案,能够实现热服务编排聚合、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理、回调管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。Java220
certd开源SSL证书管理工具;全自动证书申请、更新、续期;通配符证书,泛域名证书申请;证书自动化部署到阿里云、腾讯云、主机、群晖、宝塔;https证书,pfx证书,der证书,TLS证书,nginx证书自动续签自动部署JavaScript220
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python300
