ARTICLE DETAIL

资讯详情

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

1695张车牌图像跑通YOLOv8检测:数据集准备与训练调参实战

1695张车牌图像跑通YOLOv8检测:数据集准备与训练调参实战 简介一份面向车牌检测与识别任务的高质量图像数据集包含1695张真实场景图片每张均带有精确的车牌边界框标注并采用YOLO文本格式存储适合用于训练和评估YOLO、CNN等对象检测模型。资源包共2000个文件其中1696个txt标注文件对应每张图像的类别与归一化坐标303个jpg原始图像覆盖不同拍摄角度、光照和背景另有1个yaml配置文件便于直接接入YOLO训练流程整体压缩包约147.47MB目录结构简洁标注信息与图像一一对应。目前已有132人学习适合计算机视觉研究者、深度学习初学者及智能交通系统开发者使用。借助该数据集用户可跳过繁琐的数据整理环节直接开展车牌定位、识别模型的训练与调优同时多样化的图像来源也有助于检验算法在不同环境下的鲁棒性为智慧停车、交通监控、高速收费等实际应用提供可靠的数据支撑。1. 车牌图像识别最容易被低估的其实是那1695张训练图做车牌图像识别的人一上来就问“数据集够不够大”但真正跑过检测模型的人会告诉你1695张图片、YOLO格式标注用在固定场景的车牌检测上效果往往比盲目堆到上万张还要稳。这个数据集的定位很明确——它不追求覆盖“全中国所有车牌样式”而是把车牌这个目标物的几何特征、颜色对比和文字结构先让模型吃透跑通一版能用的检测模型。这篇文章要讲清楚三件事这套YOLO格式的车牌图像数据集适合什么场景、不适合什么场景怎么把手上的图片和标注文件整理成能直接喂给YOLO的训练集以及训练时那些最容易让新手翻车的参数和坑。适合正在做闸口车牌识别、停车场出入口检测、或者想用YOLO系列跑通第一个检测项目的开发者也适合需要快速验证“车牌检测OCR”两段式方案的团队。2. 1695张图片能干什么先认清数据集的边界再动手2.1 车牌检测任务对数据量的真实需求对象检测任务里数据量不是唯一的决定因素。车牌这个目标物有个天然优势它是一块高对比度、高结构化的矩形区域背景再复杂车牌本身的边缘、颜色蓝底白字、黄底黑字、绿底白字、字符排布都高度一致。这让它比“行人检测”“通用物体检测”这类开放域任务更容易用小数据量收敛。拿我自己跑过的经验说用YOLOv8在1000多张图上训练车牌检测配合合适的数据增强mAP50能做到0.9以上并不稀奇。前提是你的应用场景和数据集里的图像风格不能差太远。比如数据集中都是白天、晴天、近距离的闸口照片那你的摄像头也装在闸口效果就会很好。但如果你的摄像头是架在高处俯瞰、有强逆光、或者隔着挡风玻璃拍的同样的权重就会明显掉点。所以拿到这1695张图第一件事不是急着训练而是把图片翻一遍搞清楚几个问题车牌主要是什么颜色、图像是近景还是远景、有没有夜间样本、有没有倾斜和遮挡。这些决定了你能直接复现到什么精度也决定了后期要不要补数据。2.2 能用、好用和不能用的三个场景划分按我的习惯一个数据集拿回来先划分三个档位能用固定机位、道闸口、停车场入口、加油站入口相机距离2到6米车牌宽度占画面1/8以上。这类场景和常见车牌数据集分布高度重合1695张训练验证绰绰有余。好用抓拍机位有轻微角度、车辆在画面中占比中等、光线比较均匀。这时模型能挑出车牌但可能需要把置信度阈值调到0.35以下不然会有漏检。不能用跨省长途路面卡口、多车道并行的超大视野、高速上超过60km/h的抓拍。这种场景车牌在画面里往往只有几十个像素1695张里如果本身就没这类样本模型不会凭空学会。另外注意一点数据集标题里说的是“YOLO格式”意味着每个图片对应一个同名.txt文件每一行是“类别 中心点x 中心点y 宽度 高度”坐标都做了归一化。这个格式对YOLOv5、YOLOv8、YOLOv9都通用不用做转换这是它最大的便利。2.3 算标签类别先确认是单类还是多类我吃过的亏是拿到一个数据集后想当然地当作单类“plate”直接开跑结果训练时报错说类别数对不上。所以你拿到这1695张图后第一件事是数一数所以.txt文件里第一列出现过哪些数字。常见做法是用下面这个小脚本扫一遍cat *.txt | awk {print $1} | sort | uniq -c这个命令把所有标注文件里的第一列类别id提出来统计每个id出现的次数。如果只出现“0”那是单类数据集模型输出就是1个类别。如果出现了0、1、2那就是多类数据集比如有的数据集把蓝牌、黄牌、绿牌分开了你的模型输出层要对应改成3类。这一步跑完后面所有配置都不会猜错。3. 把1695张图整理成YOLO训练集目录结构、校验脚本和划分策略3.1 标准目录结构不按这个摆YOLO会找不到数据YOLO系列对数据集目录有约定虽然不是强制性但按约定摆最少出错。结构是这样的plate_dataset/ ├── images/ │ ├── train/ │ │ ├── 0001.jpg │ │ └── ... │ └── val/ │ ├── 0050.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── 0001.txt │ │ └── ... │ └── val/ │ ├── 0050.txt │ └── ... └── dataset.yaml注意一个细节images目录和labels目录是兄弟目录不是父子目录。每个图片对应的标注文件必须和图片同名扩展名不同放在labels下对应的train或val里。YOLO训练时会根据图片路径自动把“images”替换成“labels”、“.jpg”替换成“.txt”去找标注文件所以你只需要在yaml里写images目录的路径不需要逐条指定标注路径。写dataset.yaml也很直白path: /home/user/plate_dataset train: images/train val: images/val names: 0: plate这个yaml里path是数据集的绝对路径train和val是相对path的路径。names里的0对应你在标注文件里看到的类别id。如果你发现数据集是单类的这里就写0: plate如果前面扫出来是多类就按实际类别写全。3.2 验证标注文件坐标越界和空标注是两大隐患YOLO格式的标注坐标是归一化的理论值都在0到1之间。但数据集打包、手工标注时偶尔会出现大于1的坐标或者宽度为0的坏框。训练时这些问题不会直接报错但会污染训练过程表现为loss曲线诡异、mAP上不去。我用过一个简单的Python脚本做全量校验import os label_dir labels/train for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue with open(os.path.join(label_dir, fname)) as f: lines f.readlines() if len(lines) 0: print(f空标注: {fname}) continue for i, line in enumerate(lines): parts line.strip().split() if len(parts) ! 5: print(f列数不对 {fname} 第{i1}行) continue cls, cx, cy, w, h parts cx, cy, w, h map(float, [cx, cy, w, h]) if cx 0 or cx 1 or cy 0 or cy 1: print(f中心点越界 {fname} 第{i1}行) if w 0 or h 0: print(f框宽高非法 {fname} 第{i1}行) if w 1 or h 1: print(f框宽高超过1 {fname} 第{i1}行)这段脚本遍历所有标注文件检查每行是不是5个数、坐标是否在0到1之间、宽高是否为正且不超过1。逻辑很简单但能把脏数据提前揪出来。我在实际项目中跑这类脚本几乎每次都能挑出几行越界的尤其宽高超过1的多半是标注工具导出时没做归一化。3.3 划分训练验证集用随机分配而不是手动挑1695张图不算多手动挑片子划分训练验证集很容易带入主观偏差比如把相近机位的都放进训练集验证集实际难度被高估。正确的做法是脚本随机划分按8:2或9:1的比例。下面这段Python代码完成划分并直接生成好目录结构import os import random import shutil random.seed(42) img_dir plate_images label_dir plate_labels train_ratio 0.9 all_imgs [f for f in os.listdir(img_dir) if f.endswith(.jpg)] random.shuffle(all_imgs) split_idx int(len(all_imgs) * train_ratio) train_imgs all_imgs[:split_idx] val_imgs all_imgs[split_idx:] for split, imgs in [(train, train_imgs), (val, val_imgs)]: os.makedirs(fplate_dataset/images/{split}, exist_okTrue) os.makedirs(fplate_dataset/labels/{split}, exist_okTrue) for fname in imgs: shutil.copy(os.path.join(img_dir, fname), fplate_dataset/images/{split}/{fname}) label_name fname.replace(.jpg, .txt) if os.path.exists(os.path.join(label_dir, label_name)): shutil.copy(os.path.join(label_dir, label_name), fplate_dataset/labels/{split}/{label_name}) else: print(f缺标注: {fname})代码里random.seed(42)是固定随机种子保证每次跑划分结果一致方便复现。train_ratio设为0.9意味着1521张进训练集、174张做验证集。对1695张这个规模9:1比8:2更合适因为验证集如果只有100多张评估波动也会比较大但训练数据能多留一点。要留意的是代码里如果发现图片没有对应的txt会打印“缺标注”这行信息很关键——如果缺的多了说明数据集本身不完整训练时YOLO会忽略没有标注的图片等于实际训练量比预期小。4. 跑通YOLOv8车牌检测最小训练命令和三个必调参数4.1 环境准备和最小训练命令训练环境我用的是YOLOv8这是目前迭代比较稳、文档完善、对新手最友好的一版。安装和启动训练就两行命令pip install ultralytics yolo detect train dataplate_dataset/dataset.yaml modelyolov8n.pt epochs100 batch16 imgsz640这段命令的意思是用yolov8n.pt这个最小的预训练权重做初始化在dataset.yaml指定的数据上训练100轮。yolov8n是nano版本模型最小、显存要求最低用在1695张图上完全够用跑起来也快。如果你有GPU显存充裕可以换yolov8s.pt精度会好一些但对小数据集提升有限。训练结束后在runs/detect/train目录下会产生weights/best.pt和weights/last.pt。best.pt是在验证集上效果最好的权重后面推理就用它last.pt只是最后一轮的快照。这两者的区别新手容易忽视best看的是val mAPlast是训练到最后的权重一般用best。4.2 必调参数一imgsz的选择直接决定小目标检出率imgsz是输入网络的图像尺寸。YOLO训练和推理时会先把原图缩放到这个尺寸再送进网络。对车牌检测640是默认值但如果你的图像里车牌占比本来就小640下车牌可能只有20x60像素特征不足检测就难了。经验做法是先统计一下目标宽高占全图的比例。可以用一个小脚本把标注读出来算出所有车牌框的平均像素宽度。如果平均车宽小于40像素在640尺度下就要把imgsz升到960或1280。代价是训练时间变长、显存占用变大。1695张图、batch16、imgsz96020G显存的卡能跑再大就得减batch。不用怀疑这个参数的重要性我自己遇到过imgsz从640提到960后mAP50从0.83涨到0.91的情况。要是你的场景里车牌占图像比例大反而不用调高640就够。4.3 必调参数二epochs按小数据集减半按早停保护1695张图配100轮含义是模型总共看了大约1695×10016.9万次样本。对车牌这种简单目标通常在20轮以内就能收敛到不错的效果后面一直在做微调甚至开始过拟合。所以epochs100不是不能用但开着早停更稳妥。在命令里加一个参数yolo detect train dataplate_dataset/dataset.yaml modelyolov8n.pt epochs100 batch16 imgsz640 patience15patience15表示如果连续15轮验证集mAP没有提升就自动停。这样可以避免浪费时间也防止过拟合。家用级别的显卡训练1695张100轮nano模型大约几分钟到十几分钟如果用geq_cpu跑时间会放大10倍以上早停节省的时间就更有价值。4.4 必调参数三batch受显存约束怎么估batch大小由显存和imgsz共同决定。一个粗略的估算方式在8G显存卡上imgsz640时batch可以设为16imgsz960时batch降到8imgsz1280时batch只能4。batch减少会让训练噪声变大、收敛变慢但小数据集上影响不致命。如果你只有一个8G显存的卡建议imgsz640、batch16起步先跑通一遍确认流程无误。如果验证集效果不理想再往高分辨率调。不要一上来用最大配置翻车概率高排查也麻烦。5. 车牌检测训练避坑5条踩过的坑和对应解法5.1 标注文件里混进了中文路径导致训练中断现象训练刚开始Loader报错找不到图片或者是部分图片被跳过训练集数量比预期少。原因数据集目录或图片路径里有中文、空格等非ASCII字符ultralytics的加载器在一些环境下处理不了尤其是Windows系统下常见。我自己接过一个项目对方把数据放在“C:\用户\车牌数据\”下训练直接报错。解决把数据集挪到纯英文路径下比如/home/plate_dataset或D:/plate_dataset。目录层级不要有空格最好连下划线也不要太多。这个问题不会第一时间想到但排查成本很低先做排除。5.2 验证集mAP很高一到实际视频流里疯狂漏检现象训练完在测试图片上画框效果不错mAP50也有0.9以上但接到实时视频流后车一入画就开始漏检几帧后突然又检测到了。原因训练集的静态图片大多是车停着或者低速贴近闸口的画面车牌清晰、无运动模糊。视频流里车辆高速运动、角度倾斜、运动模糊叠加分布发生了偏移。数据集里没有这些hard example模型自然扛不住。解决从实际视频流里按帧抽图挑出运动模糊、倾斜、远端小目标的场景补充标注后做二次增量训练。增量训练时把原来的1695张一起混着用不要只训新数据否则模型会遗忘原始分布。标记20到30张实际场景的图重训一遍漏检率通常能明显下降。5.3 有两种颜色车牌的数据集按单类训练导致蓝牌黄牌互相抑制现象loss正常下降但推理时黄牌经常被漏检只有蓝牌稳定检出。原因不同颜色车牌在特征空间里差异很大如果标注文件里确实存在多个类别id但你把names只写了0: plate模型把所有车牌当作一类去学习特征表达不够区分训练时两类样本互相干扰。解决重新数一遍类别id按实际情况把names写成多个类。比如0: blue_plate、1: yellow_plate、2: green_plate然后retrain。注意这会让输出类别从1变成3训练轮次要适当增加小数据集下超参不用大改。5.4 用last.pt做推理效果明显比best.pt差现象训练完直接拿runs/detect/train/weights/last.pt做测试发现检测率比训练时验证效果差很多框的位置偶尔还飘。原因last.pt是最后一轮epoch的权重模型在训练末期可能在验证集上已经过拟合而best.pt是根据验证集mAP选出来的最优快照。很多教程里说“用best.pt”但新手常常忽略直接把训练完自动生成的last拿来用了。解决推理时显式指定权重路径为runs/detect/train/weights/best.pt。我习惯把best.pt复制到工作目录改名成plate_best.pt避免每次都要去翻runs目录下的深层路径。5.5 通过数据增强引入的噪点反而降低了精度现象训练时开了大幅度的旋转、透视增强验证精度反而不如不开。原因车牌在真实场景里虽然有倾斜但角度通常有限比如20度以内的偏转居多。如果数据增强里设了rotate30模型会学到“车牌可以横过来”这种错误先验推理时对正着停的车反而犹豫。这类先验偏差叫增强过度很多人调了半天参数其实是增强设置背锅。解决控制增强幅度。YOLOv8默认的增强参数在小数据集上可以适当调低比如在训练命令里加yolo detect train dataplate_dataset/dataset.yaml modelyolov8n.pt epochs100 batch16 imgsz640 patience15 hsv_h0.015 hsv_s0.7 hsv_v0.4 flipud0.0flipud设成0就是禁止上下翻转因为现实里车牌不会倒过来。hsv色相扰动调小避免蓝牌被干扰成绿牌。水平翻转fliplr可以保留默认的0.5车牌左右翻转后仍然是合法文本不影响学习。6. 进阶从检测到可用系统两个值得做的增强方向检测模型跑通只是第一步。做车牌识别系统的人都知道检测后面还挂了一个OCR环节这个两段式架构决定了最终可用性。这里给两个投入产出比最高的进阶方向。第一个方向是“检测框外扩”。用YOLO拿到车牌框后不要直接把框内图像送OCR而是把框的四个边向外扩展15%到20%再裁切。原因是YOLO的框追求紧凑贴合车牌边框但它两端的螺丝、边框反光、甚至半个汉字边缘会被切掉OCR对这种情况很敏感。外扩后OCR准确率能涨不少代码上就是坐标的缩放新左上角等于原左上角减0.15倍宽高新右下角加0.15倍宽高。这个改动在部署时加几行就行但效果立竿见影。第二个方向是收集真实场景的bad case做增量训练。跑一次测试视频把漏检和错检的帧截出来每50帧选一帧积累到一两百张后手工标注和原数据集混合再训一遍。数据量不用多一两百张能压下去大半的漏检问题。这是所有参数调优都替代不了的一步——模型没见过运动模糊你怎么调增强都模拟不出真实摄像头的拖影。另外说一个工作习惯每次训练完把模型推理结果的截图和mAP指标归档到一个叫“版本记录”的文件夹里标上第几次迭代、改了哪些参数、加了哪些数据。否则过了两周再回头看你已经忘了当时的best.pt基线是怎么跑出来的。这个文件夹是我做所有检测项目都会保留的后来每次复盘最快定位问题都靠它。希望这篇笔记能帮你把这1695张车牌图像的价值释放出来用最短路径跑通第一版检测模型并让你知道后面往哪个方向使力。本文还有配套的精品资源点击获取
返回列表