ARTICLE DETAIL

资讯详情

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

YOLOv5车牌识别Python毕业设计:环境搭建、训练调参与避坑全攻略

YOLOv5车牌识别Python毕业设计:环境搭建、训练调参与避坑全攻略 简介面向毕业设计的YOLOv5车牌识别Python项目源码包集成深度学习目标检测与OCR字符识别覆盖从车牌定位、模型微调到实时推理的完整流程适合计算机视觉方向课程设计与毕业设计。项目以YOLOv5为检测核心涉及卷积神经网络原理、数据标注与数据集划分、训练参数调整、目标框预测、车牌字符OCR识别以及mAP/精确率/召回率评估等关键环节。压缩包共78个文件约345.91MB主要包含Python脚本、PyTorch模型权重、YAML配置、图片与视频测试样例、Dockerfile及运行说明目录结构清晰便于直接复现。目前已有1504人学习/下载。其中内置可运行的训练与实时检测脚本、预训练权重、测试数据和文档可支撑毕业设计的功能演示、实验对比与论文撰写也适合研究生或开发者作为车牌识别项目的起步模板。1. YOLOv5车牌识别Python毕业设计一套从环境到答辩演示的完整做法毕业设计选车牌识别是车联网与智能交通里少有的“数据公开、效果直观、答辩好讲”的方向。YOLOv5作为检测模型在这类任务里属于性价比最高的选择Anchor、NMS这些底层逻辑官方仓库已经写好复现门槛低资源占用又比更新的YOLO版本友好。下面按真实落地的顺序讲清楚三件事环境怎么搭最省时间标注数据从哪来、标签格式长什么样训练时哪些参数必须动、哪些坑几乎人人都会踩。适合正在赶进度的本科生也适合想快速跑通车牌检测的开发者。整个过程不依赖付费算力一张普通游戏显卡甚至纯CPU都能撑到出结果。2. 环境与数据集准备从Python环境到车牌标注数据的落地步骤2.1 Python环境与YOLOv5依赖安装三分钟装到能跑train.py常见的做法是先用Anaconda建一个独立虚拟环境。车牌识别项目离不开PyTorch而PyTorch不同版本对Python版本有硬性要求独立环境能把版本冲突降到最低。我一般选择Python 3.8到3.10之间太新或太旧都容易在编译扩展包时碰到“缺头文件”的报错。网上那些python安装教程大多只讲到解释器装好为止实际项目里更要紧的是把conda命令调通后续创建环境才不会卡住。conda create -n lpr python3.9 -y conda activate lpr pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt这段命令依次完成四件事创建并激活名为lpr的虚拟环境安装与CUDA 11.8对应的PyTorch拉取YOLOv5官方仓库安装训练所需的全部Python依赖。如果你的机器没有NVIDIA显卡把第三行换成不带--index-url的普通安装走CPU版本即可但训练速度会慢一个数量级建议训练阶段用云GPU本地只跑推理。requirements.txt里已经包含opencv-python、pycocotools、pandas这些常用库所以不需要再单独执行“python下载cv2”之类的操作依赖里已经配好了。如果你的PyCharm在运行脚本时报ModuleNotFoundError多半是解释器没指到刚建的conda环境。打开设置里的Project Interpreter选“Conda Environment”并指向lpr环境这就是常说的pycharm配置python环境不做这一步IDE里会一直报红命令行能跑但编辑器跑不了。装完后在终端执行python -c import torch; print(torch.cuda.is_available())输出True说明GPU可用输出False说明当前是CPU状态先检查CUDA版本和驱动是否匹配再决定要不要重装PyTorch。提示项目目录整体不要放在中文路径或带空格的路径下。opencv对中文路径的兼容性很差这一步能省掉后面百分之八十的路径类报错。2.2 车牌数据集与标签格式CCPD还是自己标注数据是这一步最可能翻车的地方。网上很多标注为“免费python源码大全”的项目数据集要么是几年前的旧版本要么下载链接已经失效。车牌识别的公开数据集里CCPDChinese City Parking Dataset是公认的蓝牌检测基准包含大量真实停车场场景图片覆盖倾斜、模糊、夜间等复杂条件。对毕业设计来说不需要用全量数据随机取其中一部分平衡样本即可。CCPD有一个非常省事的特性文件名本身就是标注。文件名大致由编号、车牌号、车牌四角坐标、图片宽高、时间、类型等字段用短横线拼接而成其中四角坐标字段形如154383_386473_177454_363402用连接横纵坐标用_连接四个顶点。下面的脚本能从文件名中直接解析出车牌包围框并写出YOLO训练需要的txt标签省去手工标注的时间。import os src_dir CCPD2020/ccpd_all # 原始图片目录 label_dir labels/train # 输出标签目录 os.makedirs(label_dir, exist_okTrue) for img_name in os.listdir(src_dir): if not img_name.endswith(.jpg): continue parts img_name.split(-) # 第3段是车牌四角坐标四个顶点之间用_分隔 points parts[2].split(_) xs, ys [], [] for p in points: x, y map(int, p.split()) xs.append(x) ys.append(y) # 不同CCPD版本字段顺序略有不同先打印parts核对后再批量跑 img_w int(parts[-3]) # 图片宽度 img_h int(parts[-2]) # 图片高度 x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) x_center (x_min x_max) / 2 / img_w y_center (y_min y_max) / 2 / img_h box_w (x_max - x_min) / img_w box_h (y_max - y_min) / img_h txt_name os.path.splitext(img_name)[0] .txt with open(os.path.join(label_dir, txt_name), w) as f: f.write(f0 {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}\n)脚本逻辑是读文件名按短横线拆字段从坐标字段里解析出四个顶点的x、y值再取外接矩形作为车牌框。这里取外接矩形而不是直接拟合四边形有两个原因一是YOLO标签只支持水平矩形框YOLOv5原生内置的检测头不输出旋转框二是车牌在停车场场景里即使有轻微倾斜外接矩形的精度也足够训练用字符识别阶段再做校正即可。标签格式一行表示一个目标依次是类别编号、归一化中心点x、中心点y、归一化框宽、归一化框高。注意一个细节parts[-3]和parts[-2]是按常见CCPD版本取图片宽高不同版本的字段顺序可能会有出入。批量转换前先打印一条文件名和parts列表人工核对坐标是否落在图片尺寸范围内再用随机几张图把框画回原图检查。我自己习惯用cv2.rectangle画几条看看框贴合车牌边缘才算通过。这个校验动作花不了两分钟却能避免后面训出一个“框全偏了”的模型。数据准备好之后还需要一个YOLOv5的数据配置文件内容如下保存为data/plate.yamltrain: /absolute/path/to/dataset/images/train val: /absolute/path/to/dataset/images/val nc: 1 names: [plate]这里的train和val推荐写绝对路径。很多新手写相对路径换一个终端启动目录就报“Dataset not found”。nc是类别数当前只识别车牌一个类别所以是1如果要做“车辆车牌”双目标检测就改成nc: 2并把names补成[car, plate]。数据划分按8:1:1随机抽就行但一定要保证训练集和验证集没有同一张图后面避坑章节会再讲这个问题的严重性。3. 训练与调参YOLOv5车牌识别的核心命令与四个必调参数3.1 用train.py发起训练命令、输出与怎么判断训练正常数据、标签、配置文件就位后训练命令本身并不复杂。在YOLOv5仓库根目录执行train.py把数据配置和预训练权重传进去即可。常见做法是先用yolov5s这个轻量版本跑通流程再根据显存和精度需要决定要不要换更大的模型。python train.py \ --data data/plate.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --project runs/train \ --name plate_exp1命令里--data指向刚才写的yaml配置--weights用官方预训练权重这是迁移学习的关键比从零开始训练收敛快很多通常在几十轮内就能看到可用结果--img 640是输入分辨率车牌属于整张图里占比不大的目标640是速度和精度的折中--batch 16在8GB显存上比较稳定显存紧张就降到8或4--epochs 100对单类别车牌检测绰绰有余跑满后会触发早停或自动停止--project和--name指定输出目录这样多次实验不会被互相覆盖。训练启动后不要只盯着进度条。每一轮结束会打印P、R、mAP50、mAP50-95这几列P是精确率表示检出的框里真正是车牌的比例R是召回率表示真实车牌里被找回来的比例mAP50是IoU阈值0.5时的平均精度均值对车牌任务这个值能稳定到0.95以上才算合格。训练完成后在runs/train/plate_exp1目录下会看到best.pt和last.pt两个权重前者按验证集指标择优保存后者是最后一轮的结果后续推理一律用best.pt。如果想看得更直观用TensorBoard打开runs/train/plate_exp1目录或者直接翻输出目录下的val_batch0_labels.jpg和val_batch0_pred.jpg。这两张图分别是标注框和预测框的可视化对比如果预测框能贴合车牌边缘、没有把车灯或反光区域当成车牌说明模型定位能力已经达标。如果训练集上P、R都很高验证集上R明显偏低说明过拟合已经开始了常见处理是调低epochs或提前早停但车牌检测这类单目标任务数据量够大时更值得先检查验证集划分是否干净而不是急着加正则。3.2 最值得动的四个参数img、batch、epochs、weights选型逻辑很多人在调参阶段喜欢把所有参数都试一遍结果浪费时间还看不出规律。对于车牌识别这个具体任务真正值得动的主要是四个参数。参数推荐值调参方向--img640小目标多可以升到960实时需求降到416--batch16显存不足降到8或4不建议盲目调大--epochs100看mAP50趋势连续多轮不涨就提前停--weightsyolov5s.pt精度优先换yolov5m单目标不建议上yolov5l先解释--img。车牌检测的目标尺寸在整幅画面里通常只占几十分之一分辨率太低时车牌在特征图上可能只有几十个像素小目标特征很容易被卷积层吃掉。640对大多数停车场场景够用如果画面里车牌特别小且模糊可以把--img升到960代价是推理时间明显增加反过来如果做实时摄像头识别416可以换来更高的帧率准确率会略有下降。一个值得养成的习惯是训练和推理时用同一个img尺寸很多答辩翻车现场就是训练用640、推理用默认的416结果框的位置忽左忽右。再看--batch。它决定一次前向传播处理多少张图batch越大梯度估计越稳定但显存占用也越高。8GB显存配--img 640时batch 16是稳定值如果显存报OOM优先降batch而不是降分辨率因为分辨率对精度的影响更直接。--epochs配合早停机制用YOLOv5默认会在验证指标连续多轮不改善时自动停止训练所以100轮的配置通常不会真的跑满。最后是--weights的选型yolov5s在COCO上预训练过特征提取能力足够车牌检测目标单一不需要更深的网络结构去拟合几十个类别。实测中yolov5s在车牌上的精度和yolov5m差距很小但推理速度快不少。只有当你需要同时识别车牌、车辆类型、车身颜色等多类目标时才值得换yolov5m。训练完成后进入推理阶段官方仓库用detect.py命令如下python detect.py \ --weights runs/train/plate_exp1/weights/best.pt \ --source dataset/images/test \ --conf 0.4 \ --save-txt \ --project runs/detect--source可以是图片目录、单张图片、视频文件也可以是摄像头编号0--conf 0.4是置信度阈值低于这个值的框会被丢弃太低会输出一堆误检框太高则容易漏掉模糊车牌--save-txt会把每个目标的类别、坐标、置信度写入txt文件方便后续接车牌字符识别流水线。跑完之后去runs/detect目录看输出图重点检查两个指标有没有把车灯、进气格栅当车牌以及倾斜车牌的框是不是只包住了一半。4. 车牌识别项目里最常翻车的七个坑现象、原因与修复4.1 数据与路径上的三个坑先说第一个坑中文路径导致训练直接崩溃。现象是数据集放在类似D:\车牌识别\data的目录下训练一启动就报错说数据集找不到或者读图时抛异常中断。原因在于YOLOv5的图片读取链路走的是opencvopencv对中文路径支持很差很多依赖库也默认按UTF-8解析路径。解决方式没有玄学就是整个项目、数据集、虚拟环境全部放到纯英文路径下目录名不要带空格这是最省事的做法。很多人在这一步耗掉半天最后发现只是路径问题。第二个坑是数据源只有图片没有标签。网上很多标着“免费python源码大全”的压缩包解压后只有一堆jpg没有对应的txt或xml。现象是训练能正常开始但每一轮的P和R都是0loss迟迟不下降。原因很简单模型看到的每张图都没有标注框等于在学“背景里没有目标”。解决方法是先用2.2的脚本解析CCPD文件名生成标签如果是普通图片用LabelImg人工标注保存时选择YOLO格式而不是PascalVOC格式。拿到任何数据集先统计labels目录里的txt数量和图片数量是否一致这个动作能帮你省下一整天的无效训练时间。第三个坑是训练集和验证集数据交叉。现象是训练时loss正常验证集mAP高得离谱但拿一张新拍的照片去测就漏检。原因是划分数据集时没有去重同一个车牌的多张不同照片或者同一张图同时出现在训练集和验证集。解决方式是划分前按文件名做一次去重检查确保两个集合没有交集如果数据是按时间序列拍摄的建议按时间切分而不是随机切分这样验证集更接近真实场景。这个坑最隐蔽因为训练日志看起来一切正常只有到现场测试才会暴露。4.2 训练过程中的两个坑第四个坑是loss出现NaN或剧烈抖动。现象是前几十轮一切正常某轮开始loss变成nan之后再也回不来。原因集中在两方面学习率过大导致梯度爆炸或者数据集里混入了几张损坏图片opencv读到半张图就返回空矩阵。解决方式是在训练命令里加--lr0 0.005试一轮同时写一个几行的脚本遍历数据集把读不出来的图片全部挑出来删掉。这类问题不常发生但一旦出现会直接浪费几个小时我的建议是训练前先做一次图片完整性检查属于成本极低、收益极高的防御性操作。第五个坑是预测框只框住半张车牌。现象是对新能源绿牌这种双层车牌模型输出的框经常只覆盖上半部分或下半部分对蓝牌却表现正常。原因是数据分布问题CCPD以蓝牌为主绿牌样本占比太低模型学到的框形偏向蓝牌的宽高比。解决方式不是在调参上较劲而是往数据集里补充绿牌样本并按比例保证绿牌占比不低于百分之十标注时把双层车牌的上下两部分都框进去。这个坑让我意识到很多看起来像参数问题的情况本质是数据分布问题先看数据再调参是更高效的路。4.3 推理演示时的两个坑第六个坑是摄像头实时检测卡到十几帧。现象是用detect.py直接跑摄像头视频流画面明显延迟GPU利用率忽高忽低。原因是读帧和推理在同一个线程里同步执行摄像头读一帧、模型推一帧互相等待。解决方式是用生产者消费者模式读帧线程持续往队列里塞帧推理线程只取队列里最新的一帧丢掉积压的旧帧如果还想更快把--img降到416。毕业设计做现场演示前务必在目标机器上测一次摄像头笔记本自带摄像头和USB摄像头的帧率表现差别很大。第七个坑是视频里车牌框抖动时有时无。现象是同一辆车从远到近开过来远处没框、近处有框或者框的尺寸忽大忽小。原因是conf和iou两个阈值没配合好conf太低会有一堆误检太高又漏掉小目标iou阈值影响NMS合并相邻框的行为设得不对会导致同一个车牌被重复框选。解决方式是以--conf 0.4为起点配合--iou 0.45到0.5逐步调整每改一次跑同一段视频对比不要同时动两个参数否则你不知道是谁在起作用。如果发现小目标在远处总漏优先把输入尺寸从640升到960这比调阈值更有效。5. 把模型包成演示工具答辩自测清单与一个能跑的车牌识别界面5.1 用Flask做一个上传图片就能识别的页面训练完成后离现场演示还差一层包装。常见做法是用PyQt5做桌面客户端或者用Flask做一个Web页面两者的核心逻辑都是加载best.pt、读入图片、推理、把结果画出来。我一般优先推荐Flask因为环境依赖更少答辩现场换一台电脑装依赖也更省事。import cv2 import torch from flask import Flask, request, render_template_string model torch.hub.load(ultralytics/yolov5, custom, pathruns/train/plate_exp1/weights/best.pt, force_reloadFalse) app Flask(__name__) app.route(/, methods[GET, POST]) def index(): if request.method POST: # 实际项目中用 BytesIO 解码上传文件这里简化为直接读路径 img cv2.imread(request.files[file].filename) results model(img, size640) results.render() # 把预测框画到原图上 cv2.imwrite(static/out.jpg, img) return render_template_string(上传一张图片查看识别结果) app.run(host0.0.0.0, port5000)代码只有二十行左右却把“模型加载-推理-画框-展示”这条链路跑通了。torch.hub.load的参数里custom表示加载本地权重文件path指向best.ptforce_reloadFalse避免每次启动都重新拉取依赖。results.render()没有返回值它会直接在传入的图片对象上绘制预测框所以后面接cv2.imwrite保存的就是带框的图。size640必须和训练时的输入尺寸保持一致不一致时模型会自动缩放但精度会有损耗。5.2 答辩前按这份清单自测现场翻车往往不是模型问题而是流程问题。我建议在答辩前一天按下面五条过一遍第一在测试集上跑一次完整评估确认mAP50大于0.9第二统计单张图片的平均推理耗时确保演示时每张结果在1秒内返回第三找几张夜间、逆光、倾斜车牌的图片各测十张记录正确检测率第四传一张没有车牌的路面图片确认不会误检第五检查演示笔记本的摄像头和依赖环境提前装好requirements.txt。我的习惯是训练一跑起来就先做这个演示壳子而不是等模型调到完美再动手。因为模型精度不够可以换更长时间重训但现场演示如果卡在依赖问题或界面逻辑上那才是没有后悔药的时刻。希望帮到你。本文还有配套的精品资源点击获取
返回列表