ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLOv5车牌识别实战:从数据集标注到模型部署的完整指南

YOLOv5车牌识别实战:从数据集标注到模型部署的完整指南 简介目标检测是计算机视觉中的核心任务而车牌识别作为典型的落地场景融合了目标检测与OCR技术。YOLOv5凭借快速的推理速度和良好的精度平衡成为构建车牌识别系统的热门选择。文章阐述了两阶段识别的原理先通过YOLOv5定位车牌区域再结合字符识别模型完成文本输出。这一技术广泛应用于智能交通、停车场管理和安防监控等领域。围绕工程实践详细介绍了环境配置、数据集标注格式、模型训练参数调整以及推理部署中的常见问题与优化技巧帮助开发者在实际项目中快速构建高效可靠的车牌识别系统。 做车牌识别项目第一步选型就劝退了不少人。作为计算机深度学习领域很经典的一个落地场景车牌识别通常分成两段先检测出车牌在画面里的位置再识别车牌上的字符。我一开始选择了YOLOv5做检测配合后面的OCR模块完成整体识别。这篇文章就把我实际跑通过的一条完整链路分享出来从环境安装、数据集标注、模型训练到字符识别和部署踩过的坑都会写清楚。如果你现在正要接触YOLOv5车牌识别或者已经卡在某个环节可以照着这篇文章一步步走。整个过程不需要多高深的数学基础能把Python和基本命令行玩明白就行。1. 项目整体设计与方案选型1.1 车牌识别本质上是“检测 识别”的两段式任务很多人以为车牌识别是一个模型一步到位实际不是。摄像头拍到的画面里有车、有行人、有背景如果直接用一个模型去识别车牌字符模型会非常懵。更合理的思路是先用目标检测模型定位车牌区域再把裁剪出来的车牌小块交给识别模块。这个思路在工程里叫“两阶段识别”虽然看起来多了个步骤但每个阶段的模型都更简单、更容易训练精度反而更高。我这边的流程是这样摄像头或者图片输入到YOLOv5模型模型输出若干个矩形框每个框带着置信度和类别我根据置信度筛选出车牌框用仿射变换把倾斜的车牌矫正成水平方向再把矫正后的图片送给一个车牌字符识别模型最终得到类似“苏A12345”的字符串。两段模型独立训练也可以独立替换灵活性很高。1.2 为什么选择YOLOv5而不是其他目标检测算法做目标检测可选的方案很多两阶段的Faster R-CNN、单阶段的SSD、YOLOv3、YOLOv5甚至YOLOv8。我选YOLOv5主要是三个原因第一YOLOv5是目前社区生态最成熟的YOLO分支之一网上关于它训练自己数据集的中文教程非常多遇到问题很容易搜到答案。第二YOLOv5在模型大小、推理速度和精度之间取得了很好的平衡尤其YOLOv5s这个版本只有大约14 MB的权重文件在普通显卡上推理一张图只要几十毫秒部署到边缘设备也很有希望。第三YOLOv5的代码封装得很友好训练、验证、导出都能够通过命令行参数完成不需要自己写太多底层逻辑非常适合快速验证项目。做个简单对比Faster R-CNN精度不错但推理速度相对慢实时性场景不好用SSD速度还行但检测小目标能力偏弱而车牌在画面里往往占比小容易漏检YOLOv5的multi-scale和anchor机制对中小目标更友好。当然如果你现在动手做也可以直接用YOLOv8接口风格差异不大。我这篇文章还是围绕YOLOv5因为用的人多参数和权重更好找。1.3 整体技术架构和模块拆解整个项目我分成四个模块数据准备、检测模型、字符识别模型、部署服务。数据准备负责采集车牌图片并标注检测模型负责从原图找到车牌框字符识别模型负责把车牌图变成文本部署服务则是把两个模型串起来对外提供接口。模块之间用统一的数据格式对接检测模型输出的是坐标框识别模型输入的是裁剪图输出的是字符串。这种架构的好处是每个模块都能单独测试。比如检测不准我先检查是漏检还是误检识别不准我只需要固定裁剪图单独调识别模型。如果采用端到端方案出了问题反而很难定位。工程上我强烈建议先用两阶段跑通确保整个链路能工作再考虑后续优化。2. 环境准备与依赖安装2.1 硬件和系统说明在开始装环境之前先看看你的机器条件。我这次用的是一台Ubuntu 20.04系统的电脑显卡是NVIDIA GeForce RTX 306012 GB显存。如果你用的是Windows安装步骤类似但sudo命令要换成管理员权限的命令行路径写法上也有一点差异。没有NVIDIA显卡也没关系YOLOv5支持CPU训练只是速度会慢好几倍训练100轮可能要好几天建议先用小数据集验证流程再考虑是否换机器。需要提前安装的东西有Python、Anaconda或Miniconda、NVIDIA驱动和CUDA。建议不要自己单独配CUDA直接通过conda安装PyTorch时会自动带上对应版本的CUDA runtime省心很多。如果要训练大规模数据显存最好8 GB以上否则batch size一开始就会卡脖子。2.2 创建虚拟环境并安装PyTorch我习惯用conda创建独立环境避免和系统环境打架。命令行里依次执行conda create -n yolo python3.9 conda activate yolo pip install torch1.13.1 torchvision0.14.1 --index-url https://download.pytorch.org/whl/cu117PyTorch版本不需要追求最新稳定就行。装完可以用一段简单代码验证GPU能不能用import torch print(torch.__version__) print(torch.cuda.is_available())如果输出True说明GPU环境正常。这一步卡住的人很多常见原因要么是显卡驱动版本太老要么是PyTorch版本和CUDA不匹配。注意查看驱动支持的CUDA版本用nvidia-smi能看到右上角的CUDA VersionPyTorch的cu版本不要高于它。2.3 下载YOLOv5源码并安装依赖YOLOv5的源码在GitHub上可以直接用git克隆下来git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt安装的依赖包括openpyxl、matplotlib、opencv-python、pillow等。这里有个小坑requirements.txt里可能会安装一部分包的默认版本如果你机器上已经有其他深度学习项目建议先创建独立环境再安装避免版本冲突。装完之后可以跑一下官方自带的检测脚本拿一张测试图片验证环境是否OKpython detect.py --source data/images/bus.jpg --weights yolov5s.pt如果运行正常在runs/detect/exp目录下能看到带检测框的结果图。这一步能顺利通过说明基本环境没问题。3. 车牌数据集的准备与标注3.1 数据集来源与整理建议车牌识别模型的性能上限很大程度由数据决定。公开数据集方面比较常用的是CCPD中国城市车牌数据集里面有几十万张带车牌标注的图片适合做检测训练。但CCPD的标注文件不是YOLO格式需要转换一下。如果你有具体的应用场景比如停车场出口、高速公路抓拍最好自己采集一批对应场景的图片公开数据集很难覆盖所有角度和光照条件。无论用哪种数据第一步都要清洗。把模糊到完全看不清车牌的图片删掉把车牌被严重遮挡的图片去掉重复图片也要去重。我一般先人工快速浏览一遍再用脚本计算感知哈希删除相似度过高的图。数据质量比数据量重要喂给模型一万张干净图片效果可能比三万张混杂图片还好。3.2 标注工具和YOLO格式说明标注工具我用的是LabelImg简单实用。打开一张图片画矩形框把车牌包住类别设为plate保存后会自动生成一个同名的txt文件。YOLO格式的标注文件每行表示一个目标格式为class x_center y_center width heightclass是整数类别序号从0开始x_center、y_center、width、height都是相对于图片宽高的比例范围在0到1之间。比如一张宽1920高1080的图片车牌中心点坐标是(960, 540)框宽高是(200, 60)对应的txt内容就是0 0.5 0.5 0.10417 0.05556这里200除以1920约等于0.1041760除以1080约等于0.05556。数值都不带单位模型训练时会统一缩放到640×640分辨率所以标注时使用的坐标必须基于原图不要先裁剪再标注。3.3 数据增强策略与样本均衡YOLOv5内置了很多数据增强策略包括马赛克Mosaic、随机翻转、缩放、色彩空间调整等。训练时不需要额外写增强代码默认就会开启。不过车牌这类目标有特殊性车牌字符本身颜色对比度高但容易受到光照和角度影响。我建议在训练时增加一点亮度调整和模糊增强模拟夜间和运动模糊场景。另外要留意样本均衡。如果训练数据里绝大多数是蓝色牌照只有少量黄色和绿色牌照模型对后者的检测效果会明显偏差。我的做法是在准备数据时把少见类别单独复制并做一点轻度增强让它们占比至少到5%到10%。车牌检测只有一类的话问题不大如果后续还要区分类型那就得注意类别均衡。4. 模型训练的关键配置与实操4.1 修改数据配置文件和模型结构文件训练YOLOv5之前需要准备好两个yaml文件。第一个是数据配置文件一般放在yolov5/data目录下内容是数据路径和类别列表。我的carplate.yaml如下train: /home/user/datasets/carplate/images/train val: /home/user/datasets/carplate/images/val nc: 1 names: [plate]paths必须是绝对路径或者相对yaml文件位置的路径否则训练时读不到图片。第二个是模型配置文件例如models/yolov5s.yaml主要修改nc为1和数据集保持一致nc: 1 depth_multiple: 0.33 width_multiple: 0.50如果你只是检测车牌不需要改动网络结构只改nc即可。注意不要直接把官方预训练权重里的类别数覆盖掉训练时会通过yaml里nc决定最后一层输出的维度。4.2 训练命令和超参数选择训练命令我经常这样写cd yolov5 python train.py --img 640 --batch 16 --epochs 150 --data data/carplate.yaml --weights yolov5s.pt --name carplate--img表示训练时输入的图片尺寸默认640。如果车牌在画面中占比很小可以适当提升到800或者960但显存和训练时间也会随之增加。--batch要结合显卡显存调整显存吃紧就先从8开始。--epochs看数据集量级1万张以下建议100到150轮数据量大可以适当减少。超参数方面我一般保持默认学习率初始0.01最后用余弦退火降到很低。真正需要调整的是anchor尺寸。YOLOv5会自动学习anchor但如果你的车牌宽高比非常极端例如长条形的框占了大多数训练时加上--noautoanchor选项然后再微调anchor参数可能更稳定。不过对绝大多数情况默认auto anchor已经够用。4.3 训练过程监控与结果评估训练过程中会输出每个epoch的loss、精度等指标同时会在runs/train/carplate目录下保存训练曲线图。我需要重点关注的是val精度和召回率。如果loss下降缓慢或者不下降先别急着改模型检查一下数据标签有没有问题。一个常见错误是标注框坐标归一化时写错成像素坐标导致loss巨大。训练结束后验证一下效果。YOLOv5自带验证脚本python val.py --data data/carplate.yaml --weights runs/train/carplate/weights/best.pt --img 640重点关注mAP0.5和mAP0.5:0.95。车牌检测属于单类目标mAP0.5到0.95一般能到0.9以上才算合格。如果检测框经常把整辆车框进去说明回归方向有问题可能是标注框不准确。看到误检和漏检我建议先用detect.py跑几张测试图打印出检测框坐标和置信度再对照原图分析。5. 车牌后处理与字符识别5.1 从检测结果到车牌裁剪检测模型输出的信息是归一化的坐标框需要还原成原图坐标然后裁剪出车牌区域。代码逻辑不复杂import cv2 import torch # 假设det为模型输出包含xyxy格式的相对坐标 x1, y1, x2, y2 det[0][:4].tolist() h, w img.shape[:2] x1, y1, x2, y2 int(x1 * w), int(y1 * h), int(x2 * w), int(y2 * h) plate_img img[y1:y2, x1:x2]这里有一个细节如果车牌是倾斜的直接裁剪出来的矩形框会包含很多背景和多余区域影响后续识别。我通常会在得到框之后用OpenCV找到车牌区域的四个角点然后做透视校正。如果只是简单项目可以先用图像边缘检测加轮廓查找来获得车牌的最小外接矩形再通过仿射变换转正。这一步对识别率的提升非常明显。5.2 字符识别方案对比OCR框架 vs 自建分类器车牌字符识别可以分成两种路线。第一种是直接用现成OCR框架比如PaddleOCR、Tesseract。优点是上手快但中文车牌的汉字识别效果不一定好需要额外微调。第二种是自己训练一个轻量级识别模型输入是车牌图片输出是字符串通常用卷积网络加循环网络比如LPRNet。这个方案可控性和识别率更高但需要准备字符级别的标注数据。我这次选择的是LPRNet的思路先把车牌图缩放到统一尺寸比如宽94高24然后输入到一个轻量CNN网络网络输出32个字符位置的分类概率最后用CTC解码得到字符串。LPRNet结构不复杂只有几层卷积在CPU上也能跑到毫秒级。如果你不想从零训练可以先下载一个开源预训练模型再针对自己的车牌格式做微调。5.3 字符分割与常见识别错误处理传统字符识别方案是先把第二个字符后的汉字和字母数字逐个分割出来再用CNN分类。分割的关键是找字符之间的连通域但车牌铆钉、边框和污渍会干扰。现在更多使用基于CTC的序列识别不需要显式分割字符鲁棒性好很多。我用了LPRNet之后确实省掉了分割步骤。不过车牌识别依然有绕不开的坑数字0和字母O极易混淆1和I也是。建议根据车牌规则兜底比如第二位字符在民用车牌中是字母不会出现数字如果模型输出“0”可以纠正为“O”。汉字部分如“京”和“津”、“沪”和“泸”在模糊情况下也容易错如果项目允许可以加入基于车牌发牌规则的校验把不合法省份字符排除掉。6. 推理部署与常见问题排查6.1 导出模型并搭建推理接口训练好的检测模型可以导出成TorchScript或ONNX格式方便在更多环境部署。我一般先导出ONNX再根据目标设备选择运行时。导出命令python export.py --weights runs/train/carplate/weights/best.pt --include onnx --img 640导出的onnx文件可以用onnxruntime库加载推理速度比直接跑PyTorch快不少。搭一个简易接口时我会把检测和识别封装成一个类对外只暴露一个process_image方法输入图片路径或numpy数组输出车牌字符串和坐标。这样就算不写Web服务也能方便地集成到其他代码里。6.2 性能优化小技巧车牌识别通常用在实时监控或门禁场景性能很重要。几个我自己实测有效的方法第一检测和识别模型都转为FP16精度速度提升接近一倍第二把输入图片尺寸从1080p压缩到适合的最小尺寸例如1280或640检测精度几乎不受影响第三对视频流做帧间隔采样例如每3帧检测一次用跟踪算法如DeepSORT补足中间帧可以大幅降低计算压力。如果设备是边缘盒子比如瑞芯微RK3568这类平台YOLOv5模型可以先用ONNX转换成RKNN格式再进行量化。量化后模型文件变小但精度会有一定损失需要重新验证。总之性能优化要结合硬件来调没有一套配置通吃所有设备。6.3 常见问题速查表我整理了训练和部署过程中最容易踩的坑格式做成表格方便速查。问题现象可能原因解决办法训练loss居高不下标注格式错误类别数不匹配检查txt标注是否归一化nc是否正确显存不足无法训练batch size过大输入尺寸过大减小batch或设置--img 512检测框框住整辆车标注框偏大模型学到上下文重新检查标注收紧车牌框边界检测不到小尺寸车牌图片被resize后车牌过小提高输入分辨率或使用更大scale的模型车牌子颜色干扰识别光照过强字符对比度低增加图像增强或先做灰度均衡字符识别把0识别为O分类混淆根据车牌规则强制校正部署环境没有GPUONNX / CPU推理慢使用INT8量化或挑选更小模型结构有了这张表很多问题能省去排查时间。遇到新问题记得先看训练日志和输入输出别盲调参数。7. 项目扩展方向与个人实践体会7.1 拓展多类型车牌和车辆属性识别如果你之后不满足于单纯的车牌检测可以继续扩展。比如同时检测车辆类型轿车、卡车、SUV、车身颜色、车牌颜色或者识别新能源车牌和大型车黄牌。检测模型只需要增加类别数数据标注也要跟上。这个扩展思路对停车场管理和路侧停车收费场景非常实用。我在测试时发现同时输出多个属性并不会增加太多推理耗时因为都是在同一个检测模型上增加类别头关键是数据要准备充分。7.2 低光照与恶劣天气下的增强车牌识别在夜间或者雨雾天气最容易翻车。除了提升训练数据多样性我还会在推理链路中加入一个轻量的图像增强模块比如自适应直方图均衡或者零深度降噪模型。注意不要过度处理否则车牌本身的对比度也会被改变。一个简单的经验是判断车牌区域的平均亮度如果低于某个阈值再做增强否则保持原图。7.3 从YOLOv5到更轻量模型的迁移思路当项目要落地到嵌入式设备时YOLOv5s可能还是有点大。此时可以尝试剪枝、蒸馏或者换用YOLOv5n、YOLOv8n这类更小模型。我在一个边缘盒子上测试过把YOLOv5s换成YOLOv5n之后检测速度提升了40%左右mAP只下降了2个点对车牌这种单一目标影响不大。但要注意小模型对远距离小目标更敏感部署前要拿真实场景的图片多做测试不能只看公有数据集指标。从我个人经验来看YOLOv5车牌识别这个项目最适合作为深度学习的入门实战项目因为它每个环节都能拆开学习目标检测、图像分类、序列识别、模型部署全覆盖。如果只跟着教程写完代码进步有限真正打开一张图片从标注到自己的模型识别出第一个车牌那感觉和看别人的截图完全不一样。过程中遇到问题不要慌检查数据、检查标注、检查环境和版本九成问题都是这三类。本文还有配套的精品资源点击获取
返回列表