
简介本资源为面向车牌检测与车牌识别任务的人工精标数据集适用于计算机视觉入门与进阶开发者、算法工程师及需要训练车牌定位模型的研究人员。数据集聚焦黄牌场景可支撑目标检测、字符识别等下游应用。包内共9324个文件包含4627张jpg、35张jpeg图像以及4662个json标签文件压缩包约257.79MB。标签采用polygon多边形目标框格式四个点分别对应车牌四角能贴合不同倾斜角度的车牌且已逐张人工过滤不清晰图片并处理歧义区域可直接用于字符识别训练。目前已有885人学习下载。对于需要rectangle矩形框json格式或其他标签格式的用户作者支持私信转换便于快速接入不同检测框架减少数据清洗与标注成本。1. 黄牌车牌检测数据集从 json 标签到可训练样本的落地路径手上有个车牌识别项目卡在数据这一环——网上能找到的多是蓝牌数据集黄牌样本少得可怜标注格式还五花八门。这次拆的这份「车牌检测数据集黄牌json标签」核心价值就在于它把黄牌车牌单独拎出来做了标注且标签直接给的是 json 格式省掉了从 xml 或 txt 反推坐标的麻烦。黄牌主要对应大型车辆像货车、客车、工程车车牌尺寸、底色、字符排布跟蓝牌差异明显拿蓝牌模型直接迁移到黄牌场景召回率往往掉得厉害。这份资源适合两类人一是做车辆检测、车牌定位的算法工程师需要补充黄牌类别的训练样本二是做交通卡口、停车场系统的开发者想快速验证黄牌检测的可行性。json 标签意味着每张图的标注信息以结构化字段存储解析后可直接转成 YOLO、COCO 或 PaddleDetection 需要的格式不用再手写解析器去啃标注工具的私有格式。2. json 标签结构拆解与格式转换从原始标注到 YOLO 训练格式拿到 json 标签后第一件事不是急着喂给模型而是先搞清楚它的字段结构。不同标注工具导出的 json 差异很大常见的有 LabelMe 的 shapes 数组、VIA 的 regions 字典、以及自研工具导出的扁平列表。这份黄牌数据集的 json 标签我按常见结构做了兼容性处理下面把解析和转换的完整链路走一遍。2.1 json 标签的字段含义与读取方式先看一份典型的 json 标注长什么样。假设每张图对应一个 json 文件文件名与图片同名内容结构如下{ imagePath: yellow_plate_0001.jpg, imageWidth: 1920, imageHeight: 1080, shapes: [ { label: yellow_plate, points: [[320, 540], [680, 540], [680, 620], [320, 620]], shape_type: rectangle } ] }这里shapes是标注主体label是类别名points是矩形框的四个角点坐标顺序通常是左上、右上、右下、左下。imageWidth和imageHeight是原图尺寸转换时用来做归一化。有些 json 会把points写成[[x1,y1],[x2,y2]]两个点表示对角坐标这种更省事直接取 min/max 就行。读取时用 Python 的json库即可注意编码统一用utf-8避免中文路径或类别名乱码。import json import os def load_annotation(json_path): with open(json_path, r, encodingutf-8) as f: data json.load(f) # 兼容两种 points 写法四点矩形或两点对角 shapes data.get(shapes, []) boxes [] for shape in shapes: pts shape[points] if len(pts) 4: xs [p[0] for p in pts] ys [p[1] for p in pts] x1, y1, x2, y2 min(xs), min(ys), max(xs), max(ys) elif len(pts) 2: x1, y1 pts[0] x2, y2 pts[1] else: continue boxes.append({ label: shape[label], bbox: [x1, y1, x2, y2] }) return data[imageWidth], data[imageHeight], boxes这段代码的关键点在于points的兼容处理。四点矩形取 min/max 得到外接框两点对角直接赋值。label字段保留原始类别名后续映射到数字 id 时再做替换。如果 json 里还有flags或attributes字段比如是否遮挡、是否模糊可以一并读出来作为额外标签但训练检测模型时通常只用 bbox 和类别。2.2 转 YOLO 格式归一化与类别映射YOLO 格式要求每张图对应一个 txt 文件每行是class_id x_center y_center width height全部归一化到 0~1。转换时注意两点一是类别名到 id 的映射要固定比如yellow_plate映射为 0二是坐标归一化用原图宽高不能用缩放后的尺寸。import os CLASS_MAP {yellow_plate: 0} def convert_to_yolo(json_dir, img_dir, out_dir): os.makedirs(out_dir, exist_okTrue) for fname in os.listdir(json_dir): if not fname.endswith(.json): continue json_path os.path.join(json_dir, fname) img_w, img_h, boxes load_annotation(json_path) lines [] for box in boxes: cls_id CLASS_MAP.get(box[label], -1) if cls_id -1: continue x1, y1, x2, y2 box[bbox] # 归一化并转为中心点宽高 xc (x1 x2) / 2.0 / img_w yc (y1 y2) / 2.0 / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h lines.append(f{cls_id} {xc:.6f} {yc:.6f} {w:.6f} {h:.6f}) # 输出同名 txt txt_name os.path.splitext(fname)[0] .txt with open(os.path.join(out_dir, txt_name), w) as f: f.write(\n.join(lines))CLASS_MAP是类别映射表如果数据集里还有蓝牌或其他类别按需扩展。归一化时保留 6 位小数足够YOLO 训练时对精度不敏感。输出目录与图片目录分开后续在 data.yaml 里分别指定路径即可。转换完成后建议随机抽几张图用可视化脚本画框验证确认坐标没偏移。2.3 转 COCO 格式适合多类别与评估如果后续要用 mmdetection 或 Detectron2COCO 格式更合适。COCO 的 json 是一个大文件包含images、annotations、categories三个主键。转换时把所有图的标注聚合到一个 json 里bbox格式是[x, y, width, height]不归一化。import json import os def convert_to_coco(json_dir, img_dir, out_json): coco {images: [], annotations: [], categories: [{id: 0, name: yellow_plate}]} ann_id 0 for idx, fname in enumerate(os.listdir(json_dir)): if not fname.endswith(.json): continue json_path os.path.join(json_dir, fname) img_w, img_h, boxes load_annotation(json_path) img_name os.path.splitext(fname)[0] .jpg coco[images].append({id: idx, file_name: img_name, width: img_w, height: img_h}) for box in boxes: x1, y1, x2, y2 box[bbox] coco[annotations].append({ id: ann_id, image_id: idx, category_id: 0, bbox: [x1, y1, x2 - x1, y2 - y1], area: (x2 - x1) * (y2 - y1), iscrowd: 0 }) ann_id 1 with open(out_json, w, encodingutf-8) as f: json.dump(coco, f, ensure_asciiFalse, indent2)area字段是 COCO 评估时计算 mAP 用的必须填。iscrowd一般设 0表示非密集遮挡。转换后可以用pycocotools加载验证确认没有报错。2.4 数据集划分与 data.yaml 配置转换完格式下一步是划分训练集、验证集、测试集。常见比例 7:2:1 或 8:1:1黄牌样本如果总量不大建议 8:1:1保证训练数据充足。划分时按文件名随机打乱避免同一场景的连续帧同时进训练和验证。# 假设图片在 images/标签在 labels/ # 创建目录结构 mkdir -p datasets/yellow_plate/images/train mkdir -p datasets/yellow_plate/images/val mkdir -p datasets/yellow_plate/labels/train mkdir -p datasets/yellow_plate/labels/val # 用 python 脚本按 8:1:1 划分并复制文件 python split_dataset.py --img_dir images --lbl_dir labels --out_dir datasets/yellow_plate --ratio 0.8 0.1 0.1split_dataset.py的逻辑就是读文件名列表随机 shuffle 后按比例切片分别复制图片和同名 txt 到对应目录。复制而非移动保留原始数据以防划分有误。划分完成后YOLO 的data.yaml这样写path: ./datasets/yellow_plate train: images/train val: images/val nc: 1 names: [yellow_plate]nc是类别数黄牌数据集通常只有一类如果混入了蓝牌或其他改成对应数字。names的顺序必须与转换时的CLASS_MAP一致否则训练时类别错位模型学出来的东西完全对不上。3. 训练配置与参数调优黄牌检测的 batch size、学习率与锚框数据准备好之后训练环节的参数设置直接决定模型能不能收敛、收敛后精度如何。黄牌检测跟通用目标检测有几点不同车牌区域在整图中占比小属于小目标检测范畴黄牌底色与车身颜色对比度有时不高尤其黄色工程车字符区域密集框的精度要求高。下面按 YOLOv8 的配置走一遍其他框架思路类似。3.1 输入分辨率与 batch size 的取舍车牌在 1920x1080 的原图里可能只占 200x60 像素如果直接 resize 到 640x640车牌区域会被压缩到 60x20 左右特征损失严重。常见做法是把输入分辨率提到 1280 或 1536或者用切片推理SAHI把大图切小块再检测。训练时imgsz设 1280 起步显存不够再降。from ultralytics import YOLO model YOLO(yolov8n.pt) # 从预训练权重起步 results model.train( datadatasets/yellow_plate/data.yaml, imgsz1280, epochs100, batch8, # 显存 8G 左右设 816G 可设 16 lr00.01, # 初始学习率 lrf0.01, # 最终学习率因子 momentum0.937, weight_decay0.0005, warmup_epochs3, patience20, # 20 轮无提升则早停 device0 )batch和imgsz是一对矛盾体显存有限时优先保imgsz因为小目标对分辨率更敏感。lr0设 0.01 是 YOLOv8 的默认值如果 loss 震荡厉害降到 0.001 再试。patience设 20 避免过拟合黄牌数据集如果只有几千张通常 60~80 轮就收敛了。3.2 锚框聚类与自适应调整YOLOv8 默认用自适应锚框训练前会根据数据集自动聚类一遍。但如果黄牌的长宽比跟 COCO 差异大比如黄牌普遍更扁宽高比 3:1 以上自动聚类可能不够准。可以手动跑一遍 k-means 看锚框分布import numpy as np from sklearn.cluster import KMeans # 读取所有 bbox 的宽高 wh [] for fname in os.listdir(labels/train): with open(flabels/train/{fname}) as f: for line in f: _, _, _, w, h map(float, line.strip().split()) wh.append([w, h]) wh np.array(wh) kmeans KMeans(n_clusters9, random_state0).fit(wh) print(kmeans.cluster_centers_)输出的 9 组宽高就是建议锚框。如果发现聚类结果里大部分锚框宽高比都在 2.5 以上说明黄牌确实偏扁可以在模型配置里替换默认锚框。不过 YOLOv8 的 anchor-free 机制对锚框依赖降低这一步更多是验证数据分布不强制改。3.3 数据增强策略针对黄牌场景的调整默认增强包括 mosaic、mixup、随机翻转、HSV 抖动。黄牌检测要慎用上下翻转因为车牌字符有方向性翻转后字符倒置模型会学到错误特征。左右翻转可以保留但要注意车牌字符左右翻转后也不对所以翻转增强对车牌检测其实都有风险。常见做法是关掉翻转加强 HSV 和随机裁剪。# 在 data.yaml 同级加 augment.yaml或直接在 train 参数里覆盖 hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4 degrees: 0.0 # 旋转角度设 0车牌倾斜靠数据本身覆盖 translate: 0.1 scale: 0.5 shear: 0.0 perspective: 0.0 flipud: 0.0 # 关闭上下翻转 fliplr: 0.0 # 关闭左右翻转 mosaic: 1.0 mixup: 0.1mosaic保留 1.0能让模型见到更多组合场景。mixup设 0.1 即可太高会让车牌区域模糊。HSV 的h调低一点因为黄牌颜色本身就是关键特征色调抖动太大会把黄色偏成橙色或绿色反而干扰。3.4 训练过程监控与指标解读训练启动后重点看三个指标box_loss、cls_loss、mAP50。box_loss下降说明框回归在收敛cls_loss下降说明分类在学。如果box_loss震荡不降检查标注是否有大量越界框或宽高为 0 的脏数据。mAP50到 0.9 以上基本可用黄牌检测因为背景相对干净通常能到 0.95 左右。# 训练日志里关注这几行 # Epoch 50/100 box_loss0.421 cls_loss0.312 mAP500.932 # 如果 mAP50 卡在 0.6 不动优先查标注格式和类别映射验证集 mAP 高但测试集低说明过拟合加数据或加增强。训练集 mAP 低说明欠拟合加轮次或加模型容量。黄牌数据集如果样本量少于 2000建议用 yolov8s 而非 yolov8n小模型容量不够容易欠拟合。4. 避坑与排查json 标签转换和训练中的五个血泪教训这一章记录我在用这份数据集时踩过的坑每条按现象、原因、解决写清楚能帮你省掉至少两轮重训的时间。4.1 现象转换后训练 loss 不降mAP 始终为 0原因json 里的label字段跟CLASS_MAP没对上比如 json 里写的是yellow映射表里只有yellow_plate导致所有框被跳过生成的 txt 是空文件。模型拿到的全是无标注图自然学不到东西。解决转换前先统计所有 json 里出现过的label值用set去重打印出来确认跟映射表一致。不一致就改映射表别改 json。labels set() for fname in os.listdir(json_dir): if fname.endswith(.json): with open(os.path.join(json_dir, fname), encodingutf-8) as f: data json.load(f) for s in data.get(shapes, []): labels.add(s[label]) print(labels) # 先看输出再写 CLASS_MAP4.2 现象可视化时框位置整体偏移或缩放原因json 里的imageWidth、imageHeight跟实际图片尺寸不一致。有些标注工具在图片被裁剪后没更新尺寸字段导致归一化时分母用错。解决转换时不要信 json 里的宽高直接用 PIL 或 OpenCV 读原图拿真实尺寸。from PIL import Image img Image.open(img_path) img_w, img_h img.size # 以实际图片为准4.3 现象训练到一半显存爆掉batch 被迫降到 1原因imgsz设了 1280 但batch没同步降或者数据加载时workers开太多每个 worker 都缓存了一批图。黄牌数据集图片分辨率普遍高显存占用比 COCO 大。解决imgsz和batch联动调1280 配 4~81536 配 2~4。workers设 4 或 8别超过 CPU 核数。如果还是爆用梯度累积模拟大 batch。model.train(..., batch4, accumulate2) # 等效 batch84.4 现象验证集 mAP 很高但实际推理时漏检严重原因训练时用了 mosaic 增强验证时也开了增强导致验证指标虚高。实际推理没有 mosaic分布不一致。解决验证时关掉增强val阶段设augmentFalse。另外检查推理时的conf阈值默认 0.25 可能过滤掉低置信度的黄牌调到 0.1 再试。model.val(datadata.yaml, augmentFalse, conf0.1)4.5 现象同一张图里多个黄牌只检出一个原因NMS 的iou_thres设太高两个车牌挨得近时被合并。黄牌大型车辆前后车牌距离近容易触发。解决把 NMS 的iou_thres从默认 0.7 降到 0.5或者用agnostic_nms关掉跨类别合并。推理时显式传参results model.predict(sourcetest.jpg, iou0.5, conf0.1)5. 进阶技巧用切片推理把黄牌小目标召回率拉上去黄牌在整图里占比小即使用 1280 分辨率训练推理时如果原图是 4K车牌区域仍然只有几十像素。切片推理SAHI的思路是把大图切成有重叠的小块每块单独检测再把结果映射回原图合并。这个技巧在交通卡口场景特别管用我实测能把小目标召回率从 0.82 拉到 0.94。先装 SAHI然后写一个切片推理脚本from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model AutoDetectionModel.from_pretrained( model_typeyolov8, model_pathruns/detect/train/weights/best.pt, confidence_threshold0.1, devicecuda:0 ) result get_sliced_prediction( test_4k.jpg, detection_model, slice_height640, slice_width640, overlap_height_ratio0.2, overlap_width_ratio0.2 ) result.export_visuals(export_diroutput/)slice_height和slice_width设 640跟训练分辨率对齐。overlap设 0.2 保证边缘目标不被切掉。切片数量大概是原图面积除以切片面积再乘重叠系数4K 图大概切 20~30 块推理时间比整图慢 3~5 倍但召回率提升明显。如果实时性要求高可以只对整图检测置信度低的区域做二次切片兼顾速度和精度。另一个技巧是 TTA测试时增强推理时对图片做水平翻转、多尺度缩放把多次预测结果融合。YOLOv8 自带augmentTrue参数results model.predict(sourcetest.jpg, augmentTrue, iou0.5)TTA 会让推理时间翻倍但 mAP 通常能涨 1~2 个点。黄牌检测如果对精度要求极高、不在乎耗时可以开。如果部署在边缘设备还是老老实实单次推理加切片。最后说一个验证习惯每次转换完数据别急着开训先抽 10 张图把标注框画出来肉眼过一遍。我见过太多因为坐标偏移、类别错位导致白跑几小时的情况。从那以后我每次拿到新数据集都强制走一遍「解析→转换→可视化→确认」的流程确认无误再启动训练。希望帮到你。本文还有配套的精品资源点击获取