
简介本资源为基于YOLOv5的深度学习车牌识别系统本科毕业设计论文文档面向计算机、人工智能及相关专业需要完成毕业设计的学生以及希望了解深度学习目标检测落地应用的开发者。论文围绕图像采集、预处理、模型训练、车牌定位、字符分割与字符识别等关键环节展开并采用Python结合OpenCV等库完成系统开发可帮助读者梳理从选题背景到系统实现的完整研究思路。资源包内共1个docx文件约1.14MB内容涵盖摘要、绪论、目录及各章节正文结构完整便于直接参考论文框架与写作规范。目前已有1006人学习下载适合需要借鉴毕业设计论文结构、了解YOLOv5车牌识别技术路线与实现流程的读者使用。1. 从一份论文文档到能跑的车牌识别yolov5 深度学习车牌识别系统到底在做什么很多人第一次接触「基于 yolov5 的深度学习车牌识别系统论文.docx」这个标题是在毕业设计选题或者课程大作业的节点上。它听起来像一篇论文但真正落地时你会发现论文只是壳核心是一套能跑通的工程链路用 yolov5 做车牌检测把车牌区域裁出来再做字符识别最后拼成完整车牌号。这套东西在停车场闸机、高速卡口、小区门禁里天天跑也是深度学习入门者最容易上手的实战项目之一。它适合谁适合已经装好深度学习环境、跑过 yolov5 官方 demo、想找一个完整闭环项目练手的人。也适合需要交一份能演示、能写进论文、能答辩的系统的人。难点不在 yolov5 本身而在于车牌这个场景的特殊性车牌小、倾斜、光照乱、字符粘连检测框稍微偏一点后面的字符识别就全错。所以这篇不聊空泛概念直接按「检测怎么训、字符怎么识、系统怎么串、坑怎么避」的顺序把一条能复现的路径讲清楚。2. 车牌检测模型怎么选与怎么训从 yolov5 数据集到超参数2.1 为什么车牌检测优先选 yolov5 而不是更重的模型车牌检测本质是单类或双类蓝牌、绿牌目标检测目标尺寸小、长宽比固定、背景相对可控。yolov5s 或 yolov5m 在这个任务上已经能跑到很高的召回率推理速度在普通显卡甚至边缘设备上都够用。相比之下两阶段检测器虽然精度上限高但推理链路长部署到闸机这类实时场景反而吃亏。常见做法是训练阶段用 yolov5m 保证精度部署阶段导出 yolov5s 或量化版本换速度。另一个选型理由是生态。yolov5 的仓库结构清晰数据配置、训练脚本、导出脚本都在一个目录里改起来不费劲。热搜里常出现的「yolov5训练自己的数据集」「yolov5超参数」「yolov5网络结构图」其实都指向同一件事你要先能把官方模型在自己的车牌数据上跑起来再谈优化。2.2 车牌数据集怎么准备标注格式与目录结构车牌数据一般来自两个途径公开车牌数据集或者自己用手机/摄像头拍一段视频抽帧。不管来源如何最终都要转成 yolov5 要求的 YOLO 格式每张图对应一个 txt每行是class x_center y_center width height坐标全部归一化到 0 到 1。目录结构建议直接照搬 yolov5 官方约定dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yaml内容如下path: ./dataset train: images/train val: images/val nc: 2 names: [blue, green]这里nc是类别数蓝牌和绿牌分两类如果只做蓝牌就写 1。标注时最容易翻车的地方是框贴太紧车牌边缘留 2 到 3 个像素的余量后面裁图做字符识别时不会把字符切掉。2.3 训练命令与关键超参数怎么设进入 yolov5 目录后最简训练命令python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data dataset/data.yaml \ --weights yolov5m.pt \ --project runs/train \ --name plate_v1逻辑说明--img 640是输入分辨率车牌小目标多的话可以提到 1280但显存和速度会明显变化--batch 16根据显存调8G 显存跑 640 一般能到 16--weights yolov5m.pt用预训练权重比从头训收敛快很多--epochs 100是上限实际看验证集 mAP 不再涨就可以停。几个值得单独调的超参数参数作用车牌场景建议--img输入尺寸640 起步小牌多可试 960/1280--batch批大小显存允许下尽量大16/32--lr0初始学习率默认 0.01微调可降到 0.001--mosaic马赛克增强车牌建议关掉或降低概率容易把牌拼碎--degrees旋转增强0 到 10 度模拟倾斜拍摄训练过程中重点看runs/train/plate_v1/results.csv里的metrics/mAP_0.5和val/box_loss。如果 box_loss 震荡不降先查标注有没有越界或宽高为 0 的脏数据。2.4 训练完怎么验证检测效果python val.py \ --data dataset/data.yaml \ --weights runs/train/plate_v1/weights/best.pt \ --img 640 \ --conf 0.25--conf 0.25是置信度阈值车牌检测可以适当调低到 0.2 保证召回因为漏检比误检更致命。验证输出里看mAP_0.5和mAP_0.5:0.95前者到 0.95 以上基本可用后者反映框的紧致程度。如果 mAP 高但实际裁图总偏多半是标注框本身不够紧回去修标注比调模型更有效。3. 从检测框到车牌号字符识别链路怎么搭3.1 裁图与矫正检测框出来之后先做什么yolov5 输出的是车牌在整图中的位置直接送进字符识别模型往往效果差因为车牌有倾斜、透视变形。常见做法是先做透视变换把车牌摆正。用 OpenCV 的getPerspectiveTransform配合检测框四个角点或者简单点用最小外接矩形做旋转矫正。import cv2 import numpy as np def crop_plate(img, box): x1, y1, x2, y2 map(int, box) plate img[y1:y2, x1:x2] gray cv2.cvtColor(plate, cv2.COLOR_BGR2GRAY) _, thresh cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) return plate, thresh逻辑说明先按框裁图再转灰度做 OTSU 二值化方便后续字符分割或直接送 CRNN。参数上x1,y1,x2,y2要 clamp 到图像边界否则越界会报错。如果车牌倾斜明显二值化前先做cv2.minAreaRect找最小外接矩形并旋转。3.2 字符识别选 CRNN 还是直接上 OCR 模型车牌字符集很小省份汉字、字母、数字总共几十类。用 CRNNCTC 是经典方案输入是矫正后的车牌灰度图输出是字符序列不需要精确分割每个字符。训练数据就是裁好的车牌图加对应车牌号文本。另一种做法是直接用现成的 OCR 模型微调省事但可控性差遇到新能源绿牌或双层黄牌容易乱。如果论文里要体现工作量CRNN 更合适结构清晰、可解释、能画网络图。CRNN 训练数据准备import os with open(plate_train.txt, w, encodingutf-8) as f: for img_name in os.listdir(plates/train): label img_name.split(_)[0] # 文件名前缀即车牌号 f.write(fplates/train/{img_name}\t{label}\n)逻辑说明每行是「图片路径 制表符 车牌号」车牌号里不要有空格。参数上注意编码统一用 UTF-8汉字省份简称要确认字符集覆盖。3.3 检测与识别怎么串成完整系统完整链路是读图或读视频帧 → yolov5 推理得到车牌框 → 裁图矫正 → CRNN 推理得到字符 → 拼接输出。用 Python 串起来大概是这样import torch import cv2 det_model torch.hub.load(ultralytics/yolov5, custom, pathbest.pt) rec_model torch.load(crnn_best.pth, map_locationcpu) rec_model.eval() def recognize(img_path): img cv2.imread(img_path) results det_model(img) for box in results.xyxy[0]: x1, y1, x2, y2, conf, cls box.tolist() plate_img img[int(y1):int(y2), int(x1):int(x2)] # 预处理后送 rec_model plate_text rec_model(plate_img) print(plate_text) recognize(test.jpg)逻辑说明results.xyxy[0]是检测结果每行六个值。conf低于阈值的框直接跳过。实际部署时检测和识别可以放两个进程或两个线程避免互相阻塞。参数上map_locationcpu方便在没有 GPU 的机器上调试。4. 部署与加速yolov5 量化、边缘设备与常见翻车点4.1 模型导出与量化rk3568、树莓派这类设备怎么跑训练完的.pt不能直接上边缘设备一般先导出 ONNX再转 RKNN 或 TensorRT。yolov5 自带export.pypython export.py \ --weights runs/train/plate_v1/weights/best.pt \ --include onnx \ --img 640 \ --batch 1逻辑说明--include onnx导出 ONNX 格式--batch 1是推理时的批大小。导出后可以用onnxsim简化再去掉多余的输出层。量化到 INT8 时校准集要覆盖白天、夜间、逆光、倾斜各种车牌样本否则量化后小目标召回掉得厉害。树莓派 4B 上跑 yolov5 建议用 ncnn 或 ONNX Runtime输入分辨率降到 320 或 416帧率能到几帧到十几帧取决于模型大小。rk3568 这类带 NPU 的板子走 RKNN 工具链量化后速度提升明显但要注意算子支持情况某些激活函数需要替换。4.2 避坑与排查车牌识别系统最常见的 5 个问题现象一检测框总是偏大或偏小。原因多半是标注框本身不统一有人贴边有人留白。解决方法是定一份标注规范框到车牌字符外沿留 2 像素所有人按同一标准重标。现象二白天准晚上全漏。原因是训练集里夜间样本太少模型没见过低照度下的车牌。解决方法是补夜间数据或者在预处理里加自适应直方图均衡训练时开 HSV 增强。现象三绿牌识别成蓝牌或字符乱码。原因是类别不平衡蓝牌远多于绿牌。解决方法是在data.yaml里保持两类训练时用--balance或手动过采样绿牌字符识别阶段把绿牌字符集单独确认。现象四CRNN 训练 loss 不降。常见原因是标签里有空格或不可见字符或者图片路径写错导致读进来是空图。解决方法是先跑一遍数据检查脚本确认每张图能读、标签长度一致。现象五部署后速度慢到不可用。原因通常是输入分辨率没降、模型没量化、或者前后处理用了 Python 循环。解决方法是先量化再测速前处理用 OpenCV 的向量化操作后处理 NMS 用模型自带的。5. 把系统写进论文之外几个能拉开差距的进阶技巧5.1 用检测框置信度和字符置信度做二次校验单一模型的输出总会有错但检测和识别两个阶段的置信度可以互相验证。如果检测框置信度很高但字符识别置信度很低大概率是车牌被遮挡或严重倾斜这时候可以触发重拍或人工复核。反过来检测置信度低但字符置信度高可能是误检了一个像车牌的区域实际是广告牌。这个逻辑在闸机场景很实用能明显降低误放行。def double_check(det_conf, rec_conf, det_th0.5, rec_th0.8): if det_conf det_th and rec_conf rec_th: return review # 转人工 if det_conf det_th and rec_conf rec_th: return reject # 疑似误检 return pass参数上det_th和rec_th要根据实际业务调闸机场景宁可 review 也不要误放。5.2 用少量真实数据做微调而不是从头训很多人拿到一个新场景就想从头训其实用预训练权重加几百张场景图微调效果往往更好也更快。微调时学习率降到 0.001 甚至更低冻结 backbone 前几层只训检测头和识别头。这样既保留通用特征又适应新场景的光照和角度。5.3 数据闭环把线上错例捞回来重新标系统上线后最有价值的不是模型本身而是错例。每天把置信度低、人工复核过的图存下来每周标一批加进训练集再微调一轮。这个闭环跑起来模型会越来越贴合你的实际场景。我自己的习惯是每轮微调前先看一遍新错例确认不是标注问题再动模型否则就是白训。这套东西从论文文档到能跑的系统中间隔的不是算法而是数据、标注、部署和反复排查。我踩过最深的坑是拿一份标注质量参差不齐的数据集训了三天mAP 死活上不去最后发现是有人把车牌号当成了类别标签。后来我养成一个习惯任何训练开始前先随机抽 50 张图把标注画出来看一眼。希望帮到你。本文还有配套的精品资源点击获取