简介这是一份面向智能小车物品识别与智能购买场景的单类别目标检测数据集按YOLOV5标准目录结构整理图片与标注文件一一对应可直接作为训练输入无需额外转换。数据集中唯一类别为purchase所有图片分辨率统一为416×416像素的RGB格式训练集包含710张图片及711个标签文件验证集包含177张图片及177个标签文件并附带类别字典文件便于后续类别映射。除JPG图片与文本标注外资源内还提供1个Python可视化脚本和1张示例图运行脚本即可随机读取图片并绘制边界框结果自动保存到当前目录无需修改任何参数。整个资源共1777个文件JPG图片887张、文本标注888个压缩包约26.48MB体量轻、目录清晰适合学习目标检测流程或快速搭建智能购买识别实验的开发者直接使用。目前已有157人学习下载性价比高开箱即用。1. 目标检测数据集按YOLOV5目录格式交付为什么这是智能小车识别项目的第一道坎目标检测数据集以YOLOV5目录格式整理好意味着你拿到的不是一堆散图而是一套开箱即训的标准结构。做过智能小车物品识别的人都知道训练一个能用的模型最耗时间的往往不是调参而是数据标注格式对不对、train和val有没有交叉、标签和图片能不能对上——这些数据侧的坑比模型结构更隐蔽报错也更难懂。这份资源适合两类人一类是带智能小车做竞赛或课设想在最短时间内把物品识别链路跑通另一类是刚接触YOLOV5想找一份规范的数据集当标准答案对照自己手头数据的组织方式。下面从目录约定、标签计算、转换脚本和训练前检查四条线展开把最容易翻车的几个位置一次说清。2. 目录结构与标签文件读懂YOLOV5数据集的三个关键约定2.1 目录树images与labels、train与val的对应关系拿到这份数据集先不要急着开train.py花两分钟把目录结构过一遍。标准的YOLOV5目录树长这样dataset/ ├── images/ │ ├── train/ │ │ ├── 000001.jpg │ │ └── ... │ └── val/ │ ├── 000101.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── 000001.txt │ │ └── ... │ └── val/ │ ├── 000101.txt │ └── ... └── data.yaml这个结构里有三条对应关系必须成立。第一images和labels两个目录必须同在一层YOLOV5默认在data.yaml指定路径的基础上把image目录的上一级当根目录再拼labels目录如果你的data.yaml里train写的是./images/train那labels文件就必须在./labels/train名字必须和图片同名。第二train和val是两个独立的数据集不能有同一张图既进train又进val。我见过不少人在手动拷贝时图省事直接把所有图片丢进trainval从train里随机抽——这种交叉会导致mAP虚高训练时模型其实见过验证集图片部署到小车上实测才发现指标完全对不上。判断方法也简单对比两个目录的文件名集合取交集非空就有问题。第三图片和标签文件必须一一对应。每张训练图片必须有一个同名txt哪怕这张图里没有任何目标txt也要存在并且为空。有些标注工具导出的目录里丢弃了无目标图片的标签训练时YOLOV5会报找不到label文件或者静默跳过让你误以为数据质量很好实际有效样本已经悄悄缩水。另外注意图片后缀的坑。标注文件靠文件名配对不靠后缀所以000001.jpg和000001.png如果同时存在会互相覆盖或产生歧义。整理数据集时统一把所有图片转成同一种后缀避免同名不同格式的文件混在同一个目录里。这套目录约定不只YOLOV5在用YOLOV8等后续版本也沿用同样的标签规范学会一次后面换框架不换思路。2.2 标签txtclass、归一化中心点、宽高的换算逻辑labels目录下的每个txt是纯文本每一行描述一个目标。和VOC的xml存绝对像素坐标不同YOLO格式存的是归一化坐标一行五个浮点数0 0.485 0.321 0.184 0.275 1 0.712 0.668 0.093 0.149第一列是类别id从0开始顺序严格对应data.yaml里names列表的下标后面四列依次是目标中心点的x、y坐标和目标宽w、高h全部除以图片宽高做了归一化取值范围在0到1之间。归一化这个设计是YOLO系格式能被广泛复用的核心原因同一份标注放在640×640的训练输入和放在1280×1280的推理输入里都不需要修改比例天然一致。你只需要在做转换时记住换算公式x_center (xmin xmax) / 2 / 图片宽度y_center同理w (xmax - xmin) / 图片宽度h (ymax - ymin) / 图片高度。很多标注工具直接勾选YOLO格式导出就能得到正确结果但如果你拿到的原始数据是xml或json转换脚本里最容易错的就是忘了除以图片宽高导致标签框整体偏移。类别id从0开始这一点和很多人的直觉相反。你也许习惯从1开始编号但在YOLO体系里0就是第一类是合法的。如果某份数据里出现负的id或小数id说明转换脚本写错了或标注工具配置有误这类标签优先排查。提示看txt里是否有大于1或小于0的值是判断标签是否出界最快的方式。后面第5章会给专门的排查方法。2.3 data.yamlnc、names和路径三个字段错一个都白搭data.yaml是整个训练入口的配置文件YOLOV5训练时通过--data参数指向它。一个完整可用的data.yaml长这样train: ./images/train val: ./images/val nc: 4 names: [bottle, can, box, ball]这里的坑集中在三个字段。一是nc必须和names的长度一致且等于所有txt中出现的最大类别id加1。比如txt里出现了类别3nc至少要填4否则训练过程会在compute_loss里报index越界的错。二是names的下标就是txt里class id的映射names列表写错顺序模型学到的东西就张冠李戴。三是train和val路径YOLOV5相对路径是相对于当前工作目录解析的如果你在项目根目录外执行train.py./images/train就可能找不到我一般建议在yaml里写绝对路径或者在项目根目录下执行训练命令两种方式任选其一不要混用。字段含义常见错误train训练图片目录写成图片文件而非目录val验证图片目录与train目录交叉nc类别总数与names长度不一致names类别名列表顺序和txt里的class id不对应这三个约定是整个数据集的地基第3章的转换脚本、第5章的排查思路都建立在它们之上。如果你手里的数据是VOC格式或者自己用别的工具标了一批图接着看第3章的转换方法。3. 从零整理自己的数据集标注工具选型与VOC转YOLO实战脚本3.1 标注工具怎么选LabelImg、X-AnyLabeling、Roboflow三选一大部分数据集不会正好是YOLO格式到手之后先确认原始格式再决定用什么工具转。常见的三种情况已经有xml标注文件需要转YOLO手里只有图片需要从头标注标注量很大想用辅助标注。对应工具我都用过按场景选就行。LabelImg是老牌工具轻量、纯本地运行标注界面简单直接输出可以是VOC的xml也能切到YOLO模式直接存txt。缺点是框多了以后界面有点卡且单张图片操作效率一般。X-AnyLabeling是目前我常用的替代品它带模型辅助标注框一个目标后自动跟踪类似物体对几百上千张同场景图片效率提升明显。Roboflow是在线方案标注、增强、格式导出一条龙还能自动处理数据集划分但图片要上传到云端如果涉及竞赛规则或数据隐私慎用。对于智能小车这类物体相对固定、拍摄背景单一的数据集我的建议是量小于500张用LabelImg或X-AnyLabeling本地标量大或需要快速迭代用Roboflow但本地始终留一份原始图片备份。标注工具只能输出标注不能替代你检查标签质量标完必须随机抽几十张图人工过一遍。3.2 VOC转YOLO一个能直接用的xml_to_yolo.py如果你手上是VOC的xml标注我在项目里一般用一个固定脚本转换几十行搞定import xml.etree.ElementTree as ET import os def xml_to_yolo(xml_path, out_dir, classes): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in classes: continue box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{classes.index(name)} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}) if lines: txt_name os.path.splitext(os.path.basename(xml_path))[0] .txt with open(os.path.join(out_dir, txt_name), w) as f: f.write(\n.join(lines)) # 用法 classes [bottle, can, box, ball] os.makedirs(labels_train, exist_okTrue) for xml in os.listdir(xmls): if xml.endswith(.xml): xml_to_yolo(os.path.join(xmls, xml), labels_train, classes)这个脚本的核心逻辑是把像素坐标转成归一化坐标。注意几个关键点图片宽高取自xml里的size节点而不是从图片文件读取因为标注时的图片分辨率可能和你现在手里的不完全一致以标注时记录的为准转换后的坐标保留6位小数精度足够训练使用不用纠结更多位数如果xml里出现了classes列表之外的类别脚本直接跳过避免把脏数据带进训练集。转换完之后强烈建议随机打开几张图把txt画上去对比原标注这一步能拦截90%的坐标错误。3.3 划分train/val并生成YOLOV5需要的路径索引文件标注整理好之后接下来要划分训练集和验证集。经典的划分比例是8:2或9:1小车数据集一般量不大我习惯用随机抽样的方式固定随机种子保证多次转换结果一致import os import random from shutil import copy2 src_img images_all src_lbl labels_all train_img dataset/images/train train_lbl dataset/labels/train val_img dataset/images/val val_lbl dataset/labels/val for d in [train_img, train_lbl, val_img, val_lbl]: os.makedirs(d, exist_okTrue) random.seed(42) imgs [f for f in os.listdir(src_img) if f.endswith(.jpg)] random.shuffle(imgs) split int(len(imgs) * 0.8) for img in imgs[:split]: base os.path.splitext(img)[0] copy2(os.path.join(src_img, img), train_img) copy2(os.path.join(src_lbl, base .txt), train_lbl) for img in imgs[split:]: base os.path.splitext(img)[0] copy2(os.path.join(src_img, img), val_img) copy2(os.path.join(src_lbl, base .txt), val_lbl) print(train:, len(imgs[:split]), val:, len(imgs[split:]))这里用shutil.copy2保留文件时间戳等信息方便后面排查随机种子固定为42改比例时不会影响顺序可复现性。注意划分的是图片文件名集合标签跟随图片同名移动绝对不能分别shuffle否则train和val的配对关系就乱了。划分完成后在数据集的根目录执行find . -name *.txt | wc -l对比一下labels总数是否等于images总数数值对不上就先别训练。注意YOLOV5新版通过data.yaml自动扫描目录不需要额外的train.txt和val.txt索引文件。如果你在旧版代码或网上教程里见到txt索引那是v3之前的写法不要混用。4. 智能小车场景下的数据坑光照、视角和类别不均衡4.1 小车摄像头视角的特殊性低机位、运动模糊和反光普通目标检测数据集大多是手持相机、俯视或平视拍摄而智能小车的摄像头高度通常只有十厘米上下视角更低、离目标更近这两种数据训练的模型部署时性能差距明显。低机位拍摄意味着目标的透视形变更强同样的瓶子俯视图看到的是瓶盖圆面小车平视看到的是瓶身侧面和标签纹理运动模糊就更直接小车跑起来摄像头抖动画面比静态拍摄糊一截开灯巡检场景还会遇到地面反光目标边缘在反光区域直接消失。所以整理或扩充数据集时我的原则是以实际小车摄像头拍摄的画面为主网上找的图片最多做补充不能反过来。拍的时候尽量复现真实工况小车以巡线速度跑拍一段视频然后抽帧比静态摆拍更接近推理时的输入分布。实拍画面整理时我一般直接抽帧而不是一张张拍照用ffmpeg一条命令就能从视频里按固定间隔取帧ffmpeg -i run_video.mp4 -vf fps10 frame_%04d.jpgfps10表示每秒抽10帧。帧率太高会造成大量相似图片训练时冗余样本会放大某一段轨迹的场景特征导致模型对其他位置的目标泛化变差。抽完帧再按时间间隔二次采样尽量覆盖不同位置、不同角度。如果发现验证集mAP不低但小车行驶中漏检优先怀疑训练图和实拍图存在视角、清晰度上的分布差异。4.2 类别不均衡少数类只占5%时怎么处理物品识别里类别不均衡是很常见的情况比如易拉罐出现几百次乒乓球只有几十次。模型训练时损失被多数类主导少数类学不到位最终表现为多数类recall很高少数类几乎不报或者全部误判成多数类。在小车抓取、分拣这类任务里漏检一个少数类目标可能直接影响执行逻辑比误检更致命。处理方式按优先级排序。第一步先统计类别分布把所有txt读一遍统计每一行的class id出现次数第二步对少数类做简单过采样把包含少数类的整张图复制几份放进训练集注意复制的是图片加对应的标注txt不是只复制txt第三步如果还不行可以针对少数类做目标级复制粘贴增强把小目标的标注区域扣出来贴到背景图上同时生成对应标注。多数类不做处理保持原始数量即可。过采样之后train和val之间仍然不能有重叠验证集保持原始分布否则mAP会虚高。4.3 数据增强参数mosaic、mixup与hsv的合理边界YOLOV5默认开启的增强里mosaic和mixup对小车场景影响最大。mosaic把四张图拼成一张训练能显著提升小目标检测能力但训练到后期mosaic会拖慢收敛、让loss波动变大常见的习惯是训练超过100个epoch时在最后30个epoch把mosaic关闭让模型在接近真实分布的图上精调。mixup把两张图半透明叠加对遮挡鲁棒性有帮助但叠加后的画面和真实场景差异较大不要开太强。hsv增强里我一般保留默认的hsv_h0.015、hsv_s0.7、hsv_v0.4这个组合已经覆盖了光照变化。不过要注意如果小车识别的是颜色敏感物体比如颜色区分是否成熟的果实hsv_h建议降到0.01以内否则色相抖动会让模型混淆不同颜色类别的物体。fliplr水平翻转增强默认开着但对于有方向语义的目标要关掉比如瓶身上的文字标签、巡线赛里的方向箭头翻转之后语义就反了。参数默认值小车场景建议说明mosaic1.0前中期1.0最后30个epoch关小目标增益大后期拖收敛mixup0.00~0.2遮挡场景可开别超过0.5fliplr0.5有方向性目标时设0文字、箭头翻转后语义错误hsv_h0.015颜色敏感时降至0.01色相抖动太大导致颜色混淆增强参数的调整要在训练配置里改不是在数据集里改。把增强写进图片本身会让验证集失真正确做法是在train.py对应的hyp.yaml里只调训练侧增强验证集始终用原始未增强的图。5. 训练前必查的五个坑YOLOV5数据集常见问题与排查5.1 标签越界训练时报越界错误或标签画错位置现象训练日志里出现类似IndexError: index 12 is out of bounds for axis 0 with size 8或者debug里看到标签框超出图片边界。原因txt里的归一化坐标为负或大于1通常来自转换脚本没除以图片宽高或标注框本身超出图片像素范围。YOLOV5在读取标签时会做边缘裁剪超界不致命但标注框位置已经失真模型学到的是偏了心的目标。解决写个脚本扫一遍全部txt把任何坐标小于-0.01或大于1.01的标签打出来再回原图核实。修正的办法不是手改坐标而是回到标注源或转换脚本重跑。我一般在dataloader里临时加一段打印逻辑把超界的标注打出来先定位是哪张图再修转换脚本。5.2 class not in dataset警告某个类别id在数据集里不存在现象训练开始阶段日志显示WARNING: class 3 not in dataset但进程不中断训练照常跑。原因data.yaml里nc配了5names长度也写了5但txt里实际只出现了0到3的类别类别4在整个数据集一张都没有或者names顺序和你标注时用的class id对不上某个id对应的名称为空。解决统计全部txt的类别出现频率把没有样本的类别从names里移除nc改为实际出现数。这个警告的危害是静默的它不报错但模型最后一层的输出维度包含空类别虽然不影响收敛会浪费一部分计算量且拉低mAP的统计口径。5.3 图片读取异常EXIF旋转和RGBA通道现象训练时个别图片无法加载或者模型学出来的目标角度始终偏转90度。原因手机拍的JPG带EXIF方向信息有的库读出来是正的有的库不解析EXIF直接按像素原始方向显示导致标注和实际画面旋转不一致另一种情况是图片是RGBA四通道YOLOV5默认按三通道处理读图时报通道数不符。解决训练前统一转格式用脚本把所有图片转成RGB的JPG并去掉EXIF方向PNG带透明通道的合成一张纯色背景再存JPG。这个预处理直接做一次比每次训练都排查来得省事。5.4 mAP很高但小车实测漏检数据集和部署环境的分布差现象验证集mAP 0.92模型部署到小车上实拍画面里目标明明很清楚就是识别不到偶尔框还乱跳。原因这是数据集问题里最隐蔽的一类。训练图片是静态高清部署画面是运动模糊加低照度训练输入resize到640部署输入可能被工程代码resize到416或320另外验证集里如果包含和训练集相似的图高mAP本身就可疑。解决训练时就把输入尺寸定成和部署一致不要训练用640、部署用320。然后把小车实拍的视频抽帧单独做一个小而真的评测集不用标注很多三五十张就够跑一遍val脚本看实际准确率。这一步通常能暴露差距比盯训练mAP有用得多。5.5 data.yaml和实际标注对不上names顺序错了现象训练正常推理时框和类别对不上比如明明标的是盒子模型一直输出瓶子。原因标注工具导出时class id从0开始顺序编号但你参考的文档或示例里names顺序不同比如别人数据集的names是[box,bottle]你直接套用类别映射就整体错位。解决这类问题有一个笨但有效的办法训练完看val_batch预测图上面会印出预测类别名拿实际图片对照立刻能发现错位。改names顺序比重新训练代价小改完再训一遍。从那以后我每次开局先输出一遍names和id对照表再往模型里塞数据。6. 半小时跑通快速基线用训练日志验证数据集本身的质量6.1 用默认超参跑30个epoch当体检数据集整理完不要急着调优先用一套完全默认的超参做一次快速基线目的是体检数据集不是追求精度。命令长这样python train.py --data dataset/data.yaml --weights yolov5s.pt --img 640 --epochs 30 --batch 16 --project baseline_check参数说明weights用yolov5s.pt体积小、训练快只验证数据链路img固定640和部署尺寸保持一致后面部署到树莓派或者其他边缘设备时再根据实际算力换更小的输入尺寸epochs设30个一般跑到第10到15个epoch就能看出loss是否下降batch大小根据显存调整6G显存用1612G以上可以加到32。关键看两个指标loss曲线是否平滑下降以及第1个epoch的P、R、mAP是否从接近0的水平开始上升。如果loss从一开始就是nan先查标签数据和图片数据不需要查模型配置。6.2 盯紧三个日志文件train_batch、val_batch、results.csv训练输出目录里除了终端日志最值得看的是三个文件。第一个是results.csv直接打开看epoch、box_loss、cls_loss、mAP这几列的变化趋势loss锯齿状上下是正常的但必须整体下行第二个是train_batch0.jpg这是第一张训练batch图图上画了标注框一眼就能看出标签和实际目标是否对齐第三个是val_batch0.jpg展示验证集的预测结果框是否准、类别名对不对都在上面。我的习惯是训练跑完先看train_batch0.jpg再开results.csv最后才看mAP数字。如果图片上标签框明显偏移说明转换脚本有坐标错误这时的mAP数字再好看也不能信。这次快速基线跑完再根据第4章的增强策略和第5章的排查清单调整数据之后才进入正式训练。从那以后我每次整理数据集都强制走一遍这个流程转格式、划分布、画框检查、跑30个epoch基线、看三份日志这套流程看着笨但真能拦住大部分数据侧的隐蔽问题希望帮到你。本文还有配套的精品资源点击获取