尧图精选

YOLOv7中文车牌识别源码实战:从环境搭建到训练部署全流程

🕒 发布时间:2026/10/1 16:33:23 📁 来源:尧图网络
简介基于YOLOv7的中文车牌检测识别项目资源面向计算机视觉方向的在校学生、教师及企业开发者覆盖模型训练到部署的完整链路。系统支持单行/双层蓝牌/黄牌/新能源/警用/武警/使馆/港澳/农用/民航等12种常见车牌类型可直接用于毕设、课程设计或实际项目二次开发。压缩包内共97个文件体积约24MB其中包含38个Python脚本以及YOLOv7模型配置、预训练权重.pt/.pth、测试图片与字体文件并附有C推理代码及TensorRT/ONNX/NCNN等部署相关文件环境搭建与使用说明也已整理在文档中。已有193人学习代码以毕业设计为基础经多轮功能测试运行稳定性有保障。下载后可快速完成车牌检测、识别及双层车牌分割的实验复现也可参照工程目录结构进行算法调整与功能扩展。1. 车牌检测识别为什么难YOLOv7 中文车牌源码把哪三件事串起来了中文车牌识别和英文车牌识别是完全不同的两码事。英文车牌是字母加数字的 36 类分类问题模型随便训一训精度就上去了中文车牌要分辨省份汉字、字母、数字还得扛住双层黄牌这种特殊结构字符集和分类难度直接翻倍。这套基于 YOLOv7 的车牌检测识别源码把「车牌区域检测 → 字符分割 → 字符识别」三个阶段串成完整管线支持 12 种中文车牌类型双层车牌单独处理源码配文档适合做课设、毕设、停车场项目原型也适合想研究 YOLOv7 工程落地方式的人。我拆过不少类似项目这套的优点是流程完整、训练推理脚本齐全不是只有一个检测模型的半成品。下面从环境搭建开始一步步把它跑起来。2. 环境准备与项目结构跑通首次推理前先弄清三件事2.1 环境依赖Python 版本和 PyTorch 必须对齐YOLOv7 的代码基础是 2022 年的版本它对 PyTorch 版本的要求没有 YOLOv8 那么宽容。我自己的经验是 Python 3.8 或 3.9 最稳PyTorch 用 1.10 到 1.13 之间都可以超过 2.0 之后个别算子在训练时报错需要手动改源码。这里给一套我常用的环境组合conda create -n plate python3.8 -y conda activate plate pip install torch1.12.1cu116 torchvision0.13.1cu116 --extra-index-url https://download.pytorch.org/whl/cu116先装 PyTorch 再装项目依赖。如果直接pip install -r requirements.txtpip 会按依赖把 torch 拉成最新版后面跑训练时经常报算子不匹配的错误。装完验证一下环境python -c import torch; print(torch.__version__, torch.cuda.is_available())输出1.12.1 True说明 GPU 可用。只有 CPU 的话训练会慢但推理能正常跑显存不足的情况可以先拿 CPU 调试流程。安装阶段最容易翻车的是 CUDA 版本和 NVIDIA 驱动不匹配。先跑nvidia-smi看驱动支持的最高 CUDA 版本再选对应的 torch 安装包驱动版本太老时强行装 cu116 会在运行时直接报CUDA driver version is insufficient。遇到这种问题不用重装系统降一个 CUDA 小版本比如从 cu116 换到 cu113通常就能解决。2.2 项目结构检测、识别、分类三个模块分别在哪解压源码后先看目录不要急着运行。这个项目的核心文件集中在几个位置plate_recognition/ ├── detect.py # 检测 识别主入口 ├── train.py # 检测模型训练脚本 ├── train_recognition.py # 字符识别模型训练脚本 ├── data/ │ ├── plate.yaml # 检测数据集配置 │ ├── char_dict.json # 字符集字典省份 字母 数字 │ └── fonts/ # 车牌字体文件 ├── weights/ │ ├── yolov7.pt # COCO 预训练权重 │ ├── plate_detect.pt # 车牌检测权重 │ └── plate_rec.pth # 字符识别权重 └── utils/ ├── plate_recognition.py # 识别后处理逻辑 └── split_plate.py # 双层车牌分割detect.py 是整个流程的入口先加载车牌检测权重把车牌位置框出来再把框内图像裁切送给字符识别模型。data/plate.yaml 写明检测数据集的路径和类别char_dict.json 是识别模型输出的字符映射表模型输出的是索引必须靠它转成汉字和字母。weights 目录下三个权重对应三个阶段yolov7.pt 是官方 COCO 预训练权重只用来做迁移学习初始化plate_detect.pt 是训练好的车牌检测权重plate_rec.pth 是训练好的字符识别权重。字符识别模型这部分的处理思路是这样车牌区域裁切图进来后先按字符位置做分割中文车牌字符数量固定多数实现直接用固定网格切分或者用垂直投影找字符边界。分割出的单字符图逐个过分类网络输出每个位置的最大概率索引再查 char_dict.json 拼成完整车牌字符串。这个流程决定了后面调优的方向——如果识别错的是个别字符问题大概率在分割或者分类如果整串全乱基本都是字典映射错位。2.3 首次推理从单张图片确认整条管线正常环境没问题、目录看明白了就跑推理。先用单张图片验证python detect.py --source test.jpg --weights weights/plate_detect.pt \ --recognize-weights weights/plate_rec.pth --conf-thres 0.4 --iou-thres 0.5--source接受图片路径、视频路径或摄像头编号传 0 就是调用第一个摄像头。--conf-thres是置信度阈值低于这个值的检测框会被过滤。日常场景 0.4 合适距离远或者光照差的场景降到 0.3 能找回一些召回率但误检也会变多。--iou-thres是 NMS 交并比阈值同一个车牌出现多个重叠框时按它来抑制一般保持 0.5 不用动。跑通之后看两个输出终端打印的识别结果包括车牌字符串和置信度保存路径下的标注图检测框画得准不准一眼就能判断。这一步能确认三件事检测权重能不能加载、识别权重能不能加载、两者衔接是否正常。如果报缺依赖按报错逐个补包如果框出来了但识别全是乱码大概率是字符字典和识别模型输出的索引顺序不一致这个坑后面单独讲。3. 训练自己的数据集标注格式、参数配置与迁移学习3.1 数据集组织方式YOLO 格式还是 VOC 格式这套代码支持两种标注格式YOLO 的 txt 格式和 VOC 的 XML 格式。新手建议直接用 YOLO 格式省去 XML 解析的麻烦。目录结构要求如下datasets/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/每个标注文件是 txt一行一个目标格式是class_id x_center y_center width height四个坐标值全部归一化到 0 到 1 之间。车牌检测只有一个类别class_id 基本固定为 0。归一化坐标用 LabelImg 这类工具导出时会自动算好手工写的时候记得除以图片宽高复制粘贴别人数据集时最容易在这里出错。我曾见过一个项目把归一化坐标写成像素坐标训练损失降不下去排查了半天才发现是这个问题。把自己的车牌图片按 8:2 分到 train 和 val再改 data/plate.yamltrain: datasets/images/train val: datasets/images/val nc: 1 names: [plate]nc是类别数只检测车牌就写 1如果想把车和车牌一起检测按实际类别数改。names列表的顺序必须和标注里的 class_id 对应不然训练不报错但评估结果的类别名是乱的后期分析错误样本时非常别扭。3.2 训练参数迁移学习怎么用才不翻车训练检测模型用 train.py最常见命令是python train.py --data data/plate.yaml \ --cfg cfg/training/yolov7.yaml \ --weights weights/yolov7.pt \ --batch-size 8 --epochs 100 --img-size 640 --device 0--weights weights/yolov7.pt是迁移学习的关键。用 COCO 预训练权重初始化网络比从零训练收敛快得多一般前 20 个 epoch 就能看到 mAP 明显上升。不要省这一步直接随机初始化车牌这类纹理特征强的目标从零训练 100 个 epoch 的效果通常还不如迁移学习 30 个 epoch。batch-size 默认 8按显存 8 到 11G 设计。显存不够就降到 4同时把--img-size从 640 降到 512检测精度损失很小但训练显存占用能降 30% 以上。学习率一般不用手动改代码里会根据 epoch 自动做余弦退火初始学习率默认 0.01前三个 epoch 还有 warm-up。新手常犯的错是把学习率调到 0.1 想加速收敛结果 loss 直接发散训练白跑两小时。训练到 100 epoch 后weights 目录下会生成 best.pt 和 last.pt。best 按验证集 mAP 选出推理时优先用 best。把这个文件替换到 2.3 节推理脚本的--weights参数里不用改任何代码。我一般训练完先跑一遍验证集图集确认 best 权重在自己采集的测试图上不是偶然指标高而是真的可用再决定要不要继续加 epoch。3.3 识别模型训练先固定字符集再调参字符识别是分类问题训练脚本是 train_recognition.py输入是车牌检测框裁出来的图片输出是字符序列。这里的核心是字符集字典data/char_dict.json 定义了模型认识的字符范围。中文车牌字符集包含 31 个省份简称、24 个字母I 和 O 不用、10 个数字加起来约 65 个字符。如果自己的场景有特殊字符必须先把字典文件改了再训练。训练完字典和模型是绑定的推理时换字典必乱。训练命令python train_recognition.py --data data/recognition_set \ --dict data/char_dict.json --batch-size 32 --epochs 50recognition_set 目录下每个子目录按字符名组织或者提供一个 CSV 标注文件映射图片和字符序列具体格式看文档。识别模型训练比检测快很多50 个 epoch 在 GTX 1660 上大概几小时。这里有个容易忽略的点识别模型训练用的图片最好和检测框的输出保持同样比例训练时用了拉伸推理时检测框裁出来也按同样方式拉伸两边一致精度才稳。不然训练时字符比例正常推理时字符被压扁或拉长识别率掉得很厉害。3.4 结果怎么看mAP、精确率和召回率训练日志里会输出 P、R、mAP0.5、mAP0.5:0.95 这几个指标。P 是精确率检测出来的框里有多少是对的R 是召回率真正的车牌有多少被找出来mAP 是两个的综合。实际场景中车牌漏检比误检更致命所以调阈值时我优先保证召回率。我一般接受的标准白天场景 mAP0.5 到 0.95 这个区间看 0.5 单点0.95 以上算合格夜间或雨雾场景 0.88 以上可接受。如果 mAP 高但实际推理效果差检查是不是验证集和测试集分布不一致或者训练时数据增强配置不合理。YOLOv7 自带 mosaic 增强但小目标车牌在 mosaic 拼接后尺寸更小如果数据集里车牌普遍很小建议关闭 mosaic 并调大输入尺寸。4. 避坑手册中文车牌识别最容易翻车的六个场景4.1 识别结果全是乱码但检测框是准的现象检测框准确框住车牌但输出字符串是「??◎◎」之类的乱码或者汉字部分全是错的。原因最常见是 char_dict.json 字符字典和模型输出的类别索引对不上。训练时字典按「省份汉字 → 字母 → 数字」排序推理时如果加载了另一个字典文件或者字典顺序改了索引映射就全错位。另一个原因是 CPU 跑识别时模型数据类型没统一输出概率分布被截断。解决确认训练和推理用同一个 char_dict.json推理时加--dict data/char_dict.json显式指定。数据类型问题检查识别模型推理时是否混用了 float32 和 float16统一用 float32 就稳。从那以后我每次换权重都会先用文档配套的示例图和权重跑一遍确认输出正常再换自己的数据。4.2 双层黄色车牌只识别出下半部分现象双层车牌被检测框框住但识别结果只输出一行字符下半部分内容正常上半部分丢了。原因字符识别模型按单层车牌设计输入固定高度双层车牌被压缩成长条图后上层字符太密集特征提取阶段就丢了。检测阶段没问题问题出在识别阶段对长宽比的适应性上。解决检测到车牌后按宽高比判断是不是双层宽高比小于 2.5具体阈值看数据就进入双层识别分支。先按水平中线把裁切图分成上下两半每半分别缩放成标准输入尺寸再并行送识别模型最后把两行字符上下拼接。这属于常见做法项目 utils/split_plate.py 里已经实现了这套逻辑。改参数时注意不要硬编码图片宽度不同摄像头分辨率下双层车牌的像素宽度差别很大。4.3 训练时 CUDA out of memory现象训练启动后几十秒报 CUDA out of memory程序直接退出前面白跑。原因显存 8G 的卡硬跑默认 batch-size 8 加 img-size 640加上 YOLOv7 的 PAN 结构训练显存占用很容易超过 10G。解决先降 batch-size 到 4再不行降到 2同时把 img-size 降到 512。这两个参数对显存的影响立竿见影。还爆的话把--workers降到 2 或者 0Windows 下 workers 过高还会触发内存泄漏这个坑不少人都踩过。另外检查是不是多进程共用一块卡nvidia-smi看一下显存占用情况。4.4 检测框偏移但识别几乎全对现象检测框没有完全贴住车牌左右或上下偏移几个像素但识别结果正确率还挺高。原因检测模型训练的标注框本身就带偏移或者验证集标注得比较随意。识别模型有字符级冗余略微偏移还能扛住但到了夜景和强反光场景偏移带来的裁切误差被放大。解决对验证集标注做抽查特别看边界上的标注框是否贴紧车牌边缘。更实际的做法是推理阶段给检测框做 margin 扩展左右各扩 3% 的框宽度上下各扩 5% 的框高度把字符和边框的边缘信息包进去。扩展比例别超过 10%扩太多会把周围背景带进识别输入反而干扰。4.5 把车标、广告牌误检成车牌现象图片里有大面积字体区域时检测框错误地圈上去识别结果当然也是错的。原因训练集负样本太少。YOLO 类模型对「像文本的矩形区域」天然敏感如果数据集中只有正样本模型没见过足够多「类似车牌但实际不是」的样本就会把一切蓝底白字、黄底黑字的矩形都当作目标。解决收集 500 到 1000 张包含车标、车身贴纸、路牌、广告牌的图片标注为空labels 目录下放空 txt 文件放进训练集。这个操作成本很低但效果非常明显我自己数据里加了负样本之后误检率大概降了一半。另外可以把 conf-thres 从 0.25 提到 0.4简单粗暴过滤低置信度误检。4.6 同一辆车检测出两个框现象一个车牌被套上两个几乎重叠的检测框识别结果两个框还不一样。原因NMS 阈值设定太高或者检测框的分布太散。YOLOv7 输出多个 anchor 层同一目标在不同层都可能响应NMS 没把低分框压掉。解决把--iou-thres从 0.5 降到 0.45让 NMS 更激进同时检查置信度阈值是否太低。如果两个框置信度都很高说明训练数据里有大量标注不一致的情况同一个车牌有的标成一个框有的拆成两个框模型学成了多峰分布。这种情况要回头清理数据而不是调参。5. 进阶优化双层车牌分支与 ONNX 导出并行的思路5.1 双层车牌识别分支怎么和主流程衔接前面避坑部分提过双层车牌要单独走分支这里把它写清楚。在 detect.py 的识别回调里检测框裁出后先算宽高比import cv2 plate_roi img[y1:y2, x1:x2] h, w plate_roi.shape[:2] ratio w / h if ratio 2.5: # 判断为双层车牌 mid h // 2 upper plate_roi[:mid, :] lower plate_roi[mid:, :] # 上下两半分别识别再按行合并 plate_str recognize_row(upper) recognize_row(lower) else: plate_str recognize_row(plate_roi)这里的recognize_row封装了缩放、灰度处理和模型前向。双层车牌常见结构是上层省份加字母、下层数字加字母上下两半字符数不一定相同分别识别再拼接比整体识别稳得多。阈值 2.5 不是死的新能源绿牌宽度比普通蓝牌略窄如果自己场景绿牌多把阈值放到 3.0 更合适。拿 50 张标注数据统计一下宽高比分布再定阈值比自己拍脑袋准。5.2 导出 ONNX推理提速与算子兼容项目在 PyTorch 下跑没问题但部署到嵌入式设备或对接 C 服务时通常转 ONNX。YOLOv7 官方仓库自带 export.py但车牌项目检测头和识别头是分开的需要分别导出python export.py --weights weights/plate_detect.pt --img-size 640 --simplify python export_recognize.py --weights weights/plate_rec.pth --simplify导出后先做精度对比同一批测试图分别跑 PyTorch 和 ONNX对比检测框坐标和识别结果。YOLOv7 检测头里有不少自定义算子ONNX Runtime 支持不完全常报 Unsupported operator 错误解决方法是带--simplify简化导出或者手动把检测头里某些算子实现改成等价的矩阵运算。核验通过后ONNX 的 CPU 推理速度通常比 PyTorch 快 30% 到 50%配合 OpenVINO 还能再提一档。导出成功整个流程就从 Python 原型变成可部署服务了。我习惯在最后强制走一遍验证清单用同一张双层车牌图依次跑原始仓库权重、自己训练的权重、ONNX 导出权重三个结果必须一致任何一步对不上都说明某个环节参数没对齐。从那以后我每次拿到新权重或者新字典都强制走一遍这个验证流程真的帮我省掉了好几次深夜排查。这套源码从环境搭建到踩坑排查再到部署优化我已经完整拆了一遍希望帮到你。跑的过程中如果卡在字符字典对齐或者双层分割上先回头确认 char_dict.json 和训练权重是否配套这个检查能帮你省下大半晚上的排查时间。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →