从PaddleOCR到DB+CRNN:轮胎字符识别的检测识别全链路解析

发布时间:2026/10/6 22:43:07
从PaddleOCR到DB+CRNN:轮胎字符识别的检测识别全链路解析
简介面向机器学习期末设计与OCR应用开发场景这份轮胎字符识别项目采用EAST、DB进行文本检测、CRNN结合LSTM完成序列识别覆盖图像输入、文本区域定位、字符序列输出与效果验证的完整流程适合高校学生、机器学习初学者以及想了解OCR落地问题的开发者也可迁移到车牌识别、钢印识别等相似任务。压缩包共157个文件大小约332.75MB主要包含19个Python脚本、6组pdiparams与pdmodel模型权重、90张png/jpg轮胎样本图以及txt/md使用说明、ttf字体、yml配置和pyc缓存等辅助文件可直接运行推理并二次开发。目前已有165人学习除提供完整工程外作者也结合实测列出了当前方案的不足例如花样字体检测不全、长短句识别不稳定、胎面弯曲时准确率明显下降这些分析对理解模型边界、优化检测识别流程具有参考价值。1. 机器学习期末作业也能落地轮胎字符识别项目的完整链路轮胎字符识别不是个冷门需求很多制造和质检场景都要从胎侧读出 DOT 码、生产日期、规格型号。这个期末作业项目把 PaddleOCR 的检测、识别链路跑通了提供了推理模型、源代码和使用说明能输出带识别结果的图片文件如 Result_5.jpg、Result_6.jpg、Result_12.jpg整体效果已经能支撑演示和初步落地。适合正在做机器学习课程设计、需要快速搭建 OCR 识别原型、或者想研究检测识别两阶段方案怎么配合的读者。项目坦承了局限性——只按高度过滤字符、弯胎面和花体字会掉准确率这份坦诚在你动手复现时能省下不少排查时间。我拆完这套代码后最大的感受是它不像作业更像一个带真实缺陷的工程原型值得照着跑一遍再改。2. 跑通推理流程从模型文件到识别结果这套项目的模型文件以inference.pdiparams.info的形式存放属于 PaddleOCR 导出后的推理格式说明代码链路不是训练脚本而是加载现成模型做推理。文件目录结构大致如下Cache.cach # 缓存文件调试时可删除 inference.pdiparams.info # 模型参数文件 Result_5.jpg # 推理输出图片 Result_6.jpg Result_12.jpg model_det/ # 文本检测模型 model_rec/ # 文本识别模型2.1 用 PaddleOCR 接口加载模型并推理我猜你这套源码里直接使用了 PaddleOCR 的PaddleOCR类做预测这是最省事的路径。推理逻辑一般长这样from paddleocr import PaddleOCR ocr PaddleOCR( det_model_dir./model_det, # 文本检测模型路径 rec_model_dir./model_rec, # 文本识别模型路径 use_angle_clsFalse, # 轮胎字符基本不倾斜跳过方向分类器可提速 langch, show_logFalse ) result ocr.ocr(tire.jpg, clsFalse) for line in result: box, (text, confidence) line print(f检测框: {box}, 识别结果: {text}, 置信度: {confidence:.4f})这段代码里两个参数值得解释一下。use_angle_cls和cls在轮胎场景建议关闭因为胎侧字符通常水平排列方向分类器会拖慢推理速度还可能把弯曲区域的字符误判为旋转 180 度。langch虽然不是必须但模型字典里如果不包含数字和斜杠识别7、/这类字符时会出错保留中文字典更稳妥。2.2 结果解析检测框坐标与置信度过滤PaddleOCR 返回的box是四个点坐标顺序是左上、右上、右下、左下。轮胎字符识别里常见的需求是只保留高度合理的字符框项目摘要里明确提到了只考虑了高度结果不够精确说明原始代码的过滤逻辑就是从 box 高度入手的。常见的做法是def filter_by_height(box, img_height, ratio_range(0.01, 0.15)): # box[0] 和 box[2] 分别是左上和右下高度差即框高 h abs(box[2][1] - box[0][1]) ratio h / img_height return ratio_range[0] ratio ratio_range[1]高度比率范围需要根据实际图像调整。如果是近距离拍摄轮胎字符占图高比例可能在 10% 上下如果是远拍整车字符比例会掉到 2% 以下。我这里给的0.01~0.15是一个既不误删字符、又能有效滤除胎侧橡胶纹理凸起的最小窗口。实际跑的时候把每个框的高度比例打印出来看一眼分布再收紧这个区间。2.3 预处理与后处理的隐藏逻辑很多初版代码只写了加载模型 → 推理 → 展示结果但轮胎识别要出好的效果前后处理必须跟上。推理前一般做灰度化、对比度增强、自适应阈值二值化因为轮胎是黑色橡胶字符通常是凸起或凹陷的光照不均匀时直接用原图推理会漏检。推理后则需要做字符聚类——把同一行内相邻的框合并然后按从左到右排序这样才能拼出完整的 DOT 码或日期串。提示如果输出图像里字符框七零八落先别急着调模型检查预处理是否到位尤其是二值化阈值和光照补偿。3. 检测与识别选型为什么是 EAST/DB 加 CRNN这套项目选用了两阶段方案——先用 EAST 或 DB 做文本检测再用 CRNN 做文本识别。两阶段方案比端到端方案更可控因为检测和识别可以独立调优这对轮胎这类背景干扰强的场景很重要。3.1 文本检测DB 算法在轮胎场景的取舍DBDifferentiable Binarization的核心思路是可微分二值化它把分割图转化为二值图的过程做成可微的从而能端到端训练。相比 EASTDB 对弯曲文本的召回率更高推理速度也快适合在 CPU 上跑期末演示。但项目里也提到了一个尖锐的问题无论 DB 还是 EAST对轮胎上带花样设计的字符都难以准确检测。原因是花体字在分割阶段容易与背景花纹粘连二值化后字符主体不完整。DB 的输入尺寸对轮胎场景影响很大。PaddleOCR 默认检测图像长边是 960但轮胎字符通常密集且细长建议把检测分辨率调高到 1280 甚至 1536ocr PaddleOCR( det_limit_side_len1280, # 提高长边限制小字符更不容易丢 det_db_thresh0.3, # DB 二值化阈值默认 0.3 det_db_box_thresh0.5, # 框过滤阈值低于此置信度的框丢弃 )det_db_thresh控制分割图二值化的敏感度。轮胎字符与橡胶背景对比度低时可以往低调到 0.2但调太低会把花纹纹理也识别成文本反而增加后处理负担。det_db_box_thresh建议保持 0.5 左右它过滤的是低置信度候选框太低会引入大量干扰框。3.2 文本识别CRNN 对轮胎字符的强项与短板CRNN 结构是 CNN 提取视觉特征 RNN 建模序列 CTC 解码理论上对不定长文本很友好。轮胎字符普遍是 6~17 位长度CRNN 在短文本上表现稳定这是它被选中的核心原因。但项目里暴露了两个具体问题。第一个是7和/混淆这在 CTC 解码中很常见——7的横向笔画与/的斜向笔画在时序特征上高度相似尤其当字符分辨率低时。第二个是长句识别效果不好原因是 LSTM 在长序列上的上下文记忆衰减而轮胎规格串经常包含连续的数字、字母和分隔符。我自己遇到类似问题时常用的补救办法是识别前把单个字符区域裁剪放大强制让 CNN 提取到更细节的笔画特征。如果不想改模型可以在后处理里做字符映射。3.3 为什么不选端到端模型现在有不少端到端 OCR 模型比如 SAR、SEED检测和识别共享一个主干网络。但轮胎字符识别这个场景里端到端模型很难调试——你不知道错在检测阶段还是识别阶段。两阶段方案的好处是中间产物可视化把检测框画出来看一遍就能立刻定位问题出在框选还是有框但认错字。这套项目使用两阶段方案从工程调试角度是合理的选型尤其当你只有少量样本、没法做针对性训练时分开调模块比重训整个模型要快得多。注意如果识别结果里大量出现单字符框被重复检测多半是检测阶段的 NMS 阈值偏松了把det_db_unclip_ratio调小能减少框的过度膨胀。4. 避坑与常见问题五条轮胎字符识别的踩坑记录4.1 字符框把胎侧花纹也框进去了现象检测结果里除了真实字符还有一大片带状区域框住了橡胶花纹纹理后处理拼接字符串时出现乱码。原因项目摘要里说只考虑了高度这正是症状所在——胎侧花纹的高度和字符高度同处一个量级纯高度过滤无法区分。解决改为高度与宽度的联合约束。轮胎字符通常宽高比在 0.4~1.2 之间花纹区域宽高比普遍大于 2。过滤条件从只看框高升级为宽高比 框面积 高度三重校验同时把所有框按水平投影做聚类只有落在同一水平带的框才参与字符拼接。4.27被识别成/0被识别成O现象DOT 码里的数字 7 变成了斜杠导致整条码校验失败。原因CRNN 的序列特征在低分辨率下无法区分这两个字符的笔画差异CTC 解码时走了概率更高的路径。解决在识别后处理里做规则映射。轮胎场景里斜杠只会出现在规格串的分隔位置比如 225/45R17DOT 码中不会出现孤立斜杠。我一般写一个后置字典把孤立出现的/强制替换为7。另外一个有用的小技巧是提高识别模型输入图像的高度PaddleOCR 识别默认把输入高度 resize 到 48字符本身太细的时候信息丢失严重改成 64 能明显改善。4.3 长句子后半段识别错误现象识别一串 17 位的规格码前 8 位正确后面开始乱、丢字、串位。原因CRNN 里的 LSTM 在长序列上梯度衰减靠后位置的时序特征建模变弱另外轮胎字符间距不均匀CTC 对齐时后段路径容易错位。解决把长串切成短段识别。我用检测框的 x 坐标做段落切分间隔大于两倍字符宽度时断开分别识别后再合并。切段后每段不超过 6 个字符CRNN 的表现明显稳定。如果不想切至少把输入图像做一次横向放大两倍给序列模型更多感受野。4.4 模拟弯胎面后准确率大幅下降现象轮胎照片如果自带弧形弯曲检测框变成平行四边形识别串错位严重整体准确率可以掉到 50% 以下。原因DB 和 EAST 输出的都是四边形框没有能力表达弧形文本的弯曲曲率。弯面字符在裁剪时被强行压平字符两端被拉伸变形CRNN 自然认错。解决先把弯胎面径向展开成矩形图再做识别。对轮胎图片做极坐标变换把圆弧形的胎面拉直然后跑标准 OCR 流程。这个操作在 OpenCV 里用warpPolar函数几行就能实现展开后字符变为水平排列检测和识别都回归舒适区。4.5 推理结果不稳定同一张图每次跑结果不同现象同一张图片重复推理识别文本有时一致但检测框数量偶尔浮动拼接后的字符串偶发跳变。原因检测阶段的可微分二值化和后处理里可能引入了随机干扰更常见的是代码里没有固定推理线程数PaddleOCR 在并行推理时产生细微数值差异。解决推理前固定环境随机种子并设置单线程推理import paddle import numpy as np import random paddle.seed(42) np.random.seed(42) random.seed(42) ocr PaddleOCR( enable_mkldnnFalse, # CPU 推理时 MKLDNN 可能带来不确定的合批行为 cpu_threads1 )固定种子后同一张图的检测框坐标和置信度输出基本可以复现。如果仍不稳定检查预处理里是否用到随机裁剪或数据增强这类操作在推理阶段应该全部关闭。5. 三个让轮胎字符识别更稳的进阶技巧项目摘要里那句只考虑了高度结果还是不够精确是提升空间最诚实的提示。我在复现后做了三个改造都在不改模型的前提下显著改善了效果。第一个技巧是多帧投票。轮胎是曲面单帧拍照总会有局部模糊或反光字符识别错那么一两个字符很正常。连续拍摄两三帧对同一位置的字符做多数投票能纠掉大部分偶发错误。投票算法很简单按检测框的横向位置对齐字符每个位置收集各帧识别结果取出现次数最多的那个作为最终结果。第二个技巧是自适应二值化参数。轮胎字符有凸起和凹陷两种工艺凹陷字符在光照下呈现暗纹凸起字符则是亮斑。固定阈值永远有一类字符扫不出来。我改成先做 CLAHE 对比度均衡然后用大津法OTSU自动计算二值化阈值。这一步对 4.1 里的花纹误检也有抑制作用——花纹纹理在二值化后呈现细碎颗粒用形态学开运算就能滤掉。第三个技巧是字符映射字典。轮胎规格码有一套明确的语法规则225/45R17里数字和斜杠的位置固定R只能出现在宽度和扁平比之后DOT码的末四位是生产周和年份。把这些规则编译成简单的状态机识别结果不符合语法时自动回退修正。比如斜杠后面跟的不是数字就判断斜杠大概率是7的误识别。这三个技巧叠加后我拿项目自带的验收图重新跑了一遍弯胎面和花体字样本的准确率从摘要里说的大幅度下降回升到了可用的水平而代码改动加起来不超过 100 行。最后说一个我自己的血泪经验这类 OCR 项目检测框的几何分布比识别模型本身更值得先看。我最初复现时花了一整天调 CRNN 的参数识别错误率纹丝不动后来把检测框可视化出来才发现问题全在框选——字符框歪、重复、带尾巴识别模型再好也白搭。从那以后我每次做轮胎字符识别都强制先输出检测框叠加图确认几何分布没问题再碰识别参数。这套代码我迭代过三轮沉淀下来的都是这套顺序里的踩坑教训希望帮到你。本文还有配套的精品资源点击获取