简介本资源为面向目标检测入门与智能小车视觉项目实践者的YOLOv5格式数据集聚焦智能购买场景下的物品识别任务可用于训练与验证单类别检测模型帮助读者快速跑通从数据加载到边界框可视化的完整流程。压缩包共1777个文件以jpg图像与txt标注文件为主另含1个可视化py脚本和1个png示意图整体约26.48MB目录按YOLOv5规范组织无需额外转换即可直接投入训练。数据分为训练集710张图片与711个标签、测试集177张图片与177个标签图像为416×416的RGB图片类别仅purchase一类并附检测类别字典文件。可视化脚本随机传入一张图片即可绘制边界框并保存至当前目录无需修改即可运行便于检查标注质量与模型效果。目前已有157人学习适合作为课程设计、竞赛验证或算法调试的轻量级数据基础。1. 智能小车物品识别为什么 YOLOv5 目录格式是绕不开的第一道坎做智能小车物品识别的人十有八九在数据集这一步翻过车。模型结构抄得再顺、训练脚本跑得再溜只要目录格式和标注文件对不上训练照样在第一个 epoch 就报错退出。YOLOv5 目录格式之所以成为事实标准是因为它把「图片放哪、标签放哪、类别怎么编号」这三件事用一套极简约定固定下来让数据加载器不用猜。智能购买场景下的图像目标检测本质是让小车摄像头识别货架或桌面上的物品输出类别和位置再驱动抓取或结算逻辑。这套数据集格式适合两类人一是刚接手智能小车视觉模块、需要快速跑通训练闭环的嵌入式开发者二是手里有一批标注数据、想迁移到 YOLOv5 训练管线却卡在格式转换上的算法同学。下面从目录结构讲到训练验证把每一步的参数和坑都摊开。2. YOLOv5 目录格式拆解images、labels 与 data.yaml 的三角关系2.1 标准目录树长什么样YOLOv5 官方推荐的数据集目录结构并不复杂但每一层的命名和位置都有硬性要求。常见做法是建一个数据集根目录下面分 images 和 labels 两个平行文件夹各自再分 train、val有时加 test。标签文件必须和图片文件同名只是扩展名从 .jpg 换成 .txt。这个「同名不同扩展」的约定是数据加载器定位标签的唯一依据改一个字都会导致找不到标签。dataset/ ├── images/ │ ├── train/ │ │ ├── item_0001.jpg │ │ └── item_0002.jpg │ └── val/ │ ├── item_0101.jpg │ └── item_0102.jpg ├── labels/ │ ├── train/ │ │ ├── item_0001.txt │ │ └── item_0002.txt │ └── val/ │ ├── item_0101.txt │ └── item_0102.txt └── data.yaml上面这段目录树里images/train 和 labels/train 是成对出现的val 同理。注意 labels 下不要放任何图片images 下也不要放 txt混放会让加载器把非图片文件当样本读直接抛异常。data.yaml 放在根目录路径写法有两种绝对路径最稳相对路径则相对于训练时的工作目录容易因为启动位置不同而失效。2.2 标签 txt 的每一行到底在写什么每个标签 txt 文件里一行对应一个目标框格式是「类别编号 中心x 中心y 宽 高」后四个值都是归一化到 0 到 1 之间的小数。类别编号从 0 开始和 data.yaml 里 names 列表的顺序严格对应。这里最容易翻车的是归一化有人直接拿像素坐标除以图片宽度忘了中心点要先算 (xminxmax)/2结果框整体偏移。# 把 VOC 的 xmin,ymin,xmax,ymax 转成 YOLO 归一化格式 def voc_to_yolo(xmin, ymin, xmax, ymax, img_w, img_h): # 计算中心点坐标 cx (xmin xmax) / 2.0 cy (ymin ymax) / 2.0 # 计算宽高 w xmax - xmin h ymax - ymin # 全部除以图片尺寸做归一化保留 6 位小数足够 return round(cx / img_w, 6), round(cy / img_h, 6), round(w / img_w, 6), round(h / img_h, 6) # 示例一张 640x480 的图框在 (100,80) 到 (300,280) print(voc_to_yolo(100, 80, 300, 280, 640, 480)) # 输出 (0.3125, 0.375, 0.3125, 0.416667)这段函数的关键参数是 img_w 和 img_h必须传原图真实尺寸不能传网络输入尺寸。有人图省事统一按 640 算遇到非 640 宽的图就全错。round 到 6 位是经验值YOLOv5 内部会再处理但保留太少位数在极端小目标上会有精度损失。类别编号那一位是整数不要写成 0.0 这种浮点虽然部分版本能容错但没必要给自己埋雷。2.3 data.yaml 里三个字段决定训练能不能启动data.yaml 是数据集和训练脚本之间的契约最少要写 path、train、val、nc、names 五项。path 是数据集根目录train 和 val 是相对 path 的图片路径nc 是类别数量names 是类别名列表。nc 和 names 长度必须一致差一个就会在算损失时维度不匹配。# data.yaml 示例智能小车物品识别5 类物品 path: /data/smart_cart_dataset # 数据集根目录绝对路径最稳 train: images/train # 相对 path 的训练图片目录 val: images/val # 相对 path 的验证图片目录 nc: 5 # 类别数量必须和 names 长度一致 names: # 类别名顺序即类别编号 0-4 - bottle - box - can - bag - cuppath 用绝对路径能避免「换个终端就找不到数据」的玄学问题。train 和 val 写相对路径时YOLOv5 会拼在 path 后面所以不要重复写 dataset 前缀。names 里的顺序就是标签文件里类别编号的含义改顺序等于把所有标签的语义打乱必须和标注阶段约定的一致。如果只有训练集没有验证集可以把 val 指向 train但这样验证指标会虚高不建议。3. 从零构建智能购买物品检测数据集采集、标注到划分3.1 采集阶段就要想好类别边界智能购买场景的物品识别类别定义直接决定后面标注和训练的工作量。常见做法是按「抓取策略」而不是按「商品名称」来分类比如所有圆柱形可抓取物归为 can所有软质袋装归为 bag。这样类别数少、类间差异大小车抓取逻辑也好写。如果按具体商品名分几十类标注成本翻几倍模型在小样本类上还容易崩。采集时每个类别至少 200 张光照覆盖顺光、逆光、室内暖光三种角度覆盖正面、侧面、俯视。图片分辨率不用追求 4K长边 1280 足够太大反而拖慢训练。3.2 标注工具选型与导出格式标注工具常见的有 labelImg、CVAT、Labelme 几类。做目标检测矩形框labelImg 最轻量导出直接选 YOLO 格式省掉转换步骤。CVAT 适合多人协作但导出后往往还是 VOC 或 COCO需要自己转。Labelme 默认是多边形做实例分割才用纯检测别选它。标注时框要贴紧目标边缘留白超过 10 像素就会让回归分支学偏。遮挡目标如果露出面积小于 30%建议标为 difficult 或不标硬标会让模型在正常样本上反而犹豫。# 批量检查标签文件是否有越界或空文件 import os def check_labels(label_dir): issues [] for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue fpath os.path.join(label_dir, fname) if os.path.getsize(fpath) 0: issues.append(f{fname}: 空标签文件) continue with open(fpath) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: issues.append(f{fname} 第{i1}行: 字段数不是5) continue vals [float(v) for v in parts[1:]] if any(v 0 or v 1 for v in vals): issues.append(f{fname} 第{i1}行: 归一化值越界) return issues # 用法打印所有问题标签 for msg in check_labels(/data/smart_cart_dataset/labels/train): print(msg)这个检查脚本在标注完成后跑一遍能提前发现空文件、字段缺失、归一化越界三类高频问题。空标签文件在 YOLOv5 里会被当作「无目标」样本少量可以大量会让模型学不到正样本。字段数不是 5 说明标注导出时格式选错了比如导成了 VOC 的 xml 内容。归一化值越界通常是坐标算错或图片尺寸传错必须在训练前修掉。3.3 训练集验证集划分的两种可靠做法划分比例常见 8:2 或 9:1但比比例更重要的是「同场景不跨集」。如果同一段视频抽帧的图片既在训练集又在验证集验证指标会虚高模型实际泛化能力被高估。可靠做法是按采集批次划分第 1 到 8 批进训练第 9 到 10 批进验证。另一种是按时间划分先采的进训练后采的进验证更接近真实部署时遇到新数据的场景。# 按文件名前缀批次划分batch01-08 进 trainbatch09-10 进 val for f in images/all/batch0[1-8]*.jpg; do cp $f images/train/ cp labels/all/$(basename $f .jpg).txt labels/train/ done for f in images/all/batch09*.jpg images/all/batch10*.jpg; do cp $f images/val/ cp labels/all/$(basename $f .jpg).txt labels/val/ done这段 shell 按文件名前缀做批次划分图片和标签同步复制保证同名对应。basename 去掉 .jpg 再拼 .txt 是标签定位的标准写法。如果文件名没有批次前缀可以先重命名再加前缀别用随机划分糊弄随机划分在物品识别这种场景下很容易把同一物品的不同角度分到两边指标好看但上线就露馅。4. 用 YOLOv5 训练智能小车物品识别模型命令、参数与验证4.1 训练命令与关键参数含义YOLOv5 的训练入口是 train.py核心参数有 --data、--weights、--img、--batch、--epochs、--device。--data 指向 data.yaml--weights 用预训练权重能显著加快收敛--img 是网络输入尺寸--batch 受显存限制--epochs 一般 100 到 300。智能小车物品识别类别少、场景相对固定从 yolov5s 预训练权重起步100 epoch 通常够用。# 从预训练权重开始训练输入 640批次 16100 轮 python train.py \ --data /data/smart_cart_dataset/data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0 \ --project runs/train \ --name cart_item_v1--img 640 是 YOLOv5 的默认输入改成 416 能提速但小目标召回下降改成 1280 精度可能升但显存翻倍。--batch 16 在 8G 显存上跑 yolov5s 比较稳报显存不足就降到 8。--device 0 指定第一块 GPUCPU 训练把 0 换成 cpu但速度会慢一个数量级。--name 给这次训练起个可追溯的名字后面看结果和导出权重都靠它定位。4.2 训练过程看哪些指标才算没白跑训练日志里重点看三个box_loss、obj_loss、mAP0.5。box_loss 下降说明框回归在学obj_loss 下降说明目标置信度在学mAP0.5 是综合指标。前 10 个 epoch 指标波动大是正常的30 epoch 后还不降就要查数据和参数。如果 box_loss 降但 mAP 不涨多半是标签框质量差或类别不平衡。如果 obj_loss 一直高检查是否有大量背景图被误标成正样本。# 从 results.csv 里提取每轮 mAP找最佳 epoch import csv best_map, best_epoch 0, 0 with open(runs/train/cart_item_v1/results.csv) as f: reader csv.DictReader(f) for row in reader: # 列名带空格strip 一下 m float(row[ metrics/mAP_0.5].strip()) e int(row[epoch].strip()) if m best_map: best_map, best_epoch m, e print(f最佳 mAP0.5{best_map:.4f} 出现在第 {best_epoch} 轮)results.csv 是 YOLOv5 每轮自动写的训练记录列名前后有空格读取时要 strip。找到最佳 epoch 后可以用 --weights 加载对应轮次的权重做推理不一定用最后一轮因为后面可能过拟合。这个脚本在调参阶段很实用能快速对比不同配置的峰值表现。4.3 推理验证拿小车实拍图跑一遍训练完不能只看验证集指标要拿小车摄像头实拍的、没参与训练的图跑推理看框的位置和类别是否符合预期。用 detect.py 指定权重和图片目录--conf 控制置信度阈值--iou 控制 NMS 的 IoU 阈值。# 用训练好的权重对实拍图做推理 python detect.py \ --weights runs/train/cart_item_v1/weights/best.pt \ --source /data/cart_test_photos \ --img 640 \ --conf 0.4 \ --iou 0.45 \ --save-txt--conf 0.4 意味着置信度低于 0.4 的框不输出智能小车抓取场景宁可漏检也别误抓可以调到 0.5。--iou 0.45 是 NMS 合并重叠框的阈值物品密集摆放时调低到 0.3 能减少框粘连。--save-txt 把检测结果存成 YOLO 格式 txt方便和标注对比算实际精度。实拍图推理翻车最常见的原因是训练集光照和实拍差异大补采对应光照的图重训比调参有效。5. 避坑与排查智能小车物品识别数据集最常见的五个翻车点5.1 训练报「No labels found」但标签明明存在现象是启动训练几秒后报错退出提示找不到标签。原因通常是 images 和 labels 的目录层级不对比如 labels 下多套了一层 train或者标签文件名和图片名大小写不一致。解决方法是打印 data.yaml 里 train 路径下的图片列表再打印对应 labels 路径逐个人工核对同名文件是否存在。Linux 下大小写敏感Item_0001.jpg 和 item_0001.txt 不算同名。5.2 训练正常但 mAP 始终低于 0.3现象是 loss 在降但 mAP 卡在低位。原因多半是类别编号和 names 顺序错位或者标注框大面积偏移。排查方法是抽 10 张训练图用可视化脚本把标签框画到图上肉眼看框是否贴住目标。如果框整体偏移检查归一化时用的图片尺寸是否和实际一致。如果框位置对但类别乱检查 data.yaml 的 names 顺序和标注时的类别映射表。5.3 验证集指标高但实拍推理一塌糊涂现象是验证 mAP 0.9 以上实拍图却大量漏检误检。原因是训练集和验证集同源实拍图分布不同。解决方法是按采集批次划分数据集并补采实拍场景的图进训练集。另一个常见原因是验证集图片分辨率统一实拍图分辨率不同推理时 --img 和实际不匹配把 --img 设成接近实拍长边的值。5.4 显存溢出导致训练中断现象是训练到一半报 CUDA out of memory。原因是 batch 太大或 --img 太高。解决方法是把 --batch 减半或把 --img 从 640 降到 512。YOLOv5 支持 --multi-scale但小显存下开多尺度会加剧波动建议先关掉。如果减 batch 后指标下降明显用 --accumulate 做梯度累积等效大 batch 但显存占用低。5.5 标签文件里混入非目标类别现象是模型把背景里的货架、桌面也框出来。原因是标注时把一些「看起来像目标」的背景物体也标了或者类别定义太宽泛。解决方法是重新审视类别定义把容易混淆的背景物单独设一类或明确不标。YOLOv5 对背景样本有一定容忍度但大量误标正样本会让 obj_loss 居高不下最终影响所有类别的精度。6. 进阶技巧用锚框聚类和类别权重把智能购买识别再提一档默认锚框是基于 COCO 通用数据集聚类的智能小车物品识别的目标尺寸分布往往和 COCO 差很远直接用默认锚框会让回归分支起步就偏。用训练集标签跑一遍 k-means 聚类生成适配自己数据的锚框替换模型配置里的 anchors通常能带来 1 到 3 个点的 mAP 提升。聚类时把图片缩放到网络输入尺寸再算框的宽高k 取 9和 YOLOv5 的三层检测头对应。# 用 k-means 对训练集标签做锚框聚类 import numpy as np from sklearn.cluster import KMeans def load_boxes(label_dir, img_size640): boxes [] for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue with open(os.path.join(label_dir, fname)) as f: for line in f: _, _, _, w, h map(float, line.split()) # 反归一化到像素尺寸 boxes.append([w * img_size, h * img_size]) return np.array(boxes) boxes load_boxes(/data/smart_cart_dataset/labels/train) kmeans KMeans(n_clusters9, random_state0).fit(boxes) anchors kmeans.cluster_centers_ # 按面积排序小框给浅层检测头 anchors anchors[np.argsort(anchors[:, 0] * anchors[:, 1])] print(聚类锚框宽 高) for a in anchors: print(f{a[0]:.1f} {a[1]:.1f})这段代码把标签里的归一化宽高还原成像素尺寸再聚类k9 对应 YOLOv5 的 3 个检测层各 3 个锚框。聚类结果按面积从小到大排序小的给负责小目标的浅层大的给深层。替换锚框后要重新训练不能接着旧权重微调因为检测头的先验变了。如果类别样本数差异大还可以在训练时给稀有类加权YOLOv5 的损失函数里可以通过调整类别权重来缓解但权重别设太猛否则稀有类精度上去了常见类反而崩。我自己踩过最深的坑是锚框聚类时忘了把图片缩放到网络输入尺寸直接用原图尺寸算结果聚类出的锚框偏大小目标召回掉了一截。后来养成习惯任何和尺寸相关的计算先确认当前处于哪个坐标系是原图、网络输入还是特征图。这个习惯比任何调参技巧都值钱。希望帮到你。本文还有配套的精品资源点击获取