
简介本资源为面向YOLO系列目标检测算法的烟盒识别数据集适合从事目标检测学习、模型训练与验证的开发者及研究人员使用可解决烟盒类目标识别任务中数据准备繁琐的问题。压缩包共2000个文件约192.79MB包含1545个xml标注文件与455个txt标注文件分别对应VOC格式与YOLO格式便于不同框架直接读取。数据集已按训练与验证需求划分完毕并附带data.yaml配置文件可无缝适配yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流算法。YOLO格式标注采用类别索引与归一化中心点、宽高比例符合标准训练输入要求。目前已有176人学习下载读者可直接获得完整标注数据与配置省去采集与标注成本快速投入模型训练、对比实验与效果验证适合作为课程设计、科研实验或工程原型的训练基础。1. 烟盒检测数据集上手1934 张图带标签为什么它值得先跑一遍拿到一个目标检测数据集最怕的不是数据少而是格式乱、划分乱、标签对不上。这份烟盒数据集在这几点上做得比较干净1934 张图像全部带标签已经划分好训练集和验证集同时提供 YOLO 格式的 txt 和 VOC 格式的 xml 两套标注还附带data.yaml配置文件。也就是说你不需要自己写脚本去切分数据、转换坐标解压完改一下路径就能直接开训。它适合谁如果你正在做 yolo系列算法目标检测数据集的练手项目或者想验证 yolov8目标识别 在自己环境里的完整链路这份数据集的体量刚好——1934 张不算大单卡几十分钟能跑完一轮但类别单一、目标明确足够暴露数据加载、标签解析、评估指标这些环节的问题。烟盒这个目标本身也有意思长方体、有反光、摆放角度多变拿来观察模型对小目标和遮挡的响应挺直观。需要先明确一点数据集只解决“数据从哪来”不解决“模型怎么调”。下面按“先看懂标签格式再跑通训练最后避开几个高频坑”的顺序拆开讲每一步都落到能直接复制的命令和参数上。2. 标签格式与目录结构先搞懂 YOLO txt 和 VOC xml 的对应关系2.1 两种标注格式的字段含义YOLO 格式每个 txt 文件对应一张图每行一个目标字段是class x_center y_center width height。这里最容易翻车的是坐标归一化x_center和y_center是框中心点相对整张图宽高的比例width和height也是比例值全部落在 0 到 1 之间。很多人第一次拿到 txt 看到0.523 0.137 0.088 0.203这种数误以为是像素坐标直接乘图像尺寸就错了——它已经是比例要还原像素得再乘宽高。VOC 格式的 xml 则是绝对像素坐标xmin/ymin/xmax/ymax直接对应图像上的位置。两套标签放在不同文件夹好处是你用 YOLO 系列就直接读 txt想换到别的框架或者做格式对比就用 xml。判断一份 YOLO 标签是否合法我一般先跑一个快速校验所有数值是否在 [0,1]width和height是否大于 0类别索引是否超出nc。import os label_dir labels/train bad [] for name in os.listdir(label_dir): if not name.endswith(.txt): continue with open(os.path.join(label_dir, name)) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: bad.append((name, i, 字段数不对)) continue cls, x, y, w, h parts vals list(map(float, [x, y, w, h])) # 归一化坐标必须落在 0~1宽高必须为正 if any(v 0 or v 1 for v in vals) or vals[2] 0 or vals[3] 0: bad.append((name, i, line.strip())) print(异常条目数:, len(bad)) for b in bad[:10]: print(b)这段脚本做三件事检查每行是否恰好 5 个字段、坐标是否越界、宽高是否非正。参数上label_dir换成你的实际路径即可。跑完如果异常条目为 0说明标签本身没问题后面训练出问题就不用怀疑标注了。2.2 目录结构与 data.yaml 的对应数据集已经划分好典型结构是images/train、images/val配labels/train、labels/val根目录放data.yaml。data.yaml里关键字段是train、val两个路径以及nc类别数和names类别名列表。烟盒数据集类别单一nc通常是 1names里就一个类别名。这里有个高频误解data.yaml里的路径写的是相对于谁的路径YOLOv5/v8 默认按“相对于数据集根目录”解析但不同版本、不同启动方式下行为会变。稳妥做法是直接写绝对路径或者确认你从哪个目录执行训练命令。我一般会把data.yaml打开逐行核对把train和val改成绝对路径省得后面报No labels found还找不到原因。# data.yaml 关键字段示例 path: /data/smoke_dataset # 数据集根目录 train: images/train # 相对 path 的训练图目录 val: images/val # 相对 path 的验证图目录 nc: 1 # 类别数烟盒通常为 1 names: 0: cigarette_box # 类别名按你的实际标注改path是根train/val相对它拼接。如果你的目录层级和这个不一致要么改 yaml要么调整文件夹。别小看这一步训练脚本读不到图九成是这里路径没对上。3. 用 YOLOv8 跑通训练从环境到第一轮验证指标3.1 环境准备与依赖版本YOLOv8 走 ultralytics 包安装本身不复杂坑在版本和 CUDA 匹配。常见做法是先用 conda 或 venv 建一个干净环境再装对应 CUDA 版本的 torch最后装 ultralytics。如果你机器上已经有 torch先确认它能不能正常调用 GPU否则训练会默默退回 CPU速度差几十倍。# 建环境并安装torch 版本按你的 CUDA 选 conda create -n yolo_smoke python3.10 -y conda activate yolo_smoke pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics # 验证 GPU 是否可用 python -c import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))torch.cuda.is_available()返回True才说明 GPU 可用。如果返回False先别急着训检查驱动和 CUDA 版本不然跑一晚上发现用的是 CPU血泪经验。ultralytics装完会自带yolo命令行工具后面直接用它。3.2 启动训练与关键参数训练命令本身很短参数才是决定成败的地方。下面这条是我在单卡上跑烟盒数据集的常用配置imgsz设 640batch按显存给epochs先跑 100 看收敛趋势。yolo detect train \ data/data/smoke_dataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/smoke \ nameexp1逐项说明data指向你的 yamlmodelyolov8n.pt用 nano 版预训练权重数据集小、类别单一nano 足够且快想提精度再换yolov8s.ptimgsz640是输入分辨率烟盒在图中占比不大时可以试 640 或 768batch16显存不够就降到 8 或 4lr00.01是初始学习率小数据集别设太大patience20表示 20 轮没提升就早停省时间。project和name决定结果存哪方便你对比多次实验。训练过程中重点看box_loss、cls_loss和mAP50。box_loss下降说明框在收敛cls_loss下降说明分类在学mAP50是验证集上的主指标。如果box_loss一直震荡不降先回去查标签坐标是否越界如果mAP50卡在很低的值多半是类别索引或路径问题。3.3 验证与推理确认模型真的学到了训练完别只看最后一行的数字跑一次独立验证和几张图的推理眼见为实。验证命令会输出每类的 P、R、mAP推理则能直接看图上的框。# 在验证集上评估 yolo detect val \ modelruns/smoke/exp1/weights/best.pt \ data/data/smoke_dataset/data.yaml \ imgsz640 # 对单张图推理并保存结果 yolo detect predict \ modelruns/smoke/exp1/weights/best.pt \ source/data/smoke_dataset/images/val \ saveTrue \ conf0.25val的imgsz要和训练一致否则指标会偏。predict里conf0.25是置信度阈值烟盒这种目标可以先用 0.25 看召回漏检多就降到 0.1误检多就升到 0.4。结果图存在runs/detect/predict下抽十几张看框的位置和置信度比盯数字有用。如果框明显偏移回到标签校验那一步如果框对但类别错检查names顺序和训练时是否一致。4. 避坑与排查标签、路径、显存这三类问题最常见4.1 训练报 No labels found现象启动训练后直接报找不到标签或者labels为空。原因通常是data.yaml里train/val路径写错或者图片和标签目录没对应上——YOLO 默认按“把images替换成labels、扩展名换成.txt”去找标签。解决先确认images/train下每张图在labels/train下有同名 txt再把 yaml 里的路径改成绝对路径排除相对路径歧义。改完重跑别在报错状态下反复调参。4.2 坐标越界导致框画到图外现象推理结果里框跑到图像边界外或者训练 loss 异常。原因YOLO txt 的坐标必须是归一化值如果误把像素坐标写进去数值会大于 1。解决跑 2.1 里的校验脚本把所有越界行找出来。如果是自己转换格式时出的错检查转换脚本有没有除以图像宽高。这份数据集自带 txt正常不会越界但如果你混用了 xml 转换的结果就要重点查。4.3 显存不足训练中断现象训练几轮后报 CUDA out of memory。原因batch或imgsz超过显存。解决优先降batch从 16 降到 8 再到 4还不行就降imgsz到 512。另外workers设太大也会占内存一般设 4 到 8。别硬扛大 batch小 batch 配合梯度累积也能收敛只是慢一点。4.4 验证指标虚高或虚低现象mAP50高得离谱或低得离谱。原因验证集和训练集图片重叠或者val路径指到了训练集。解决确认images/val和images/train没有重复文件用文件名或哈希去重。这份数据集已经划分好正常不会重叠但如果你自己重新切分过务必检查。指标虚低则多半是imgsz和训练不一致或者conf阈值设太高。4.5 类别名对不上导致评估错乱现象训练正常但评估时类别显示成class_0之类或者 P/R 明显不对。原因data.yaml的names和标签里的类别索引没对齐。解决确认nc等于names长度且标签里的class索引从 0 开始、不超过nc-1。烟盒数据集类别单一nc1、索引只有 0这种情况一般不会错但换成多类数据集时这是高频坑。5. 进阶技巧用 xml 做交叉校验把数据质量钉死跑通训练只是第一步真正让模型稳的是数据质量。这份数据集同时给了 YOLO txt 和 VOC xml很多人只用 txt把 xml 晾在一边其实它是最好的交叉校验工具。思路很简单同一张图txt 里的归一化框还原成像素后应该和 xml 里的xmin/ymin/xmax/ymax基本重合。如果偏差大说明其中一套标签有问题。import os import xml.etree.ElementTree as ET from PIL import Image img_dir images/train txt_dir labels/train xml_dir annotations/train # 按你的实际目录改 def yolo_to_xyxy(line, w, h): cls, x, y, bw, bh line.split() x, y, bw, bh map(float, (x, y, bw, bh)) # 归一化中心宽高 - 像素左上右下 x1 (x - bw / 2) * w y1 (y - bh / 2) * h x2 (x bw / 2) * w y2 (y bh / 2) * h return x1, y1, x2, y2 mismatch [] for name in os.listdir(txt_dir): if not name.endswith(.txt): continue stem name[:-4] img_path os.path.join(img_dir, stem .jpg) xml_path os.path.join(xml_dir, stem .xml) if not (os.path.exists(img_path) and os.path.exists(xml_path)): continue w, h Image.open(img_path).size with open(os.path.join(txt_dir, name)) as f: yolo_lines [l for l in f if l.strip()] tree ET.parse(xml_path) xml_boxes [] for obj in tree.findall(object): b obj.find(bndbox) xml_boxes.append(( float(b.find(xmin).text), float(b.find(ymin).text), float(b.find(xmax).text), float(b.find(ymax).text) )) if len(yolo_lines) ! len(xml_boxes): mismatch.append((stem, 数量不一致, len(yolo_lines), len(xml_boxes))) continue for line, xb in zip(yolo_lines, xml_boxes): yb yolo_to_xyxy(line, w, h) # 允许 2 像素误差 if max(abs(a - b) for a, b in zip(yb, xb)) 2: mismatch.append((stem, 坐标偏差, yb, xb)) break print(不一致样本数:, len(mismatch)) for m in mismatch[:10]: print(m)这段脚本把 txt 的归一化框还原成像素坐标再和 xml 的绝对坐标逐框比对允许 2 像素误差。img_dir、txt_dir、xml_dir按实际路径改。跑完如果mismatch为空说明两套标签一致数据可以放心用如果有偏差优先信 xml 还是 txt 要看你的转换流程但至少你知道哪些样本需要人工复核。除了交叉校验还有两个习惯值得养成。一是训练前把data.yaml和标签校验脚本一起跑一遍当作数据体检二是每次换模型版本比如从 yolov8 换到 yolo11时先用同一份数据跑 10 个 epoch 做冒烟测试确认链路通再上完整训练。烟盒数据集体量小冒烟测试十几分钟就能出结果比训到一半发现路径错了划算得多。从那以后我每次拿到新数据集都强制先跑一遍标签校验和 xml 交叉比对再动训练命令。数据没问题后面调参才有意义。希望帮到你。本文还有配套的精品资源点击获取