☰
从PaddleOCR到DB+CRNN:轮胎字符识别的检测识别全链路解析
2026/10/6 22:41:29 网站建设 项目流程

简介:面向机器学习期末设计与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_cls=False, # 轮胎字符基本不倾斜,跳过方向分类器可提速 lang="ch", show_log=False ) result = ocr.ocr("tire.jpg", cls=False) for line in result: box, (text, confidence) = line print(f"检测框: {box}, 识别结果: {text}, 置信度: {confidence:.4f}")

这段代码里两个参数值得解释一下。use_angle_cls和cls在轮胎场景建议关闭,因为胎侧字符通常水平排列,方向分类器会拖慢推理速度,还可能把弯曲区域的字符误判为旋转 180 度。lang="ch"虽然不是必须,但模型字典里如果不包含数字和斜杠,识别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 算法在轮胎场景的取舍

DB(Differentiable Binarization)的核心思路是可微分二值化,它把分割图转化为二值图的过程做成可微的,从而能端到端训练。相比 EAST,DB 对弯曲文本的召回率更高,推理速度也快,适合在 CPU 上跑期末演示。但项目里也提到了一个尖锐的问题:无论 DB 还是 EAST,对轮胎上带花样设计的字符都难以准确检测。原因是花体字在分割阶段容易与背景花纹粘连,二值化后字符主体不完整。

DB 的输入尺寸对轮胎场景影响很大。PaddleOCR 默认检测图像长边是 960,但轮胎字符通常密集且细长,建议把检测分辨率调高到 1280 甚至 1536:

ocr = PaddleOCR( det_limit_side_len=1280, # 提高长边限制,小字符更不容易丢 det_db_thresh=0.3, # DB 二值化阈值,默认 0.3 det_db_box_thresh=0.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/45R17),DOT 码中不会出现孤立斜杠。我一般写一个后置字典,把孤立出现的/强制替换为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_mkldnn=False, # CPU 推理时 MKLDNN 可能带来不确定的合批行为 cpu_threads=1 )

固定种子后,同一张图的检测框坐标和置信度输出基本可以复现。如果仍不稳定,检查预处理里是否用到随机裁剪或数据增强,这类操作在推理阶段应该全部关闭。

5. 三个让轮胎字符识别更稳的进阶技巧

项目摘要里那句"只考虑了高度,结果还是不够精确"是提升空间最诚实的提示。我在复现后做了三个改造,都在不改模型的前提下显著改善了效果。

第一个技巧是多帧投票。轮胎是曲面,单帧拍照总会有局部模糊或反光,字符识别错那么一两个字符很正常。连续拍摄两三帧,对同一位置的字符做多数投票,能纠掉大部分偶发错误。投票算法很简单:按检测框的横向位置对齐字符,每个位置收集各帧识别结果,取出现次数最多的那个作为最终结果。

第二个技巧是自适应二值化参数。轮胎字符有凸起和凹陷两种工艺,凹陷字符在光照下呈现暗纹,凸起字符则是亮斑。固定阈值永远有一类字符扫不出来。我改成先做 CLAHE 对比度均衡,然后用大津法(OTSU)自动计算二值化阈值。这一步对 4.1 里的花纹误检也有抑制作用——花纹纹理在二值化后呈现细碎颗粒,用形态学开运算就能滤掉。

第三个技巧是字符映射字典。轮胎规格码有一套明确的语法规则:225/45R17里数字和斜杠的位置固定,R只能出现在宽度和扁平比之后,DOT码的末四位是生产周和年份。把这些规则编译成简单的状态机,识别结果不符合语法时自动回退修正。比如斜杠后面跟的不是数字,就判断斜杠大概率是7的误识别。

这三个技巧叠加后,我拿项目自带的验收图重新跑了一遍,弯胎面和花体字样本的准确率从摘要里说的"大幅度下降"回升到了可用的水平,而代码改动加起来不超过 100 行。

最后说一个我自己的血泪经验:这类 OCR 项目,检测框的几何分布比识别模型本身更值得先看。我最初复现时花了一整天调 CRNN 的参数,识别错误率纹丝不动,后来把检测框可视化出来才发现问题全在框选——字符框歪、重复、带尾巴,识别模型再好也白搭。从那以后我每次做轮胎字符识别,都强制先输出检测框叠加图,确认几何分布没问题再碰识别参数。这套代码我迭代过三轮,沉淀下来的都是这套顺序里的踩坑教训,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询