ARTICLE DETAIL

资讯详情

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

YOLOV5汽车数据集训练全指南:目录格式、标签检查与避坑

YOLOV5汽车数据集训练全指南:目录格式、标签检查与避坑 简介一套按YOLOV5标准目录整理并可直接用于训练的汽车目标检测数据集面向正在学习目标检测、需要车辆识别样本的算法工程师与高校学生。图片采集自多种生活场景包含完整的jpg图像、png预览图与对应txt标签文件仅设car一个类别训练集有1000张图片及1000个标签验证集有208张图片及208个标签同时提供类别字典txt文件便于模型训练时读取类别映射。压缩包共2000个文件其中约1200个txt标注文件、近800张jpg/png图像文件并附带1个无需修改即可运行的可视化Python脚本可随机抽取图片绘制边界框并将结果保存到当前目录。资源包大小约243MB目录按照datasets/images/train与val结构划分无需额外整理即可接入YOLO训练流程。目前已有187人学习浏览。对需要快速验证YOLOv5、YOLOv8等车辆检测效果或搭建基准数据集的用户能显著省去手动采集、标注与转换的耗时。1. 拿到一份 YOLOV5 汽车数据集先别急着训练汽车目标检测是目标检测入门和高频落地最典型的方向而 YOLOV5 目录格式的汽车数据集基本是把这个方向从想法变成可训练工程的第一块基石。很多人拿到数据集后直接开训结果不是Label class 8 exceeds nc报错就是训练十几轮 loss 纹丝不动最后只能怀疑模型、怀疑显卡其实根子往往在目录结构和标签文件上。这类数据集的核心价值不是给你一堆照片而是省掉了标注、切分、格式转换这几步脏活。检索引擎里搜“yolov5 训练自己的数据集”的人绝大多数不是不会写模型而是被数据格式卡住。这篇文章就顺着这个数据集展开讲清楚 YOLOV5 目录格式是什么、怎么用它把训练跑通、数据里有哪些坑、以及怎么验证模型真的可用。适合刚接触目标检测想跑通第一个模型的人也适合已经在用其他格式数据集、想迁移到 YOLO 体系的工程人员。2. 拆解 YOLOV5 目录格式images/labels 为什么必须分开2.1 目录结构先立对train/val/test 与图片标签一一对应YOLOV5 的数据组织方式核心就是两组目录图片放在images下标签放在labels下切分后的子集由train/val/test目录来区分。一份合格的汽车目标检测数据集长这样dataset/ ├── images/ │ ├── train/ │ │ ├── car_001.jpg │ │ ├── car_002.jpg │ │ └── ... │ ├── val/ │ │ └── ... │ └── test/ │ └── ... ├── labels/ │ ├── train/ │ │ ├── car_001.txt │ │ ├── car_002.txt │ │ └── ... │ ├── val/ │ │ └── ... │ └── test/ │ └── ... └── dataset.yaml图片和标签是靠“同名不同后缀”关联的。car_001.jpg的训练标签就是car_001.txt这个对应关系在 YOLOV5 的 dataloader 里由img2label_paths这个函数完成它做的就是取图片路径、换目录、换后缀。很多人翻车的第一个点就在这里图片叫car_001.jpg标签叫1_car_001.txt或者图片和标签混放在同一个目录下这些都会导致训练时出现 “WARNING: No labels found in ...”看起来在跑但实际一个标签都没加载进来。还有一个常见做法值得确认数据集里如果只有train和val而没有test训练时test.txt会按空处理YOLOV5 本身不强制要求 test 集。但如果你打算用这份数据集做第三方评测最好单独留一份没参与过验证的test子集避免调参时窥探到测试分布。2.2 标签 txt 的格式类别索引加归一化框坐标YOLO 标签 txt 每一行对应一个目标格式是固定的五列class_id x_center y_center width heightclass_id从 0 开始整数后四列全部是归一化坐标范围 0 到 1等于像素值除以图片宽高。比如一张 1920x1080 的图一个车框左上角在 (960, 540)、宽高各 300 像素归一化后就是0 0.6875 0.6389 0.1562 0.2778x_center (960 300/2) / 1920 0.6875y_center (540 300/2) / 1080width 300 / 1920height 300 / 1080。浮点数的精度要保留到小数点后 6 位左右太短会让框的位置偏移几十个像素叠加在标注误差上会影响小目标检测的 mAP。同类数据集的标签通常已经做过这一步拿到后不用自己换算。但你需要确认一件事这份标签里的类别索引和dataset.yaml里names的顺序是否一致。很多汽车数据集类别定义是names: [car, truck, bus, motorcycle]如果标签 txt 里写的是 0-3而 yaml 里写成了[bus, car, ...]训练不会报错但模型会在 bus 的位置学 car推理结果一塌糊涂这是最难排查的隐性错误之一。2.3 为什么 YOLO 体系坚持 txt 而不是 XML/JSON用 VOC 的 XML 或 COCO 的 JSON 做目标检测数据集也很常见但 YOLOV5 这套 txt 方案在工程上更省事。XML 需要解析树结构JSON 需要按annotations和images两个数组做 ID 关联而 txt 是纯文本读一行切一列就是数值I/O 开销小配合归一化坐标可以不用管图片尺寸——dataloader 读图后直接按模型输入分辨率缩放标签坐标天然不受影响。还有一个经常被忽略的理由txt 方便做数据增强。Mosaic 拼接时要把四张图的标签全部映射到一个新的画布坐标系纯数值数组直接做平移缩放运算非常顺手而 XML/JSON 里存的是绝对像素坐标增强时还要同步改尺寸字段写错的概率高很多。这份数据集坚持 YOLOV5 目录格式本质上就是选了一条离训练最近的路。3. 用这份汽车数据集跑通 YOLOV5 训练yaml 配置与命令3.1 数据划分与目录规划不管数据集自带多少张图片拿到后先看一眼分布。常见做法是用一个脚本把各子集的数量统计出来比如images/train里约 7000 张、val里约 1500 张、test里约 1500 张总计一万张左右。如果发现val缺失或者数量占比少于 5%自己用 8:1:1 或 9:1 的比例重切。切分时要注意按“文件夹整体”移动不要打乱同名配对关系。一个我自己常用的检查点是验证集和测试集必须和训练集来自同一分布。如果这张数据集的图片是从不同监控摄像头、不同天气、不同时间段采集的重切分时先按来源分组再从每组里按比例抽到 val/test。否则随机切分很容易把某个特定时段的图片全部塞进验证集导致 val mAP 虚高部署到实际场景后性能断崖。3.2 编写 dataset.yaml路径、类别、nc 三者缺一不可YOLOV5 的dataset.yaml是训练入口的数据说明文件最简写法如下# dataset.yaml path: /data/vehicle_detection/dataset # 数据集根目录建议绝对路径 train: images/train # 相对 path 的训练图片目录 val: images/val # 相对 path 的验证图片目录 test: images/test # 可选没有可以删掉这行 nc: 4 # 类别数量 names: [car, truck, bus, motorcycle] # 类别名称索引从0开始这份 yaml 里最容易出问题的是path字段。YOLOV5 新版把train/val作为相对path的路径来解析如果写成train: /data/.../images/train这种绝对路径部分版本会拼接出/data/.../images/train/images/train这样的重复路径。我一般统一用相对路径加根目录的方式并在训练前先跑数据加载自检。nc和names的数量必须和标签文件里的最大类别索引对得上。比如标签里出现过类别索引 5而nc只写了 5对应索引 0-4训练一开始就会抛出Label class 5 exceeds nc5 in ...这时直接改 yaml 是无效的因为问题是标签数据超出预期类别范围属于数据问题要回到第 4 章的标签检查流程里去处理。3.3 模型配置与训练启动命令YOLOV5 有 s/m/l/x 四个体积档位在这一万张规模的汽车数据集上从yolov5s起步是合理选择。它能在单张消费级显卡上快速迭代模型权重约 14MB边训练边调参的反馈周期短。训练脚本自带模型结构文件引用不需要手动修改yolov5s.yaml但如果你用官方仓库训练注意在models/yolov5s.yaml里确认nc被自动覆盖成数据集 yaml 的nc旧版本需要手动把nc: 80改成你的类别数漏掉这个会导致分类层维度不匹配崩掉。克隆官方仓库后训练命令一般长这样python train.py \ --data /data/vehicle_detection/dataset/dataset.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --cache ram \ --project /output/vehicle_yolov5--img 640是输入分辨率汽车目标通常在中大尺度640 性价比最高追求小目标可以上 1280但显存占用和训练时间都会明显上涨。--batch 16在 8GB 显存的卡上跑 s 模型比较稳如果 OOM 先降到 8不要直接关掉训练脚本换模型。--cache ram会把图片一次性载入内存一万张 640 分辨率的图大约需要 6-8GB 内存够的话建议开着能省掉每个 epoch 反复读盘的 I/O 时间。训练日志里重点看三个量box_loss、obj_loss、cls_loss是否在稳步下降mAP0.5是否一路抬升以及每个 epoch 结束时的P/R精确率和召回率是否平衡。如果R明显低于P通常是漏检比误检多优先回看标签里小目标的比例。3.4 权重输出与推理验证训练完不等于能直接用训练结束后/output/vehicle_yolov5/exp/weights/下会出现best.pt和last.pt。best.pt是按验证集 mAP 保存的最优权重last.pt是最后一个 epoch 的权重。部署优先用best.pt但如果best出现在前 30 个 epoch而后面 70 个 epoch 的 mAP 一直没能超过它说明学习率衰减策略有优化空间常见做法是加--cos-lr或者在 60 epoch 附近手工降学习率。推理验证用官方detect.pypython detect.py \ --weights /output/vehicle_yolov5/exp/weights/best.pt \ --source /data/vehicle_detection/test_images \ --img 640 \ --conf-thres 0.4 \ --iou-thres 0.5 \ --save-txt--conf-thres控制置信度阈值0.4 是个保守起点如果检测框太多互相叠加往 0.5 以上调如果漏检明显往 0.3 以下调。--iou-thres是 NMS 的 IoU 阈值0.5 是通用值密集车辆场景可以降到 0.4减少相邻目标被合并的情况。跑完后打开runs/detect/exp下的可视化图片这是验证数据集质量最直观的方式。4. 数据质量治理训练前把标签彻底检查一遍4.1 标签合法性脚本五类异常一次查清YOLO 标签最常见的五类异常是坐标不在 0-1 范围、宽高为 0 或负值、类别索引越界、txt 空文件、坐标解析失败。把这些检查写成一个独立脚本训练前跑一遍能在 10 分钟内替你把训练中可能出现的各种玄学问题挡在门外。import os from pathlib import Path label_dirs [dataset/labels/train, dataset/labels/val, dataset/labels/test] nc 4 # 与 dataset.yaml 保持一致 for ld in label_dirs: for txt in Path(ld).glob(*.txt): lines txt.read_text().strip().splitlines() if not lines: print(f[EMPTY] {txt}) continue for i, line in enumerate(lines): parts line.strip().split() if len(parts) ! 5: print(f[COLUMN] {txt} line {i}: {line}) continue try: cls, x, y, w, h map(float, parts) except ValueError: print(f[PARSE] {txt} line {i}: {line}) continue if cls 0 or cls nc: print(f[CLASS] {txt} line {i}: cls{cls}) if w 0 or h 0: print(f[SIZE] {txt} line {i}: w{w}, h{h}) if not (0 x 1 and 0 y 1): print(f[POS] {txt} line {i}: cx{x}, cy{y})这个脚本不会修改任何文件它只负责把异常打印出来。拿到异常列表后逐条处理空文件直接删掉意味着这张图没有目标坐标越界通常是标注工具导出的 bug用裁剪到 0-1 区间的脚本统一修复类别索引越界要回到标签源头看是不是标注时选错了类。修复完成后再跑一遍脚本直到输出为空。这一步虽然花时间但它是避免训练到一半才翻车的唯一手段。4.2 类别样本统计与长尾处理汽车场景的数据集往往存在严重的类别不均衡car占了七八成motorcycle只有几百个样本。用脚本统计每个类别的框数量for f in dataset/labels/train/*.txt; do awk {print $1} $f; done | sort | uniq -c如果某个类别的框数量低于总框数的 5%模型对这个类的 mAP 大概率会很难看。常规解法有三条路一是去补充该类别的图片成本最高二是对这类样本做离线增强比如把摩托车图片上下左右翻转、调整亮度饱和度扩充数量三是调整--cls损失权重让模型更重视稀少类别。第三条路的参数在 YOLOV5 的loss.py里通过cls_pw控制效果不如前两者直接但在样本完全无法补充时是最后的后悔药。还有一个常被忽略的点只有框数量均衡不够要看类别在不同尺度下的分布。如果bus只出现在大尺度motorcycle只出现在小尺度模型学到的其实是“尺度”和“类别”的关联而不是真正的类别特征。抽样看几十张标注图确认小目标类别没有被系统性漏标这比任何统计指标都可靠。4.3 增强参数怎么调mosaic 不是越大越好YOLOV5 自带的数据增强默认开启mosaic1.0它把四张图拼成一张训练对小目标检测效果显著。但汽车数据集里如果已经包含了大量小目标mosaic 把小图再缩小一倍会导致目标过小、特征完全丢失。常见的做法是把--mosaic在最后 20 个 epoch 关闭YOLOV5 的hyp.scratch.yaml里可以按 epoch 阶段调整让模型在接近真实分布的数据上微调收敛。增强参数的另外两个重点是hsv_h/hsv_s/hsv_v色调、饱和度、亮度偏移和fliplr水平翻转。汽车场景里车灯、车牌这些特征对颜色敏感色调偏移幅度建议从默认的 0.015 降到 0.005水平翻转可以放心开对称性对车辆目标成立。垂直翻转不要开车辆在画面里的上下关系不是可交换的。4.4 标注工具与格式转换如果这份数据集要自己扩展拿到这份数据集后往往要往里加自己的图片格式转换就是个绕不开的环节。标注时建议直接用 LabelImg 或 X-AnyLabeling 这类带 YOLO 输出格式的工具它们会直接生成同名 txt不需要额外转换。如果手里已经有 VOC 格式的标注转换脚本的框架是遍历 XML读bndbox的四个像素坐标再除以图片宽高得到归一化值import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_path, out_txt): img Image.open(img_path) w_img, h_img img.size root ET.parse(xml_path).getroot() with open(out_txt, w) as f: for obj in root.findall(object): cls obj.find(name).text box obj.find(bndbox) x1 int(box.find(xmin).text) y1 int(box.find(ymin).text) x2 int(box.find(xmax).text) y2 int(box.find(ymax).text) x_c ((x1 x2) / 2) / w_img y_c ((y1 y2) / 2) / h_img w (x2 - x1) / w_img h (y2 - y1) / h_img f.write(f0 {x_c:.6f} {y_c:.6f} {w:.6f} {h:.6f}\n)这个脚本是类别无关的cls到索引的映射需要自己维护一张字典。常见的坑是 XML 里xmax比图片宽度还大或者xmin为 0 但bndbox解析出来的宽度把边界扩到图片外了。这类边界框在 VOC 里合法但 YOLO 的归一化坐标会超出 0-1 范围落回训练时就是上一节脚本里查出的[POS]异常。转换后务必把 4.1 的检查脚本再跑一遍。5. 训练避坑汽车目标检测数据集最常见的翻车现场5.1 现象训练前报错 “Label class 8 exceeds nc4”原因标签文件里出现了类别索引 8而 yaml 里nc只写了 4。这通常是标签文件里混了其他数据集的类别编号或者标注工具导出时类目选择错误。解决先定位是哪些 txt 文件出了问题用 4.1 节脚本筛选出[CLASS]行。看那个目标实际是什么——如果确实是汽车把类别索引改成 0如果根本不是目标类别直接删掉这一行。不要为了训练去把nc改成 9那会让模型学到一个你并不需要的类别。5.2 现象训练可以跑但 mAP 一直是 0loss 高居不下原因绝大多数情况是dataset.yaml里的train/val路径写错导致加载到的是一组空标签。YOLOV5 的日志里会有 “WARNING: No labels found in ...”但这条警告混在大量训练日志里很容易被刷掉。解决训练前单独跑一次数据加载自检python train.py --data dataset.yaml --weights yolov5s.pt --img 640 --batch 1 --epochs 1看日志开头是否打印出Scanning的图片数和标签数以及labels的统计柱状图。如果柱状图全是空回到目录结构章节检查images和labels的对应关系。5.3 现象val 集 mAP 很高但实测单张图片检测效果差原因验证集和训练集来自同一批采集数据场景高度相似模型等于做了“开卷考试”。尤其当数据集图片来自单一摄像头时模型学到的是背景特征而不是车本身的特征。解决单独收集一小批不同时间、不同场景的图片50-100 张作为外部验证集跑detect.py看泛化效果。如果外部验证集 mAP 掉得厉害优先从数据侧解决——补充多样化的图片而不是去调模型结构。5.4 现象训练中断提示图片加载失败或图像尺寸错误原因数据集里的图片可能有损坏的 JPEG、有 EXIF 方向旋转、或者 PNG 带透明通道导致读图异常。YOLOV5 的 dataloader 会尝试跳过坏图但文档里没写的是跳过坏图的同时会丢掉对应的标签文件形成“图片缺失但标签还留着”的脏数据。解决先用脚本扫描所有图片是否能正常打开from PIL import Image from pathlib import Path for img_path in Path(dataset/images/train).glob(*.*): try: Image.open(img_path).load() except Exception as e: print(f[BROKEN] {img_path}: {e})找到坏图后把图片和同名标签一起删除。不要只删图片不删标签否则后续 epochs 会在标签目录里发现找不到对应的目标图片影响 dataloader 的基准统计。5.5 现象显存充足仍然 OOMbatch 降到 2 也救不回来原因某些训练配置里--image-weights或--cache会额外吃显存另外 1280 分辨率的输入在特征图上比 640 多出 4 倍内存。如果用的还是 m/l/x 模型固定 batch size 下 OOM 是必然的。解决先在 s 模型、640 分辨率、batch 8 的配置上跑通完整流程再逐步往上加。显存不够时优先降--batch其次降--img不要一上来就把模型换成 tiny 版tiny 在汽车小目标上的精度损失明显。6. 模型可用的判断标准用 mAP、混淆矩阵和外部验证说话训练结束后runs/.../exp/下生成的results.png可以把你的模型从“黑匣子”变成可解释的对象。曲线上一共九个子图但核心只看两组第一组是P/R曲线和mAP0.5、mAP0.5:0.95第二组是confusion_matrix.png和labels_correlogram.jpg。mAP0.5:0.95在汽车检测场景里比mAP0.5更值得关注因为这个 IoU 区间覆盖了从宽松到严格的定位要求。如果两个指标差距过大比如 0.5 有 0.90.95 只有 0.3说明框的位置偏边界不够贴合优先检查标签的标注质量而不是模型结构。混淆矩阵则能直接看出类别之间的互相混淆——bus 和 truck 在视觉上高度相似这一项出现高位假阳性很常见。验证模型的第二个层次是看尺度维度。把验证集图片按目标面积分成小/中/大三组分别统计 AP如果小目标 AP 明显低于大目标回到增强参数调--img到 1280 或者增加 mosaic 的启用比例。第三个层次是跑一段视频做时序稳定性测试——模型在单张图片上表现好在视频里不一定稳定汽车场景尤其要关注相邻帧间的检测框抖动常见做法是接入 DeepSORT 之类的跟踪器做平滑这属于部署层的优化。最后留下一个我自己的习惯每个跑通的数据集都把dataset.yaml、训练命令、标签检查脚本、最后的 mAP 指标存成一个文本文件放在数据集根目录下。下次换机器重训或者换同事接手时不需要重新摸索参数。这套工作流帮我省过很多次重复踩坑的时间也希望能帮到你。本文还有配套的精品资源点击获取
返回列表