ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

YOLOv5+CRNN中文车牌识别实战:从数据到部署全流程解析

YOLOv5+CRNN中文车牌识别实战:从数据到部署全流程解析 简介本资源是一套完整的中文车牌识别高分项目实现基于YOLOv5实现车牌定位、CRNN模型完成字符识别面向人工智能、自动化、电子信息等专业学生及初学者适用于毕业设计、课程设计、项目演示与算法进阶学习。压缩包共92个文件含53个Python核心脚本涵盖检测、识别、训练、测试、GUI界面及模型转换、15个YAML配置文件支持多种YOLOv5模型结构与超参微调、9张效果示意图与7张测试样图以及2个预训练权重.pth/.pt文件整体体积仅7.65MB结构清晰、模块解耦便于理解与二次开发。已有112人下载学习项目经导师指导并获95分答辩评审所有代码均通过实测验证配套详细文档覆盖环境配置、数据准备、训练流程、推理部署及常见问题说明还包含plateNet/LPRNet/colorNet等关键网络实现、onnx/openvino导出脚本及torch2trt加速支持显著降低复现门槛。 直接把 YOLOv5 和 CRNN 拼在一起做中文车牌识别这个组合在国内毕设、课设和简历项目里出现频率非常高。原因很简单它足够经典分工明确——YOLOv5 负责把车牌从复杂场景里“抠”出来CRNN 负责把抠出来的车牌图转成字符串两件事都各自有极其成熟的方案可以借鉴。我最初拿到这套源码的时候第一感觉是资料真全模型、训练日志、标注工具、说明文档都齐了但真正动手跑起来、再自己复现一遍之后才发现里面的细节远比想象中多。这篇文章我会把整套方案的思路、数据准备、训练调参、串接部署以及我踩过的坑全部拆开讲清楚。适合正在做毕业设计的学生也适合想快速落地一个车牌识别 demo 的工程师参考。我不会把代码贴得密密麻麻而是把每个环节的“为什么这么做”和“实际怎么调”讲透你拿着思路就能在自己的项目里复现。1. 整体方案拆解为什么是 YOLOv5 CRNN而不是端到端一步到位1.1 两阶段架构的核心思路车牌识别听起来是一个任务实际上可以拆成两个子任务第一步是定位第二步是识别。这套系统采用的就是典型的两阶段架构。检测端用 YOLOv5输入一张完整图像输出若干个带置信度的车牌边界框识别端用 CRNN把每个裁剪出来的车牌小图变成一串字符比如“京A12345”。为什么要把两个任务拆开因为检测和识别的输入输出差异很大。检测需要的是全局上下文信息它得理解“车牌在画面里属于一个相对小的目标周围可能有车头、车身、路面背景”所以网络要能看全图而且对尺度变化要敏感。而识别任务面对的是已经裁剪好的近似矩形的车牌照它的核心是“从左到右逐字符读取”更关注局部纹理和序列顺序。把这两个任务强行塞进同一个端到端模型里反而会互相干扰。从训练角度看拆开也更省心。YOLOv5 有海量预训练权重在 COCO 上训好的模型可以直接拿来做迁移学习车牌检测数据量要求其实不高几千张就能训得不错。CRNN 也是一样可以先用合成车牌数据预训练再用真实数据微调。两个模型的训练数据可以分别迭代、分别优化调试起来心智负担小很多。这对学生项目或者中小团队来说是巨大的优势。1.2 检测端的选型为什么 YOLOv5 依然是稳妥选择YOLOv5 虽然名字里带 v5但在车牌检测这种相对单一的场景里它依然是非常能打的选手。对比 YOLOv8、YOLOv9 这些更新版本YOLOv5 的生态最成熟教程多、踩坑记录多、ONNX 导出方便对于课程设计级别的项目来说“求稳”比“追新”更重要。具体到车牌场景YOLOv5s 这个轻量版本就够用。车牌目标在监控画面里通常占几十到几百像素不算极小目标用 s 版的感受野和特征提取能力完全覆盖。如果你用的是 640x640 输入一张普通图片里车牌再怎么小也不会小于 20x20s 版的 P3 层能够处理。我实际测试下来的感受是在 CCPD 数据集上用 YOLOv5s 训练mAP0.5 轻松到 0.98 以上换到包含复杂场景的自建数据集也能保持在 0.95 左右。作为对比如果一开始就用 YOLOv8虽然性能略有提升但很多配套工具比如标签格式转换脚本、部署示例都得自己重新踩一遍投入产出比不明显。如果你的项目时间紧直接 YOLOv5s 起步是性价比最高的选择。1.3 识别端为什么选 CRNN序列建模天然适配车牌结构车牌字符识别的核心难点在于字符宽度不一、位置不固定、存在轻微倾斜和模糊而且整串字符是一个强顺序依赖的序列。CRNN 的设计哲学恰好就是“用 CNN 提特征用 RNN 建模序列用 CTC 对齐”每一步都踩在车牌的痛点上。具体展开说CRNN 的第一段是卷积网络把输入图像转成一系列特征图第二段是双向 LSTM对特征序列做上下文建模。为什么要加 LSTM因为车牌里有“京A12345”这种字符组合前一个字符对后一个字符有强烈的先验约束比如省份汉字后面一定跟字母字母后面是数字或字母双向 LSTM 能学到这种隐式语法。第三段是 CTC 解码它最大的好处是不需要逐字符标注位置只需要整串标注训练数据标注成本大幅降低。和 LPRNet、PaddleOCR 里的车牌子模型相比CRNN 胜在结构简单、解释性强、改造成本低。你可以在不改变整体框架的情况下把主干网络从 VGG 换成 ResNet把 LSTM 层数从 1 层加到 2 层每一步改动效果都是可预期的。对想要在答辩时展示“我理解这个模型”的学生来说CRNN 比用现成 OCR 工具更拿得出手。1.4 中文车牌的特殊难点不是简单的 OCR很多人以为车牌识别就是把开源 OCR 拿过来用真上手会发现中文车牌有一堆“专属坑”。首先是字符集中国车牌包含省份汉字31 个省市简称、24 个字母不含 I、O、10 个数字但在实际场景中还会出现“警”“学”“挂”“使”等特殊字符。其次是字符排布结构。最常见的蓝牌是单排 7 位但新能源绿牌是 8 位且第 2 位是字母 D 或 F黄牌大车是双排结构教练车、领馆车还有额外的小字。这套系统如果只针对蓝牌做单排 CRNN 就够了要支持绿牌就得把序列长度调成 8要支持黄牌双排还得加一个“是否双排”的分类分支。这些都是做真实项目绕不开的细节。再就是成像质量问题。车牌在画面里往往是倾斜的、模糊的、反光的甚至被灰尘遮挡。YOLOv5 检测框是水平矩形如果车牌本身有透视形变裁出来的图就是歪的CRNN 直接识别这种歪图效果会大打折扣。所以很多工程落地时会在检测和识别之间加一个透视矫正步骤我在后面实操部分会详细讲怎么处理。2. 环境搭建与数据准备这套系统的地基2.1 环境版本清单与依赖安装先给出一份我验证过能稳定跑通的版本组合。GPU 环境建议 CUDA 11.3 以上显存 6G 就够训练 YOLOv5s 和轻量 CRNN如果显存只有 4Gbatch size 就要调小一点。Python 建议用 3.8 或 3.9PyTorch 用 1.10 到 1.13 之间的版本。YOLOv5 官方仓库对这几个版本的兼容性最好太新的 PyTorch 反而偶尔会出现算子兼容问题。安装依赖的步骤很简单YOLOv5 部分直接进仓库目录执行cd yolov5/ pip install -r requirements.txt这里有个小坑requirements.txt 里会装一批库如果你机器上已经装过其他深度学习框架建议先建一个独立的 conda 环境避免依赖冲突。CRNN 部分相对轻量只需要 torch、torchvision、opencv-python、numpy、lmdb如果用了 LMDB 格式的数据集。我个人的习惯是装完环境先跑一句python detect.py --source data/images/bus.jpg验证 YOLOv5 能否正常推理。很多问题在环境刚装好时暴露最明显比如 CUDA 不可用、torchvision 版本不匹配这时候排查成本最低。倒腾半天跑训练才发现环境有问题那才是真浪费时间。2.2 数据集从哪来公开数据集 自采数据的组合策略车牌识别不能只用公开数据集硬训因为每个地区的车牌样式、场景光照、拍摄角度都有差异。最稳的组合是“公开数据集打底 少量场景数据微调”。公开数据集方面国内用得最多的是 CCPD中国城市停车场数据集和 CRPD中国道路停车场数据集。CCPD 有超过 20 万张图片覆盖了不同天气、不同角度、不同距离的蓝牌场景适合做检测模型的训练。CRPD 则更偏道路监控视角包含更多复杂背景。这两个数据集的标注格式略有不同CCPD 的车牌框坐标写在文件名里需要写脚本解析CRPD 则提供了 XML 或 TXT 标注转换起来更方便。YOLOv5 需要的标注格式是每个图片对应一个同名 txt 文件每行是“class cx cy w h”其中 cx、cy、w、h 都是相对于图片宽高的归一化值。转换脚本网上很多但核心逻辑都是一致的读取原标注 - 解析出左上角坐标和右下角坐标 - 算出中心点和宽高 - 归一化 - 写入 txt。如果你的项目有特定场景需求比如停车场出入口、高速卡口建议自己也拍一些照片补充进数据集。不需要太多几百张就能显著提升模型在你实际场景里的表现。自采数据需要注意的是标注一致性——框一定要紧贴车牌边缘宁可多框一点也不能框一半YOLO 对标注框质量的敏感度很高。2.3 车牌区域裁剪从检测到识别的关键中间步骤训练好检测模型之后接下来的流程是对图片推理得到车牌框把框内的图像裁出来送给识别模型。这一步看似简单实际上有几个容易翻车的细节。第一个细节是坐标换算。YOLOv5 输出的坐标是归一化的需要乘回原图宽高还要注意 YOLOv5 的坐标格式是 xywh中心点 宽高要先转成 xyxy左上角 右下角再裁剪。第二个细节是边界裁剪。如果检测框部分超出图像边界cv2.getRectSubPix或image[y1:y2, x1:x2]可能会报错或得到空白图必须加边界 clamp 处理。第三个细节是扩展边距。直接裁剪检测框有时候会把车牌边缘的螺丝、边框截掉一部分影响识别精度。我通常会在原框基础上向外扩 10% 到 15% 的宽度再裁剪。比如检测框是 (x1, y1, x2, y2)扩展后的宽度就是w x2 - x1新的 x1 是max(0, x1 - 0.1 * w)依此类推。这个微小的改动在绿牌和双层黄牌识别上效果很显著。2.4 数据增强让模型在恶劣环境下也能干活车牌识别最怕的场景是模糊、暗光、倾斜、逆光。数据增强就是用来模拟这些情况的。YOLOv5 自带的增强已经很完善包括 Mosaic、HSV 色域增强、随机翻转、随机缩放训练时默认开启不需要额外处理。但有几个点需要手动调。车牌检测场景里上下翻转增强没有意义——车牌不会倒着出现建议在数据配置文件的flipud参数里设置为 0只保留左右翻转。另外车牌的宽高比非常固定普通蓝牌约 3:1Mosaic 增强会把多张图拼在一起产生一些极端宽高比的假车牌反而可能干扰训练。如果你发现模型对正常车牌的检测反而不准了可以先关掉 Mosaic 试试。CRNN 这边的增强则集中在仿射变换、透视变换、高斯模糊、亮度对比度调整上。我常用的做法是用imgaug库写一个增强流程每张车牌图随机应用 1 到 3 种增强模拟真实场景中的成像退化。这里要特别注意车牌字符的形变不能太夸张否则人眼都难认模型更学不会。3. 检测模块实操用 YOLOv5 训练高精度车牌检测器3.1 数据集划分与标签格式转换拿到原始数据后第一步是划分训练集、验证集和测试集。推荐的比例是 8:1:1且要保证三个集合中车牌的省份、场景分布大致相同。如果训练集里全是安徽车牌、测试集里全是北京车牌那验证曲线会非常难看模型泛化能力也会被高估。标签格式转换我建议写一个独立脚本而不是在训练脚本里边读边转。脚本的核心逻辑是遍历所有标注文件统一转成 YOLO 格式的 txt。CCPD 的解析比较特殊它的文件名里直接包含了车牌框信息例如“025-95_113-154383_386473-386473_177454_154383_363402-0_0_22_27_27_33_16-37-15.jpg”需要从下划线分隔的字段里提取坐标。如果你是用标注工具如 LabelImg、labelme标注的自采数据导出时选 YOLO 格式即可省去转换步骤。唯一要注意的是标签文件里 class id 必须从 0 开始连续编号我们这里只有一个类别“plate”所以永远是 0。3.2 修改配置数据 YAML 和模型 YAMLYOLOv5 训练需要两个配置文件一个是数据配置一个是模型配置。数据配置写的是数据集路径和类别数train: /data/carplate/train/images val: /data/carplate/val/images nc: 1 names: [plate]路径建议写绝对路径YOLOv5 对相对路径的处理偶有坑。模型配置可以直接用官方自带的yolov5s.yaml只需要把nc改成 1。如果你用的是 COCO 预训练权重模型的最后一层卷积输出通道数会自动适配新的类别数不需要手动改。训练命令大致如下python train.py --img 640 --batch 16 --epochs 100 --data carplate.yaml --weights yolov5s.pt --device 0--img一般设 640如果你的车牌特别小可以试着调到 960能提升小目标检测能力但训练速度会慢不少。--batch根据显存调节6G 显存建议 16如果爆显存就降到 8。--epochs我建议先跑 100 轮看趋势如果 val mAP 还在涨就继续加。3.3 训练过程分析与 checkpoint 选择训练过程中要盯三个指标train/loss、val/obj_loss、metrics/mAP_0.5。正常情况下loss 会前 20 轮快速下降后面趋于平缓mAP_0.5 会逐步逼近 0.95 以上。如果你发现 loss 下降很慢或者直接不降大概率是学习率设置问题YOLOv5 默认的--lr0 0.01对迁移学习场景基本够用不需要特殊调整。训练完成后项目文件夹下会生成runs/train/expX/weights/目录里面有last.pt和best.pt。很多人直接用last.pt这是不对的。last.pt只是最后一轮的权重如果训练后期出现轻微过拟合它的效果反而不如中间某轮的best.pt。best.pt是验证集指标最优的权重业务上线或者测试都应该用它。我习惯在训练结束后再用测试集做一次完整评测统计 mAP、每类精确率和召回率。在车牌检测这种单类别场景里如果召回率低于 0.95说明漏检严重优先检查数据增强是否过强如果精确率低说明误检多优先检查背景样本是否太少——可以专门跑一批没有车牌的图片做负样本。3.4 推理与检测结果后处理YOLOv5 推理输出的预测框置信度阈值默认是 0.25NMS 的 IoU 阈值默认是 0.45。实际车牌场景里置信度阈值可以提高到 0.45因为我们只关心高置信度的车牌框宁可漏一两个低置信度的也不要误检一堆车身贴纸。NMS 的 IoU 阈值也可以适当调低到 0.3减少重叠框。推理时要留意的是批次大小。如果要对视频流做实时处理单帧推理时间必须压到 30ms 以下这要求输入图片先缩放到 640x640 并做归一化。YOLOv5 的detect.py已经封装好了这些操作但如果是自己写推理脚本一定要记得做同样的预处理否则模型输出会非常离谱。4. 识别模块实操训练一个可靠的中文车牌 CRNN4.1 字符集设计与标签编码CRNN 的输出是字符类别概率序列所以训练前必须先定义字符集。我用的字符集包含三部分省份汉字京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼、24 个大写字母去掉 I 和 O、10 个数字再加上一个 CTC 空白符。字符集要写成一个列表文件每个字符对应一个索引。注意索引 0 通常留给 CTC 的 blank字符从 1 开始编号。这样设计的好处是 CTC 解码时blank 索引是固定的 0不用额外处理。标签编码就是把车牌字符串映射成索引序列。例如“京A12345”如果字符集里“京”是索引 5、“A”是 3那么这个标签序列就是 [5, 3, 10, 2, 4, 8, 9]数字对应的索引是它们在字符集中的位置。训练时目标序列不需要补齐到固定长度CTC 天然支持变长序列。4.2 网络结构与输入尺寸我这里用了一个精简的 CRNN 结构主干是类似 VGG 的卷积层提取特征后压缩高度再把特征图按宽度方向展开成序列输入双向 LSTM最后接全连接层输出每个时间步的字符概率。输入尺寸很关键。CRNN 要求输入图像高度固定宽度可变但为了 batch 训练方便通常会把所有图片 resize 成固定尺寸。我用的组合是height32, width128因为普通蓝牌宽高比约 3:1128 宽的序列足够容纳 7 个字符。新能源绿牌是 8 位128 宽也够。如果是双排黄牌建议单独训练一个高度 64 的模型或者加一个预处理把双排拆成单排。图像送入网络前要转成灰度图还是保留 RGB我的实验表明灰度图识别准确率略低因为颜色信息在区分某些易混字符时有帮助。所以建议保留 RGB 三通道。4.3 CTC Loss为什么它能解决“对齐”问题CRNN 训练最核心的就是 CTC Loss。传统的分类 loss 要求每个输入位置都对应一个标签但车牌字符宽度不一很难做逐像素对齐。CTC 的思路是允许网络每个时间步输出一个字符或者空白然后通过动态规划在所有可能路径中找出概率最大的那条作为预测。打个比方CTC 就像是在说“我不关心你每个时间步具体预测什么字符只要整个序列经过压缩处理后能拼出正确答案就行。”它允许连续重复字符和空白出现最后用去重操作把冗余去掉。这种机制让 CRNN 不需要字符级标注只需要整串标注就能训练。训练时 loss 直接取负对数似然。PyTorch 里用torch.nn.CTCLoss需要传入三个参数网络的 logits 序列形状是[T, N, C]T 是时间步数N 是 batch sizeC 是字符集大小、标签序列形状是[N, S]S 是标签长度用 -1 填充对齐、以及每个样本的标签长度。这里最容易出错的是 logits 的维度顺序一定记得先permute成[T, N, C]。4.4 训练策略与识别后处理CRNN 训练我建议先从合成数据开始。网上有开源的车牌合成器可以生成几万张逼真的车牌图片覆盖各种字体、背景、光照。用合成数据预训练 20 轮之后再用真实车牌数据微调。合成数据的好处是标签完全精准不会出现人眼识别错误导致标签噪声的问题。真实数据微调时学习率要降下来我用的初始学习率是 1e-4比预训练阶段小 10 倍。训练 50 轮左右验证集字符准确率能到 98% 以上。字符准确率的计算方法是对每张测试图片把模型输出的字符序列和真实标签逐位对比统计正确字符的比例。推理时要做两件后处理。第一件是 CTC 解码把概率序列转成字符串规则是取每个时间步概率最大的索引然后去除重复字符和 blank。第二件是置信度过滤如果某张车牌图的平均置信度低于 0.8宁可输出“unknown”也不要硬猜避免后续流程拿到错误结果。5. 系统集成与完整 Pipeline从图片到车牌字符串5.1 检测 识别的串接流程把 YOLOv5 和 CRNN 串起来一个最简的推理流程是这样的import cv2 import torch import numpy as np # 加载模型 detect_model torch.hub.load(yolov5, custom, pathbest.pt, sourcelocal) recognize_model CRNN(num_classeslen(CHARS)).to(device) recognize_model.load_state_dict(torch.load(crnn.pth, map_locationdevice)) recognize_model.eval() # 检测 img cv2.imread(test.jpg) results detect_model(img) boxes results.xyxy[0].cpu().numpy() # 裁剪 识别 for box in boxes: x1, y1, x2, y2, conf, cls box if conf 0.45: continue plate_img img[int(y1):int(y2), int(x1):int(x2)] plate_img cv2.resize(plate_img, (128, 32)) # 归一化、转 tensor、送入 CRNN # 输出字符串这段代码虽然只有不到 20 行但工程化时要考虑很多细节。首先是模型加载方式torch.hub.load适合快速验证正式部署建议直接用torch.jit.trace导出成 TorchScript或者导出 ONNX。其次是数据预处理的一致性CRNN 训练时如果做了归一化比如除以 255、减均值除方差推理时也要做完全一样的操作。5.2 透视矫正提升识别准确率的关键技巧前面提到直接裁剪检测框会遇到倾斜问题。YOLOv5 输出的是水平矩形框而真实车牌可能是透视形变的比如从侧面拍摄时车牌会变成一个梯形。CRNN 对这种形变非常敏感稍微歪一点字符就错。解决办法是在裁剪后做透视矫正。如果你有车牌的四个角点可以直接用cv2.getPerspectiveTransform做矫正。但 YOLOv5 只输出水平框没有角点信息。一个折中的方案是假设车牌的上下边框在检测框内基本平行用边缘检测 直线拟合来找四边形的四个顶点再做矫正。更简单粗暴的方法是对裁剪出来的车牌图做“水平拉直”。很多情况下车牌虽然倾斜但整体形变不大直接按检测框裁剪后再做cv2.warpAffine旋转让车牌长边尽量水平就能提升不少识别准确率。我实测下来在卡口场景里这个预处理能让整体识别准确率提升 3% 到 5%。5.3 性能优化与实时性考量如果需要对视频流做实时识别性能优化是绕不开的。YOLOv5s 在 GPU 上单帧推理约 10msCRNN 约 5ms加起来 15ms理论上能跑到 60 FPS。但实际中瓶颈往往在预处理和后处理上——图像缩放、颜色转换、裁剪、归一化这些步骤如果用 Python 裸写循环会吃掉大量时间。优化思路有几条。第一尽量 batch 推理视频流中连续帧可以攒一批再统一推理第二把图像 resize 和归一化放到 GPU 上做用torch.nn.functional.interpolate代替cv2.resize第三如果车牌数量多可以先用一个轻量的筛选器把没有车牌的帧直接跳过减少 CRNN 的调用次数。5.4 整体系统的模块划分与代码组织拿到这套源码时我发现它的目录结构非常典型detect/放 YOLOv5 相关代码recognize/放 CRNN 相关代码tools/放数据转换脚本inference/放完整推理脚本。这种模块化组织方式非常值得借鉴。我自己在重构的时候把流程分成了四个模块数据层负责读取和标注转换模型层负责加载和推理服务层负责封装 API 接口应用层负责对接摄像头、图片文件等输入源。如果只是做毕设不需要上 Flask 这类服务框架但保持模块划分能让答辩时讲起来更有条理。6. 常见问题与排查技巧实录6.1 训练不收敛或 loss 为 NaN这是 YOLOv5 和 CRNN 训练中最常见的问题。YOLOv5 方面loss 为 NaN 大概率是学习率过大或数据集中存在空标注文件。检查方法很简单在训练命令里加--label-smoothing 0.1试试如果还不行就检查数据集的 txt 标注文件是否有全零坐标或空文件。CRNN 方面loss 为 NaN 通常是输入图像出现了 NaN 像素值或者标签序列里有超出字符集范围的索引。建议在 DataLoader 里加一个断言检查每个 batch 的输入是否有限值。另外CTCLoss 对log_probs的数值稳定性要求较高如果网络输出里有极端值可以在 forward 最后加一层log_softmax并用torch.clamp限幅。6.2 检测框抖动和漏检问题检测框抖动在视频流里最常见表现是同一辆车前后几帧的检测框位置跳来跳去。这通常是单帧检测的固有噪声解决办法是加一个简单的跟踪平滑比如对最近 5 帧的检测框坐标取平均或者用 IoU 匹配做逐帧关联。漏检问题要分情况讨论。如果是远处的小目标漏检考虑把输入分辨率从 640 提高到 960如果是强光、逆光场景漏检建议在数据增强里加强亮度扰动并在训练数据里加入更多逆光样本。还有一种容易忽略的情况如果车牌被遮挡了一半YOLOv5 的检测框会非常不稳定此时可以适当降低置信度阈值但要做好误检增多的心理准备。6.3 识别错字的规律与对策CRNN 识别错字不是随机的它有很强的规律。最常见的是 O 和 0、D 和 Q、B 和 8 这类形状相近的字符混淆。要解决这个问题可以在训练数据里专门加入一些字符级样本或者在字符集设计时做相似字符混淆增强随机把标签里的 O 替换成 0让模型学会“看上下文”。省份汉字错误也很典型比如“皖”错成“晚”、“鲁”错成“曾”。这类错误说明模型对汉字细节的敏感度不够可以考虑在训练时对车牌图做更强的高频细节增强比如锐化。还有一个小技巧如果业务场景限定了某个地区可以在后处理时加一个省份白名单把不在白名单里的汉字直接按照相似度映射到最近允许的汉字。6.4 zip 资源包解压报错的处理这套资料打包成 zip 分发很多人在解压时遇到“file is not a zip file”或者“invalid zip archive: could not find EOCD”的报错。这个问题的根源通常是压缩包下载不完整或者文件在传输过程中被截断。EOCDEnd of Central Directory Record是 zip 文件末尾的目录记录找不到它基本可以断定文件损坏。解决方法是重新下载并检查下载文件大小是否和源文件一致。如果下载工具支持断点续传建议开启。还有一个容易踩的坑某些网盘客户端会把 zip 文件另存为 .download 后缀手动改回 .zip 后解压工具会无法识别这时候应该重新用客户端下载完成而不是手动改后缀。在 Linux 服务器上解压时用unzip命令遇到中文文件名乱码也很常见需要先设置环境变量export LANGzh_CN.UTF-8 unzip project.zip如果 zip 包是加密的unzip会提示输入密码。这类项目资源通常会在文档里说明密码注意查看 readme.txt 或 download.txt。6.5 环境配置中的“经典”报错与修复把源码从 zip 里解压出来之后运行环境配置阶段最容易出问题。先整理几个我遇到过的经典报错第一个是No module named torchvision。大概率是创建了多个虚拟环境pip 命令装到了别的环境里。检查方法是which python和python -c import torchvision同时执行确保你用的解释器和 pip 的环境一致。第二个是 CUDA 不可用torch.cuda.is_available()返回 False。先用nvidia-smi看驱动支持的 CUDA 版本再对比 torch 的 CUDA 版本。第三个是显存不足 OutOfMemoryError。解决办法是把 batch size 调小并把--workers调低减少数据加载对显存的压力。如果还不行试试在训练命令里加--cache不生效的话就检查是不是有别的进程占用了显存。6.6 高参考价值的调参速查表最后整理一份调参速查表方便你遇到问题时快速定位方向。问题现象优先检查项推荐处理方式训练 loss 不降标注质量、学习率检查标注文件降低学习率至 1e-4 重训检测 mAP 低数据量、分辨率增加数据提高输入分辨率到 960检测框乱跳置信度阈值、NMS提高阈值到 0.45降 NMS 到 0.3识别错字多字符集、矫正预处理检查字符集加透视矫正推理速度慢模型大小、预处理换 YOLOv5n优化 resize 逻辑zip 解压失败文件完整性重新下载检查文件大小一致性最后说两句整套系统跑通之后回头看最大体会是YOLOv5 CRNN 这个组合最值钱的地方不是某个模型多先进而是每个环节都极其透明出了问题能定位、能修、能改进。车牌检测不准就调检测数据识别错字就调识别数据和网络结构两边互不干扰调试效率非常高。如果你也想在这个项目上继续深挖一个值得尝试的方向是把检测和识别合并到一个 onnx 模型里做端到端加速另一个方向是把双排黄牌支持加进去这两块做完这套系统的完整度会再上一个台阶。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进