资讯动态

行李箱检测数据集:YOLO/VOC双标注格式与训练实践

发布时间:2026/9/12 23:11:21 来源:尧图企业网站定制
简介面向YOLO系列算法训练与目标检测项目落地的行李箱检测数据集专为刚接触深度学习检测的学习者以及需要在自定义场景中快速验证模型效果的开发者准备。压缩包内包含749张已标注图像同时提供两种常见标注格式YOLO格式的文本文件与VOC格式的XML文件两种标签分别存放便于在不同训练框架和标注工具之间切换使用其中YOLO标签以归一化坐标记录目标框训练时无需再做格式转换。压缩包共2000个文件包含501张原始图像、749个文本标注、749个XML标注另附一个数据集配置文件data.yaml整体约60.15MB体量适中并且已经划分好训练集和验证集可在YOLOv5、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLO11等主流版本中直接训练和测试。已有240人学习使用既能用于行李箱目标检测的入门实操也可作为算法选型对比时的标准数据集。1. 行李箱检测的 749 张图像比想象中更能说明问题机场行李传送带、高铁进站口这类固定机位场景里行李箱检测的核心门槛不在模型结构选型而在于标注数据的质量与格式是否统一。749 张带标签的行李箱图像听起来数量不大但如果标注框一致性好、场景分布集中配合 YOLO 系列在 COCO 上的预训练权重做迁移学习训练结果在固定视角下的可用程度往往接近数千张数据集的水平。这份目标检测数据集同时保留了 YOLO 归一化 txt 和 VOC 像素坐标 xml 两种标注解压后可以直接喂给 YOLOv5、YOLOv8、YOLOv9、YOLOv10 或 YOLO11 训练。适合正在整理数据集、验证检测流程或者准备用少量自有数据做专用检测器的工程师。2. 数据集目录与 YOLO/VOC 双标注格式的映射关系2.1 目录结构拆解与文件对应解压 zip 之后先不要急着开训目录结构直接决定后续脚本怎么写。常见的目标检测数据集会按 images 和 labels 分两个根目录这份数据集的特殊之处在于标签同时存在两份一份是 YOLO 训练直接读取的 txt另一份是 LabelImg 等工具链偏好的 VOC xml。两个文件夹里的标注内容完全一致但坐标表示方式不同这一点在后面章节会展开。luggage_dataset/ ├── images/ │ ├── train/ │ │ ├── img_0420_620.jpg │ │ └── ... │ └── val/ ├── labels/ # YOLO 格式 txt ├── xml/ # VOC 格式 xml └── data.yamltrain、val 的划分直接体现在 images 的子目录上labels 里的 txt 和 xml 里的 xml 共用同一套文件名前缀。清洗数据时首先要做的就是拿脚本把三个目录的文件名做一次集合比对确保没有缺标签的孤儿图也没有对应不上图片的多余标签。import os img_dir images/train txt_dir labels xml_dir xml # 收集文件名前缀便于三方比对 img_names {f.split(.)[0] for f in os.listdir(img_dir)} txt_names {f.split(.)[0] for f in os.listdir(txt_dir) if f.endswith(.txt)} xml_names {f.split(.)[0] for f in os.listdir(xml_dir) if f.endswith(.xml)} print(缺txt:, img_names - txt_names) print(缺xml:, img_names - xml_names) print(无图:, txt_names - img_names)这段脚本分别收集三个目录下的文件名前缀集合做差集后可以一次看出哪些图像缺 txt、哪些缺 xml、哪些标签没有对应原图。实际项目里我会先跑一遍再做训练因为缺失标签的图像会被训练程序当作纯背景参与统计行李箱数据集一共才 749 张图混进去十几张无标签样本正样本比例就会被明显稀释收敛后漏检率会变高。提示标注框的规范性比数量更重要如果 txt 与 xml 对应不上优先回到标注工具里重新导出而不是用脚本盲目补文件。2.2 归一化坐标与像素坐标的换算YOLO 格式的每一行标注都是 class x_center y_center width height而且四个坐标值全部归一化到 0 到 1 之间。很多人在拿到数据集时会直接拿 xml 里的像素数值去和 txt 对应结果发现对不上其实只是表示方式不同。以 img_0420_652.jpg 为例txt 里读出来可能长这样0 0.5123 0.4817 0.3641 0.6946第一个 0 是类别索引后面依次是中心点 x、中心点 y、框宽、框高数值分别是相对于图像宽度和高度的比例。验证标注有没有错位最快的办法是把它还原成像素坐标并画框。import cv2 img cv2.imread(images/train/img_0420_620.jpg) h, w img.shape[:2] with open(labels/img_0420_620.txt) as f: cls, cx, cy, bw, bh map(float, f.readline().split()) # 把归一化坐标还原成像素坐标 x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imwrite(check.jpg, img)这段代码先把类别和四个归一化值读进来再换算回像素坐标x1、y1 是框的左上角x2、y2 是右下角。可视化检查时重点看两处框是否紧贴行李箱主体以及拉杆、轮子这些部位是否被包进框内。如果标注者习惯把拉杆也纳入外轮廓NMS 阶段可能会把拉杆区域当成独立候选框对定位精度造成干扰。2.3 VOC xml 与 YOLO txt 的转换思路xml 一侧保存的是像素坐标xmin、ymin 是左上角xmax、ymax 是右下角。目前主流开源框架里YOLO 系直接消费 txtMMDetection 等偏研究向的框架则更习惯 VOC 的 xml。这套数据集两种都给好处是省去了在数据整理和模型训练之间反复做格式互转的时间。唯一要留意的是类别映射表必须和 data.yaml 里的 names 保持严格一致索引一旦错位模型学到的类别含义就会整个偏移。下面的函数展示了 xml 转 yolo txt 的标准做法import xml.etree.ElementTree as ET def xml_to_yolo(xml_path, out_txt, names_map): 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 names_map: continue bbox obj.find(bndbox) x1 float(bbox.find(xmin).text) y1 float(bbox.find(ymin).text) x2 float(bbox.find(xmax).text) y2 float(bbox.find(ymax).text) # 像素坐标转归一化坐标 cx (x1 x2) / 2 / w cy (y1 y2) / 2 / h bw (x2 - x1) / w bh (y2 - y1) / h lines.append(f{names_map[name]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) with open(out_txt, w) as f: f.write(\n.join(lines))转换函数里用 names_map 把字符串类别名映射成整数索引同时过滤掉不在映射表里的类别。整个转换过程只改变坐标的表示形式不修改像素内容所以不会引入额外标注误差。验证转换结果时把 xml 的 bbox 和 txt 还原出来的 bbox 逐点比对如果偏移超过 2 个像素优先检查 size 节点里的图像宽高是否被改过。3. data.yaml 配置与 YOLOv8 训练流程3.1 data.yaml 的路径与类别字段YOLO 从 v5 开始用 data.yaml 统一描述数据集YOLOv8、YOLO11 沿用了这一套约定。压缩包自带的 data.yaml 已经按官方格式写好了路径和类别名直接打开看是这样# 数据集根目录 path: ./luggage_dataset train: images/train val: images/val names: 0: luggagepath 是数据集根目录train 和 val 指向 images 下的子目录names 定义了类别索引和名称。这份数据集只有一个 luggage 类别逻辑上很简单但路径解析依赖当前工作目录。我在命令行里通常把 path 改成绝对路径避免在项目根目录和数据集目录之间切换时反复踩相对路径的坑。改绝对路径最直接的好处是无论从项目根目录启动还是从数据集目录启动训练程序都能找到图片。另一个容易被忽略的字段是 nc虽然 YOLOv8 能从 names 的长度自动推算 nc但 YOLOv5 的某些版本、以及一些二次开发的训练脚本会显式读取 nc所以我在写 yaml 时会补上nc: 1。这样做的好处是换框架或者换工具链时配置文件可以少改一处。3.2 YOLOv8 训练命令拆分数据集就绪后训练可以压缩成一行命令但每个参数最好都理解它的边界条件尤其是 749 张图像的规模下参数不合适会直接影响收敛速度。# 使用 yolov8s 预训练权重做迁移学习 yolo detect train \ modelyolov8s.pt \ datadata.yaml \ imgsz640 \ batch16 \ epochs100 \ patience20 \ device0model 指定预训练权重路径。这里选 yolov8s.pt 而不是从零初始化是因为 COCO 预训练得到的特征提取器已经具备通用物体表征能力行李箱这种外观特征可以在其基础上快速微调。imgsz 控制输入图像缩放尺寸虽然行李箱在原图里的占比不小但 640 已经足够覆盖绝大多数监控画面直接提到 1280 会成倍增加显存占用和推理耗时换来的是少量小目标精度的提升性价比不高。patience 是早停机制验证集 mAP 连续 20 个 epoch 不提升就终止训练小数据集上这个值设 10 到 20 比较合理。参数的选择可以参考下面这张表这是我对小规模单类数据集的一版默认配置参数取值作用小样本场景建议modelyolov8s.pt预训练权重优先 s、mx 很容易过拟合imgsz640输入图像尺寸目标占比大时保持 640batch16每批样本数显存不足降到 8梯度不稳定降到 4epochs100最大训练轮数100 配合早停足够patience20早停间隔建议 1020batch 从 16 降到 8 时BN 层的统计量会更不稳定行李框位置回归的抖动会变大但显存受限时也只能接受。另一个做法是保留 batch 16、把 imgsz 从 640 降到 512这样单张图占用更小虽然损失一点空间分辨率但受背景干扰也少一些。3.3 训练日志的关键指标与断点续训训练过程中控制台会持续输出 box_loss、cls_loss、mAP 等指标。单类数据集上 cls_loss 的收敛压力很小主要观察 box_loss。如果 box_loss 先降后升说明模型开始对训练集中的个别角度死记硬背已经到了过拟合临界点此时即便 mAP 还在缓慢上升也应该停止。# 从断点继续训练保留优化器状态 yolo detect train \ modelruns/detect/train/weights/last.pt \ datadata.yaml \ imgsz640 \ batch16 \ epochs150 \ resumeTrueresumeTrue 会从 last.pt 恢复权重、优化器状态和当前 epoch不需要重新加载数据集做初始化 shuffle。这个场景在反复调参时很实用比如第一次只跑了 60 个 epoch 被早停中断觉得还能继续收敛就不必从头再来。4. 小样本行李箱检测的过拟合控制与数据增强调参4.1 单类检测的 loss 特点与评估陷阱这份数据集只有 luggage 一个类别。单类目标检测与多类检测的显著区别在于分类分支几乎没有区分难度模型大部分梯度来自回归分支也就是框的位置和大小。因此训练曲线里 box_loss 才是最重要的风向标cls_loss 降到低位后基本不再变化不必为它的轻微波动反复试参数。单类模型还容易出现验证集 mAP 虚高的情况。因为类别少、背景相对单一模型只需要学会区分有行李箱和没有行李箱并且训练集和验证集如果来自同一视角刷出 0.95 以上的 mAP50 并不难但这不代表对遮挡、逆光、异形箱体有真实鲁棒性。评估时我会把验证集里被遮挡超过三分之一的样本单独拎出来看 recall这个指标比整体 mAP 更能反映模型在真实场景中的边界。做 yolo 算法改进的实验时如果只在 mAP50 上看到提升而 recall 没动那多半是提升了分类分支的置信度分布而不是真正改善了检测能力。4.2 数据增强参数对 749 张图像的作用边界YOLOv8 的超参数可以在训练命令里直接覆盖不需要改 hyp.yaml。对这批图像我习惯按下面的方式调整增强强度# 小样本场景下调低 mosaic保留适度色彩扰动 yolo detect train \ modelyolov8s.pt \ datadata.yaml \ imgsz640 \ batch16 \ epochs100 \ patience20 \ hsv_h0.015 \ hsv_s0.5 \ hsv_v0.4 \ flipud0.0 \ fliplr0.5 \ scale0.4 \ mosaic0.5hsv_h、hsv_s、hsv_v 分别控制色调、饱和度、亮度的随机扰动幅度。行李箱颜色跨度很大从纯黑到亮黄都存在适度提高色彩扰动有助于模型对颜色变化更鲁棒。flipud 设为 0 是因为监控视角下行李箱不会倒置强制加入垂直翻转等于让模型学习一个现实里不存在的分布会得不偿失。mosaic 从默认的 1.0 降到 0.5是因为数据集只有 749 张图拼接增强比例太高时每张图里的行李箱可能被切得只剩局部回归分支会被大量残破目标干扰。如果训练过程里验证集 loss 在中期开始反弹除了调增强还要检查 fliplr 带来的双重标注问题。水平翻转对行李箱这类左右不对称目标比如单侧拉杆会造成框的语义变化虽然是自动处理的但遇到拉杆位于右侧的样本翻转到左侧后模型会看到一个训练分布里少见的形态这时可以考虑把 fliplr 也降到 0.3 甚至 0。4.3 YOLOv5 锚框自适应与宽高比分布如果选择用 YOLOv5 训练这份数据集锚框的设置就不能忽略。YOLOv5 默认使用 COCO 上聚类出的锚框对行李箱这种宽高比跨度大的目标默认锚框与真实框的 IoU 匹配率可能不足。官方脚本提供了自动计算锚框的入口。# 重新计算适合当前数据集的锚框 python utils/autoanchor.py --data data.yaml --img 640autoanchor 脚本会基于训练集的真实标注做 k-means 聚类并输出最佳召回率。如果输出里某个锚框的 best recall 低于 0.98说明当前锚框设置对该类目标不够友好。之后训练时加上 --noautoanchor 参数避免训练进程再次覆盖手动配置的锚框。# 跳过训练启动时的自动锚框计算 python train.py \ --data data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --noautoanchor对行李箱检测宽高比分布通常集中在 0.6 到 1.6 之间但侧面视角会产生明显的窄长框。聚类结果里如果出现一个负责窄长目标的锚点不要为了追求分布均匀而手动删掉那样的做法会让侧面行李箱的召回明显下降。理解锚框与目标形状的匹配关系比盲改聚类数量更有意义。5. mAP 曲线读法与漏检样本排查5.1 从 runs/detect 目录还原训练结果训练结束后权重和指标都在 runs/detect/train 下。用 val 命令在验证集上跑一遍输出 mAP50、mAP50-95 以及 PR 曲线图。# 使用 best.pt 在验证集上评估 yolo detect val \ modelruns/detect/train/weights/best.pt \ datadata.yaml \ imgsz640 \ conf0.25 \ iou0.45conf 是置信度阈值iou 是 NMS 的 IoU 阈值。行李箱检测里我一般把 conf 保持在 0.25不轻易调到 0.4 以上因为行李箱视觉特征相对稳定低置信度框很多是真实的调高阈值虽然能提升 precision但漏检率上升更快。iou 保持 0.45 即可这组参数配合单类场景能最大限度保留相邻视角下的重叠框。5.2 漏检样本的批量复盘脚本排查漏检不能只看单张图。下面这段脚本会把验证集里所有置信度低于 0.3 的预测结果汇总到一个 failure 文件夹方便快速定位模型失效的场景。import glob import cv2 from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) imgs sorted(glob.glob(images/val/*.jpg)) for impath in imgs: results model.predict(impath, conf0.3, verboseFalse) boxes results[0].boxes if boxes is None or len(boxes) 1: # 完全没有检测框原图保存 img cv2.imread(impath) cv2.imwrite(ffailure/{impath.split(/)[-1]}, img) continue for b in boxes: if b.conf[0] 0.3: img cv2.imread(impath) x1, y1, x2, y2 map(int, b.xyxy[0].tolist()) cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 0), 2) cv2.imwrite(ffailure/{impath.split(/)[-1]}, img)脚本逻辑是对每张验证图执行一次推理完全没框的图原样保存有框但置信度低于 0.3 的用蓝色框标记后保存。跑完后如果 failure 目录集中在逆光、大面积遮挡或行李箱与墙壁颜色接近的样本上那说明模型学到的特征是颜色加轮廓的组合而不是结构化的箱体特征这时候调整要往数据增强的灰度扰动和对比度方向走。最后把 last.pt 和 best.pt 的验证指标做一个对比。如果两者 mAP 差距在 1 个百分点以内说明训练后期没有显著过拟合best 选取合理如果 last 比 best 低超过 3 个百分点说明后期过拟合明显可以回退到训练中期的权重并用更大的增强参数重新跑一轮这个回归方向比直接加数据更可控。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价