YOLOv5数据集目录格式详解:智能小车物品识别实战指南

发布时间:2026/10/9 20:01:09
YOLOv5数据集目录格式详解:智能小车物品识别实战指南
简介本资源为面向目标检测入门与智能小车视觉应用场景的YOLOv5格式数据集聚焦智能购买环节中的物品识别任务适合正在学习YOLO训练流程、需要快速验证检测代码的开发者与高校学生使用。数据采用标准YOLOV5目录结构组织无需额外转换即可直接投入训练图像统一为416×416的RGB图片标注类别为单类purchase覆盖智能小车对特定目标进行识别以实现智能购买的需求。压缩包共1777个文件以jpg图像与txt标注文件为主另含类别字典txt及一个可视化py脚本整体约26.48MB其中训练集含710张图片与711个标签测试集含177张图片与177个标签。可视化脚本可随机读取一张图片绘制边界框并保存至当前目录无需修改即可运行便于快速检查标注质量。目前已有157人学习适合作为目标检测练手与代码测试的轻量级数据支撑。1. 智能小车物品识别数据集YOLOv5目录格式到底长什么样做过智能小车视觉模块的工程师大概都有过这种体验算法代码跑通了模型结构也调好了结果卡在数据集上——标注文件格式不对、目录层级混乱、类别编号从1开始而不是0、图片和标签对不上号。智能小车物品识别这个场景尤其典型摄像头视角低、物品尺度变化大、背景干扰多数据集的质量直接决定模型能不能在车上跑出可用效果。而智能购买图像目标检测又是另一个高频需求货架商品、购物车物品、手持商品的检测框精度要求更高。这两个场景合在一起落到工程上就是一件事你需要一套符合YOLOv5目录格式的目标检测数据集拿来就能训练不用再花两天时间做格式转换和路径排查。这篇文章不讲空泛的“数据集很重要”而是把YOLOv5目录格式的每个文件、每个参数、每个容易翻车的地方拆开讲清楚。适合谁看正在做智能小车视觉模块的嵌入式工程师、准备训练商品检测模型的算法同学、以及第一次接触YOLOv5数据集格式不知道从哪下手的新手。读完你至少能做到自己组织一套YOLOv5格式的数据集跑通训练并且在mAP不涨的时候知道该查哪里。2. YOLOv5目录格式拆解从images到labels的完整映射2.1 标准目录树与每个文件的职责YOLOv5对数据集的目录结构有明确的约定不是随便放放就能跑。常见做法是按照以下层级组织dataset/ ├── images/ │ ├── train/ │ │ ├── 000001.jpg │ │ ├── 000002.jpg │ │ └── ... │ ├── val/ │ │ ├── 000101.jpg │ │ └── ... │ └── test/ # 可选 │ └── ... ├── labels/ │ ├── train/ │ │ ├── 000001.txt │ │ ├── 000002.txt │ │ └── ... │ ├── val/ │ │ ├── 000101.txt │ │ └── ... │ └── test/ │ └── ... └── data.yaml这里有几个硬性约束。第一images和labels下的子目录名必须一一对应train对trainval对val不能一个叫train一个叫training。第二图片文件和标签文件的主文件名必须完全相同只是扩展名不同。000001.jpg对应000001.txt如果写成000001_label.txt训练时就会报“No labels found”然后所有框都是空的。第三标签文件是.txt纯文本不是.xml也不是.json。每个标签文件的内容格式是class_id x_center y_center width height五个值之间用空格分隔每行一个目标。一张图里有三个目标就写三行。class_id从0开始计数不是从1开始。坐标全部是归一化后的值范围0到1不是像素值。这一点是新手最容易翻车的地方——拿到的标注如果是像素坐标直接写进去训练模型学出来的框会全部挤在左上角。2.2 data.yaml的六个关键字段data.yaml是YOLOv5训练时的数据配置入口内容不多但每个字段都不能写错# data.yaml path: /home/user/dataset # 数据集根目录绝对路径 train: images/train # 训练集图片路径相对于path val: images/val # 验证集图片路径相对于path test: images/test # 测试集图片路径可选 nc: 5 # 类别数量 names: # 类别名称列表顺序必须和class_id对应 0: bottle 1: box 2: can 3: bag 4: phonepath字段建议写绝对路径相对路径在不同工作目录下启动训练时容易找不到文件。train和val写相对于path的路径注意这里只写到images这一层YOLOv5会自动把images替换成labels去找对应的标签文件。nc是类别数names的键值对顺序必须和标注时的class_id严格一致。如果标注时bottle是0这里bottle就必须写在0的位置写反了模型会把瓶子识别成盒子而且loss曲线看起来还挺正常这种玄学问题排查起来很费时间。2.3 从零组织一套智能小车物品识别数据集的完整步骤假设你手头有一批智能小车拍摄的物品图片以及对应的标注文件可能是VOC XML格式或者COCO JSON格式需要转成YOLOv5格式。以下是可复现的操作流程。第一步建立目录骨架# 创建标准YOLOv5数据集目录结构 mkdir -p dataset/images/train dataset/images/val mkdir -p dataset/labels/train dataset/labels/val第二步划分训练集和验证集。常见做法是按8:2或9:1划分智能小车场景下如果图片总数少于2000张建议按8:2验证集至少留100张以上否则mAP波动会很大。import os import random import shutil # 原始图片目录和标注目录 src_images raw_images src_labels raw_labels dst_root dataset # 获取所有图片文件名不含扩展名 all_files [os.path.splitext(f)[0] for f in os.listdir(src_images) if f.endswith(.jpg)] random.seed(42) # 固定随机种子保证可复现 random.shuffle(all_files) split_idx int(len(all_files) * 0.8) train_files all_files[:split_idx] val_files all_files[split_idx:] # 复制图片和标签到对应目录 for phase, files in [(train, train_files), (val, val_files)]: for name in files: shutil.copy(f{src_images}/{name}.jpg, f{dst_root}/images/{phase}/{name}.jpg) shutil.copy(f{src_labels}/{name}.txt, f{dst_root}/labels/{phase}/{name}.txt) print(f训练集: {len(train_files)} 张, 验证集: {len(val_files)} 张)这段脚本做了三件事固定随机种子保证每次划分结果一致、按比例切分文件列表、把图片和标签成对复制到目标目录。注意random.seed(42)这行不固定种子的话每次重新划分数据集验证集变了mAP就没法横向对比调参时根本分不清是模型改进了还是验证集换了。第三步如果标注是VOC XML格式需要转成YOLO的txt格式import xml.etree.ElementTree as ET import os # 类别映射表必须和data.yaml中的names一致 class_map {bottle: 0, box: 1, can: 2, bag: 3, phone: 4} def voc_to_yolo(xml_path, img_w, img_h): 将VOC XML标注转换为YOLO格式的标签行 tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in class_map: continue # 跳过未定义类别 cls_id class_map[cls_name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 转换为归一化的中心点坐标和宽高 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h # 裁剪到[0,1]范围防止标注越界 x_center max(0, min(1, x_center)) y_center max(0, min(1, y_center)) width max(0, min(1, width)) height max(0, min(1, height)) lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) return lines转换逻辑的核心是坐标归一化VOC给的是左上角和右下角的绝对像素坐标YOLO要的是中心点坐标加宽高并且全部除以图片的宽高做归一化。保留6位小数足够YOLOv5内部会再做一次缩放。裁剪到[0,1]是防止标注人员手抖把框拖出图片边界越界的坐标会导致训练时loss异常。2.4 用YOLOv5自带脚本做数据校验YOLOv5仓库里有一个utils/general.py中的检查逻辑但更直接的方式是训练前跑一次dry-run。常见做法是用小epoch数先跑一轮# 用1个epoch快速验证数据集格式是否正确 python train.py --data data.yaml --epochs 1 --batch-size 4 --img-size 640 --weights yolov5s.pt如果数据集有问题这一步会直接报错比如“No labels found in …”说明标签路径不对“Label class 5 exceeds nc5”说明类别编号超了“invalid label”说明坐标格式有问题。花两分钟跑一轮比训练到一半才发现问题再回头改要划算得多。3. 智能购买场景下的类别设计与标注策略3.1 类别粒度怎么定从“瓶装水”到“500ml矿泉水”的取舍智能购买图像目标检测和智能小车物品识别在类别设计上有一个共同难点类别粒度太粗模型学不到区分性特征太细标注成本爆炸且样本不均衡。我一般会按以下原则做取舍。第一按功能用途分大类不按品牌分小类。比如“饮料瓶”作为一个类不要分成“可乐瓶”“雪碧瓶”“矿泉水瓶”。原因很简单智能购买场景下用户关心的是“这是什么类型的物品”不是“哪个牌子”。而且品牌包装更新频繁今天标了明天换包装模型就废了。第二外观差异大于30%才单独设类。比如“纸盒”和“塑料瓶”外观差异明显分两类没问题。“大纸盒”和“小纸盒”如果只是尺寸差异不建议分两类因为YOLOv5对尺度变化本身就有一定的适应能力强行分类反而导致小样本类别mAP极低。第三类别数控制在5到15之间。少于5类模型容易过拟合多于15类在智能小车这种算力受限的平台上推理速度和精度都会明显下降。如果确实需要检测很多种物品常见做法是先做粗分类再做细分类两级级联。3.2 标注框的四个边界规则标注质量直接决定模型上限。以下四条规则是我踩过坑之后总结出来的。规则一框要贴紧目标边缘不留空隙也不过度收缩。留空隙会让模型学出偏大的框过度收缩会让模型漏检边缘特征。判断标准是框的边线应该刚好压住目标的最外轮廓像素。规则二遮挡目标按可见部分标注。如果一个瓶子被另一个盒子挡住了一半框只标可见的那一半不要脑补被遮挡的部分。脑补出来的框和实际推理时模型看到的不一致反而降低精度。规则三密集排列的目标逐个标注不合并。货架上并排的五瓶水就是五个框不要画一个大框把五瓶水全包进去。合并标注会让模型学出“一大片区域都是目标”的错误认知。规则四小于图像面积0.5%的目标直接忽略。智能小车摄像头分辨率有限太小的目标标注了模型也学不到反而引入噪声。如果确实需要检测小目标应该提高摄像头分辨率或者用切图推理。3.3 用脚本做标注一致性检查标注人员多了之后不同人的标注风格会有差异。写一个检查脚本在训练前跑一遍import os def check_labels(label_dir, img_dir, nc): 检查标签文件的格式和数值范围 issues [] for txt_file in os.listdir(label_dir): if not txt_file.endswith(.txt): continue txt_path os.path.join(label_dir, txt_file) img_name os.path.splitext(txt_file)[0] .jpg img_path os.path.join(img_dir, img_name) # 检查图片是否存在 if not os.path.exists(img_path): issues.append(f图片缺失: {img_name}) continue with open(txt_path, r) as f: for line_num, line in enumerate(f, 1): parts line.strip().split() if len(parts) ! 5: issues.append(f{txt_file} 第{line_num}行: 字段数{len(parts)}应为5) continue cls_id int(parts[0]) if cls_id 0 or cls_id nc: issues.append(f{txt_file} 第{line_num}行: class_id{cls_id} 超出范围[0,{nc-1}]) coords [float(x) for x in parts[1:]] for i, v in enumerate(coords): if v 0 or v 1: issues.append(f{txt_file} 第{line_num}行: 坐标值{v}超出[0,1]) return issues # 使用示例 problems check_labels(dataset/labels/train, dataset/images/train, nc5) for p in problems[:20]: # 只打印前20条 print(p) print(f共发现 {len(problems)} 个问题)这个脚本检查四件事标签文件对应的图片是否存在、每行是否恰好5个字段、class_id是否在有效范围内、坐标是否归一化到[0,1]。训练前跑一遍能拦掉大部分低级错误。4. 避坑与排查训练不收敛时先查这五个地方4.1 现象loss从第一轮就不下降原因通常是标签格式错误。最常见的是坐标没有归一化还是像素值。比如x_center写成了320而不是0.5YOLOv5读取后虽然不会报错但计算loss时预测值和目标值差距巨大梯度爆炸或者直接nan。解决用上面的check_labels脚本跑一遍确认所有坐标值都在0到1之间。如果发现大量坐标大于1说明标注转换时漏了除以图片宽高这一步。4.2 现象训练正常但mAP始终在0.1以下原因可能是类别编号和data.yaml中的names顺序不一致。比如标注时bottle是0但data.yaml里bottle写在了1的位置。模型学到的“0号类别”和验证时认为的“0号类别”不是同一个东西mAP自然上不去。解决打印data.yaml的names再随机抽几个标签文件看class_id分布确认对应关系。这个坑很隐蔽因为loss曲线看起来完全正常只有mAP不涨。4.3 现象验证集mAP远低于训练集mAP原因通常是训练集和验证集的数据分布不一致。比如训练集全是白天拍摄的图片验证集混入了夜间图片或者训练集物品摆放整齐验证集物品杂乱堆叠。解决检查划分数据集时的随机种子是否固定确认两个集合的拍摄条件、光照、背景尽量一致。如果确实需要模型适应多种条件应该在训练集中就包含这些变化而不是留给验证集去“考验”模型。4.4 现象模型对某些类别完全检测不到原因可能是该类别样本数太少或者标注框尺寸异常。YOLOv5的anchor是基于COCO数据集统计的如果你的目标尺寸和COCO差异很大默认anchor可能匹配不上。解决先统计每个类别的样本数和框的宽高分布。如果某个类别样本数少于总样本的5%考虑补充数据或者用过采样。如果框的宽高比极端比如细长条可以用k-means重新聚类生成自定义anchor# 用YOLOv5自带脚本聚类生成自定义anchor python utils/autoanchor.py --data data.yaml --img-size 6404.5 现象推理时框的位置整体偏移原因通常是训练时的img-size和推理时的输入尺寸不一致或者标签坐标在转换时用了错误的图片宽高。比如图片实际是640x480但转换时按640x640算的y方向坐标就会整体偏移。解决确认转换脚本中读取的图片宽高和实际图片一致。用PIL或OpenCV读取图片尺寸时注意EXIF方向信息有些手机拍摄的图片EXIF里带了旋转标记直接读会得到错误的宽高。5. 用YOLOv5训练智能小车物品识别模型的参数调优技巧5.1 小目标检测的img-size与anchor设置智能小车摄像头通常安装位置较低拍摄的物品在画面中占比不大属于小目标检测场景。YOLOv5默认的img-size是640对于小目标建议提高到960或1280。但要注意img-size提高后显存占用和推理时间都会增加在嵌入式平台上需要做权衡。一个实用的技巧是先用640跑一轮baseline看mAP和推理速度。如果mAP明显偏低且推理速度有余量再提高到960。不要一上来就上1280训练时间翻倍不说小数据集上还容易过拟合。anchor方面用autoanchor脚本重新聚类。智能小车场景下的物品框通常偏小默认anchor中较大的那几个可能根本用不上重新聚类能让anchor更贴合实际数据分布。5.2 数据增强参数的场景化调整YOLOv5默认开启了mosaic、mixup、HSV增强等。在智能购买场景下有几个参数需要根据实际情况调整。mosaic增强默认概率是1.0它把四张图拼成一张。这个增强对小目标检测很有帮助但如果你的物品经常被遮挡mosaic可能引入不真实的拼接边界。建议先用默认值跑如果验证集mAP波动大把mosaic降到0.5试试。HSV增强中的hsv_h色调、hsv_s饱和度、hsv_v亮度默认分别是0.015、0.7、0.4。智能小车在室内外切换时亮度变化大hsv_v可以适当提高到0.5。但如果你的场景光照稳定调太高反而让模型学到无关的颜色变化。# 训练命令示例带关键参数说明 python train.py \ --data data.yaml \ --weights yolov5s.pt \ --img-size 960 \ --batch-size 8 \ --epochs 100 \ --mosaic 0.5 \ --hsv-v 0.5 \ --project runs/train \ --name smart_cart_v15.3 用验证集曲线判断过拟合与欠拟合训练过程中重点看三个曲线train/box_loss、val/box_loss、metrics/mAP_0.5。如果train/box_loss持续下降但val/box_loss在某个epoch后开始上升说明过拟合了。解决方法是增加数据增强、减少模型参数量换yolov5n或yolov5s、或者早停。如果两个loss都下降很慢且mAP低于0.3说明欠拟合。检查学习率是否太低、anchor是否匹配、类别是否太难区分。如果mAP在某个值附近震荡不涨常见原因是学习率到了平台期。YOLOv5默认用余弦退火调度一般不需要手动调。但如果数据集特别小少于500张可以把学习率从0.01降到0.001试试。5.4 导出模型到智能小车端的注意事项训练完成后导出ONNX或TensorRT时注意输入尺寸要和训练时一致。如果训练用960导出时也写960。另外YOLOv5的推理输出包含三个尺度的特征图后处理中的NMS阈值需要根据实际场景调。智能购买场景下物品密集NMS的iou阈值建议从默认的0.45降到0.3到0.4之间避免相邻物品的框被误删。我自己的习惯是每次改完数据集或训练参数先跑1个epoch确认没有格式报错再跑10个epoch看loss趋势是否正常最后才跑完整训练。这样虽然多花了几分钟但省下了大量“训练到一半发现数据有问题”的后悔药时间。希望帮到你。本文还有配套的精品资源点击获取