资讯详情

YOLOv5车牌检测+LPRNet车牌识别完整资源包实战解析

📅 2026/10/10 19:13:28 | 华诺云谱 👁 阅读
YOLOv5车牌检测+LPRNet车牌识别完整资源包实战解析
简介面向智能交通、安防监控等场景的开发者这份YOLOv5车牌检测与识别项目提供了从车牌定位到字符识别的完整实现方案可应用于停车场出入口、电子警察、高速卡口等实际场景。压缩包为rar格式共84个文件、约78.16MB涵盖Python训练与推理脚本、预训练权重pt/pth、YAML结构配置、XML标注以及大量JPG/JPEG测试图片覆盖数据准备、模型训练、检测与识别全流程。已有2057人学习下载适合目标检测与OCR方向的中高级开发者用于算法实践与项目二次开发。解压后可直接运行测试脚本快速在样例图片上完成车牌定位与字符识别同时可修改配置、更换数据集进行二次训练配套的LPRNet字符识别模块也为理解端到端识别原理提供了直观参考。整个包结构清晰既是一套可直接演示的Demo也可作为进一步优化车牌识别精度与速度的研究起点。1. 一套能直接跑的车牌检测识别包YOLOv5定位加LPRNet识别的完整资源停车场道闸摄像头拍到的画面里车牌往往只占整张图的百分之几要在一帧内同时完成定位和字符读取靠单一模型硬扛并不划算。这套 YOLOv5 车牌检测和识别资源包走的是双模块闭环YOLOv5 负责拉出车牌边界框LPRNet 负责把框内区域识别成字符文本压缩包里从模型配置、权重文件、测试图片到训练脚本全部给齐解压后就能在本地把整条推理链路跑起来。适合有 Python 和深度学习基础、想直接复现车牌识别效果的工程师也适合做智能交通、安防道闸、出入口管理系统的人拿来做基线项目参考。2. 双模块拆解YOLOv5怎么定位车牌LPRNet怎么读出字符2.1 YOLOv5检测管线三层特征图与四个模型配置YOLOv5 的检测思路常被概括为 Unified Detection Network把目标检测拆成边界框预测、类别概率预测和对象中心位置预测三个子任务。实际运行时输入图像先经过 Backbone 提取特征再通过 Neck 做多尺度特征融合最后在 Head 的三个不同尺度特征图上输出预测结果。小尺寸特征图负责大目标大尺寸特征图负责小目标车牌这种画面占比不大的目标主要靠中后层特征图去捕获。资源包 models 目录下放着 yolov5s.yaml、yolov5m.yaml、yolov5l.yaml、yolov5x.yaml 四个配置文件对应 YOLOv5 从小到大的四种模型规模。这四个文件的核心差异不在一行行网络结构写死而是通过两个缩放参数控制整体深度和宽度配置名称depth_multiplewidth_multiple适用场景yolov5s.yaml0.330.50实时性优先CPU也能跑yolov5m.yaml0.670.75精度速度均衡yolov5l.yaml1.001.00精度优先适合GPUyolov5x.yaml1.331.25追求极限检测效果depth_multiple 乘的是网络堆叠的 block 数量width_multiple 乘的是每层通道数。比如 yolov5s 的通道数只有 yolov5l 的一半所以参数量小、推理更快代价是对小目标和模糊目标的特征表达能力弱一些。实际项目里如果检测端算力充足我一般直接选 yolov5m 起步车牌检测不需要上到 x 级别s 和 m 之间的收益差最划算。值得留意的是配置里的 anchors 参数是在 COCO 等公共数据集上聚类出来的默认值并不完全适配车牌这种长宽比极端的目标。如果后续要自己训练车牌数据集建议先用 k-means 在车牌标注框上重新聚类 anchor再写回 yaml 文件的 anchors 字段。这个包如果直接用预训练权重做检测anchor 不匹配的影响还能被置信度阈值压住但要微调训练这一步省了效果会打折扣。2.2 LPRNet车牌识别从裁剪图到字符序列YOLOv5 输出的是车牌的位置框真正把车牌变成字符串的是 LPRNet。LPRNet 是轻量级车牌识别网络的代表结构整体思路是用 CNN 提取视觉特征接一层双向 LSTM 对特征序列做上下文建模最后用 CTC 损失函数对齐字符序列。这种设计最大的优势是不需要先做字符分割省去了定位每个字符位置的标注成本。资源包中的 LPRNet.py 就是这一模块的实现按常见结构简化后大致长这样# LPRNet.py 中的关键结构按常见 LPRNet 实现简化说明 import torch import torch.nn as nn class LPRNet(nn.Module): def __init__(self, class_num68): super(LPRNet, self).__init__() # CNN backbone逐层提取车牌字符的视觉特征 self.backbone nn.Sequential( nn.Conv2d(3, 32, kernel_size3, stride1, padding1), nn.ReLU(inplaceTrue), nn.Conv2d(32, 32, kernel_size3, stride1, padding0), nn.MaxPool3d(kernel_size(1, 2, 2)), # 中间还有若干卷积和池化层负责下采样和特征抽象 nn.Conv2d(64, 128, kernel_size3, stride1, padding1), nn.ReLU(inplaceTrue), nn.Conv2d(128, 128, kernel_size3, stride1, padding1), ) # LSTM 层对 CNN 输出的特征序列做双向建模 self.rnn nn.LSTM(128, 128, bidirectionalTrue, num_layers2) def forward(self, x): x self.backbone(x) # 经过 LSTM 后输出每个时间步的字符概率分布 return xclass_num 是字符类别总数中国车牌的字符集大概由省份简称、字母和数字组成常用字符表在 68 类左右这就是 68 的由来。如果换到香港、澳门车牌或者新能源车牌的新字符需要重新扩展字符表并对应修改 class_num。LSTM 双向建模的好处是字符之间有关联比如省份简称后面基本跟字母字母后面跟数字这种上下文信息能明显提升第二位字符的识别准确率。后面的 CTC 解码会把网络输出转换成最终字符串训练时用 CTC Loss 计算梯度推理时用贪心解码或者 beam search 取概率最高的路径。使用 CTC 意味着标注只需要给出整个车牌文本不用标每个字符的具体位置。2.3 检测与识别串联letterbox、NMS 与数据增强这一段对接上整个流程读取原始图YOLOv5 输出若干边界框NMS 去掉重复框然后按坐标裁剪出车牌区域缩放后送进 LPRNet。整套逻辑在 detect.py 中的串联方式大致是这样# detect.py 中检测分支与识别分支的串联逻辑示意 for det in pred: # pred 是 YOLOv5 输出的检测结果张量 x1, y1, x2, y2 det[:4].long() # 解析边界框四角坐标 # 按边界框从原始图像上裁剪车牌区域 plate_crop img[y1:y2, x1:x2] # LPRNet 输入尺寸固定需要先把裁剪图 resize 到 94x24 plate_resized cv2.resize(plate_crop, (94, 24)) # 调整维度顺序HWC - CHW并增加 batch 维度 plate_tensor torch.from_numpy(plate_resized).permute(2, 0, 1).unsqueeze(0).float() # LPRNet 前向推理输出每个时间步的字符概率 logits lpr(plate_tensor) # 贪心解码取每个时间步最大概率字符合并重复项 text greedy_decode(logits, class_map)这段代码里有两个关键点。第一YOLOv5 检测框的坐标必须在原始图像坐标系下裁剪不能直接拿 resize 后的图像坐标去裁否则框的位置会整体偏移。第二LPRNet 推理前图像要做归一化处理常规做法是把像素值除以 255 并缩放到 [-1, 1] 区间很多初学者在这一步漏掉归一化导致识别结果乱码。提示如果使用 YOLOv5 官方 detect.py默认输入图像会经过 letterbox 等比缩放并在四周填充灰边。此时记录 padding 参数裁剪时要把坐标还原到原图坐标系这是检测框准确命中的关键。数据增强在这套流程里也扮演重要角色。YOLOv5 训练时默认会做 mosaic 拼接、随机缩放、色彩空间扰动等增强目的是扩大训练集多样性、防止模型过拟合。车牌识别任务中光照变化剧烈白天逆光、夜晚车灯直射都会让车牌区域亮度分布差异很大训练时如果不开色彩扰动模型到了夜间场景基本会报废。资源包里的训练脚本继承了 YOLOv5 默认增强策略自己采集数据时建议保留至少 20% 的夜间和逆光样本增强数据多样性比单纯叠加增强策略更有效。3. 从推理到训练detect.py的参数边界与train.py自定义数据集3.1 环境准备依赖安装与容器化运行资源包根目录下有 requirements.txt 和 Dockerfile这是两套不同的环境准备路径。requirements.txt 适合本地 GPU 环境内容涵盖 torch、torchvision、opencv-python、pyyaml、tqdm、matplotlib 这几个核心库。Dockerfile 则把运行环境固化到容器里适合要交付给同事或部署到服务器上的场景。# 解压资源包rar 格式需要 unrar 或 7z 支持 7z x yolov5-detect_car_plate.rar cd yolov5-detect_car_plate # 方式一直接基于 requirements.txt 安装 pip install -r requirements.txt # 方式二基于 Dockerfile 构建容器镜像 docker build -t yolov5_plate:latest .我一般优先推荐 Docker 方式尤其是前后换过几台机器、被 CUDA 版本问题折磨过的人容器至少把依赖版本隔离这一步做掉了。requirements.txt 安装的 torch 版本如果和本机 CUDA 版本对不上加载权重文件时经常会报莫名其妙的错误比如在 GPU 机器上装到了 CPU 版 torch跑推理时速度慢得离谱而且没有任何报错提示。装完依赖后先跑一条 CPU 推理命令验证环境再切到 GPU能省掉大量排查时间。提示requirements.txt 中的 torch 版本往往有下限要求比如 torch1.7.0。高版本 torch 向下兼容性整体不错但 2.x 版本对部分旧代码中的 API 做了调整运行 detect.py 前最好先用python -c import torch; print(torch.__version__)确认实际版本。3.2 跑通检测detect.py 核心参数与输出目录资源包根目录的 detect.py 是检测入口weights 目录下存放训练好的权重文件test1.jpg、test2.jpg 等测试图直接放在根目录。跑一条基础推理命令python detect.py --weights weights/best.pt --source test1.jpg --img-size 640 --conf-thres 0.5 --iou-thres 0.45各参数含义如下参数取值示例作用与调整建议--weightsweights/best.pt指定模型权重路径加载 YOLOv5 检测模型--sourcetest1.jpg推理输入可以是单张图片、文件夹、视频流--img-size640letterbox 缩放目标尺寸需与训练尺寸一致--conf-thres0.5置信度阈值低于该值的检测结果被丢弃--iou-thres0.45NMS 去重阈值控制重叠框的保留策略--img-size 是第一个要确认的参数。如果训练时用的 640推理也必须是 640不能为了提速减到 320否则小目标在缩小后的特征图上信息丢失严重车牌这种本就占比不大目标可能直接漏检。--conf-thres 的调整看场景白天光照正常、车牌清晰0.5 够用夜间或者车牌模糊我会把阈值降到 0.25宁可多出几个误检框也不能漏掉真实车牌。--iou-thres 一般维持 0.45 到 0.5 之间这个参数决定 NMS 删除重叠框的力度设太大会出现同一个车牌多个检测框设太小会把旁边紧挨着的两个车牌误删成一个。运行结束后检测结果的标注图默认输出到 runs/detect/exp 目录。资源包里runs目录本身也存放了样例输出可以对比自己的推理结果和作者跑出来的效果。如果输出目录里只有图没有识别出的车牌文本说明 detect.py 默认只保存了检测框可视化结果识别文本需要额外打开保存逻辑把 LPRNet 的解码结果写入图片标题或同名 txt 文件。3.3 训练自定义数据集data.yaml 与超参数调节如果要针对特定场景训练自己的车牌检测模型核心是数据组织和 train.py。YOLOv5 的标签格式是每个图片对应一个 txt 文件每行内容为类别编号、中心点 x 坐标、中心点 y 坐标、框宽、框高坐标都归一化到 0 到 1。资源包 data 目录和 images 目录存放了样例图片可以参照其目录结构组织自己的数据集data/ ├── images/ │ ├── train/ # 训练集图片 │ └── val/ # 验证集图片 └── labels/ ├── train/ # 训练集标签与图片同名 txt └── val/ # 验证集标签组织好后写一份 data.yaml指定训练集、验证集路径和类别数# data/data.yaml train: data/images/train val: data/images/val nc: 1 names: [license_plate]然后运行训练命令python train.py --data data/data.yaml --cfg models/yolov5s.yaml --weights --batch-size 16 --epochs 100 --imgsz 640这里 --weights 参数我留空了表示从零训练而不是加载预训练权重继续微调。如果想微调可以改成--weights yolov5s.pt这样会加载 COCO 预训练模型的前面层参数在小数据集上收敛更快也更不容易过拟合。--batch-size 受 GPU 显存限制显存不够就调小 batch同时配合梯度累积来弥补--imgsz 建议和推理时的 --img-size 保持一致这样训练和推理的尺度不会出现偏差。train.py 里的超参数远不止这几个。初始学习率 lr0 默认 0.01momentum 默认 0.937weight_decay 默认 0.0005这些是针对一般目标检测任务调出来的组合。车牌数据集通常规模不大几百到几千张如果出现训练震荡优先把 lr0 降到 0.001再把 mosaic 数据增强概率调低。mosaic 增强在数据集小的情况下反而会引入过多拼接痕迹让模型学到不真实的特征。训练日志保存在 runs/train/exp 目录下权重文件 best.pt 和 last.pt 都在该目录推理时指定 best.pt 即可。4. 避坑环境、显存、识别乱码与部署精度问题排查4.1 坑位一加载权重时报 Torch not compiled with CUDA enabled这是个非常典型的报错现象是程序在model DetectMultiBackend(...)这行直接崩溃错误信息里明确写着Torch not compiled with CUDA enabled。很多人第一反应是去查代码里 device 参数实际上问题根本不在这。原因是 torch 装成了 CPU 版本。pip 默认安装 torch 时会根据当前 PyPI 上的 wheel 决定版本国内很多镜像源里默认就是 CPU 版。解决方法是先检查本机显卡驱动和 CUDA 版本再安装对应 CUDA 的 torch。推荐在 PyTorch 官网选择器里找到匹配的命令比如 CUDA 11.8 对应pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118装完后用torch.cuda.is_available()验证返回 True 说明 GPU 可用。从那以后每次在新机器配环境我都强制先跑这一步避免后面推理花了半天时间白等。4.2 坑位二LPRNet 识别结果乱码或整体错位现象是检测框完全正常但输出的字符既不匹配车牌也不是常见字符看起来完全是乱码。原因通常是字符集映射表不一致。训练 LPRNet 时的 class_num 和字符顺序映射存在一个固定的 class_map 字典推理时如果代码里的字符顺序和训练时不一致解码出的文本自然就乱了。资源包中训练脚本和识别脚本大概率共用同一份字符表但自己改动过字符集、或者直接替换了权重文件后这个映射关系容易悄悄错位。第二种常见原因是图像预处理不一致。训练时做了归一化、均值方差标准化推理时没做网络输入分布对不上输出概率分布被打乱。检查推理流程里的预处理函数是否和训练完全一致尤其是归一化的数值范围。解决方法是把预处理逻辑统一封装成一个函数训练和推理都调用它不要在两个地方各写一份。4.3 坑位三检测框总是偏移半个车牌位置现象是框能框住车牌附近区域但总偏左上或偏右裁出来的区域不是完整车牌。这种情况排查检测模型本身往往是徒劳问题大多出在图像预处理阶段。YOLOv5 推理时会用 letterbox 把图像等比缩放到 640x640不足的部分填充灰色像素。如果检测得到的坐标是在 letterbox 图上的坐标直接套用到原始图上裁剪不减去 padding 偏移框的位置就会整体偏移。解决方法是保留 letterbox 函数返回的 padding 参数推理结束后把坐标减去 padding 再除以缩放比例还原到原图坐标系。代码层面就是记录ratio, (dw, dh)然后对每个检测框做对应变换。这类问题在检测结果可视化时看不出来因为画框是在同一张 letterbox 图上画的一旦切图给 LPRNet 就露馅。4.4 坑位四训练时 GPU 显存不够直接 OOM现象是训练刚开始就跑出RuntimeError: CUDA out of memory甚至把显存占满后导致整个桌面卡死。原因多数是 batch-size 或者 imgsz 一开始设太高少数情况是显卡本身显存就小比如 4G 显存的入门卡跑默认 batch-size 16 和 640 分辨率大概率直接炸。解决路径有两条。第一条是把 batch-size 降到 4 或 8同步把 imgsz 从 640 降到 416这样显存占用会明显下降代价是模型对细节特征的提取能力弱一点。第二条是开启梯度累积比如显存只能跑 batch-size 4但想模拟 batch-size 16 的效果就在 train.py 里把累积步数设为 4每 4 个 batch 更新一次权重。如果显存依然不够最后手段是开启半精度训练 float16显存占用直接砍半但要留意模型精度可能轻微下降。4.5 坑位五模型量化后边缘设备识别精度暴跌现象是训练好的模型在 GPU 上识别率很高导出 ONNX 再转到 RK3568 或树莓派部署后漏检明显增多车牌字符错误率也上升。这个问题的根源往往不在设备而在量化策略。直接使用神经网络编译器默认的动态量化对 LPRNet 里的 LSTM 层效果尤其差因为 LSTM 的循环结构对数值精度极其敏感一旦权重被压缩到 int8隐状态传递的误差会随时间步累积。解决方法是区分量化对象。检测端 YOLOv5 用静态量化加校准数据集校准数据选 100 张以上覆盖不同光照条件的车牌图片识别端 LPRNet 优先保留 fp16 精度不强行压到 int8。如果硬件只支持 int8那就用感知量化训练 Quantization-Aware Training让网络在训练阶段就适应低精度数值范围而不是训练完再做后训练量化。这一步属于部署环节里最需要花时间的部分没有捷径可走。5. 进阶模型导出与边缘部署验证5.1 ONNX 导出与树莓派验证流程模型训练收敛后部署到边缘设备前应该先做一次完整性验证。标准流程是先把权重导出成 ONNX 格式在树莓派等 ARM 设备上跑一遍 onnxruntime确认输出与 GPU 推理基本一致再做 RK3568 的 RKNN 转换。这样可以把问题分层排查不至于直接跳到 RKNN 阶段分不清是转换问题还是网络本身的问题。# 导出 ONNX 模型 python export.py --weights weights/best.pt --img-size 640 --include onnx # 树莓派上安装 onnxruntime 后做推理验证 onnxruntime 推理脚本对比输出量化这一步我会盯紧精度损失。一般建议以 GPU 上的 mAP 为基准边缘设备量化后 mAP 下降控制在 2% 以内才判断为正常。超过 2%先增加校准图片数量再检查是否 LPRNet 被过度压缩。对 RK3568 这类 NPU 设备YOLOv5 检测端走到 rknn-toolkit 转换时注意设置正确的量化精度和输入格式NCHW 和 NHWC 的转换容易在中间抠掉细节。从那以后我每次做完训练都会强制走一遍导出 ONNX、在 CPU 和 GPU 上对比精度、再量化部署的流程这套流程帮我把边缘部署的返工率压到了很低。车牌检测识别这类任务对实时性和精度的双重需求决定了理论和实际部署之间总有一段路要走希望这套资料能帮你少走一段弯路也希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑