
简介这份吸烟行为检测数据集面向计算机视觉学习者与目标检测开发者尤其适合正在做YOLO系列实战、需要真实场景吸烟行为样本的读者。数据均使用labelImg完成标注图片为jpg格式标签同时提供xml与txt两种格式分别存放于独立文件夹可直接接入YOLO训练流程目标类别统一命名为smoke省去自行标注与格式转换的繁琐工作。压缩包共14569个文件其中jpg图片4856张、xml标签4856个、txt标签4857个整体约214.87MB结构清晰便于按需取用。目前已有4071人学习下载配套博文还给出了检测结果参考方便对照验证模型效果。对于想快速搭建吸烟行为识别基线、扩充训练样本或开展课程设计的读者这份数据能有效缩短数据准备周期把精力集中在模型调参与效果优化上。1. 5000 张吸烟行为数据为什么让 YOLO 训练从「能跑」变成「能用」吸烟行为检测这件事真正卡住落地的从来不是模型结构而是数据。你拿 COCO 或者 ImageNet 上预训练的权重直接去推理办公区、加油站、化工厂的监控画面模型大概率会把叼着的笔、手靠近嘴边的动作、甚至一根烟形状的白色反光都框成吸烟。原因很直接通用数据集里「吸烟」这个类别的样本极少且场景分布和真实监控差得太远。标题里的「YOLO 吸烟行为检测数据集5000数据」本质上是想解决一个具体问题——用一批规模可控、标注规范的吸烟行为图片把 YOLO 从「能跑通 demo」推到「在固定场景里能用」。它适合两类人一类是想做园区、工地、加油站烟火预警的算法工程师另一类是手里有摄像头但缺标注数据、想自己微调一个检测模型的技术负责人。5000 张不算大但足够让一个 YOLOv8n 或 YOLO11n 在单场景下收敛出可用的 mAP前提是你知道怎么划分、怎么标、怎么调。2. 吸烟行为检测数据集5000 张到底该怎么组织2.1 类别定义先于标注吸烟检测到底分几类很多人拿到 5000 张图第一反应是打开 labelImg 就开始框。这是血泪经验的起点。吸烟行为检测的类别设计直接决定模型能不能用。常见做法是分两类smoking正在吸烟烟在嘴边或手上且有点燃特征和not_smoking含手持烟未点燃、叼笔、打电话等干扰。但更稳的方案是只标一个类smoking把「未吸烟」交给背景。原因在于 YOLO 是单阶段检测器负样本通过背景区域隐式学习显式加一个not_smoking类反而容易让模型在「手靠近脸」和「烟靠近脸」之间反复横跳。我一般会这样定边界烟体可见且与嘴部距离小于头部宽度的 1/2标smoking烟在手上但离嘴远不标电子烟如果业务需要单独加vaping类不要和smoking混。5000 张里正样本建议不低于 3500 张否则模型会偏向背景。标注格式用 YOLO txt每行class_id x_center y_center width height全部归一化到 0~1。2.2 5000 张的划分比例与目录结构5000 张不能全拿去训练。按 8:1:1 划分是常见做法训练 4000、验证 500、测试 500。但如果你的场景有多个摄像头角度必须按摄像头划分不能随机打散否则同一帧的相邻帧会同时出现在训练和验证里mAP 虚高。目录结构建议直接对齐 YOLO 官方格式smoking_dataset/ ├── images/ │ ├── train/ # 4000 张 │ ├── val/ # 500 张 │ └── test/ # 500 张 ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── smoking.yamlsmoking.yaml内容如下path: /data/smoking_dataset train: images/train val: images/val test: images/test nc: 1 names: [smoking]这里nc是类别数names顺序必须和标注里的class_id一致。很多人翻车在path写了相对路径训练时找不到图报No labels found。建议写绝对路径或者确认训练脚本的工作目录。2.3 标注质量自查三个必须跑的脚本标完 5000 张别急着训练。先跑三个检查。第一检查图片和标签是否一一对应import os img_dir smoking_dataset/images/train lbl_dir smoking_dataset/labels/train imgs {os.path.splitext(f)[0] for f in os.listdir(img_dir)} lbls {os.path.splitext(f)[0] for f in os.listdir(lbl_dir)} print(缺标签的图:, imgs - lbls) print(缺图的标签:, lbls - imgs)第二检查标注框是否越界或宽高为 0import os lbl_dir smoking_dataset/labels/train for f in os.listdir(lbl_dir): with open(os.path.join(lbl_dir, f)) as fp: for i, line in enumerate(fp): cls, x, y, w, h map(float, line.split()) if not (0 w 1 and 0 h 1 and 0 x 1 and 0 y 1): print(f异常: {f} 第{i}行 - {line.strip()})第三统计正样本框数量。5000 张图如果总框数低于 4000说明漏标严重模型召回上不去。这三个脚本跑完再进训练能省掉后面几小时的无效 epoch。3. 用 YOLOv8/YOLO11 在 5000 张上跑通训练命令与参数3.1 环境与最小训练命令环境用 PyTorch ultralytics 即可。不要一上来就搞 TensorRT 或剪枝先把基线跑出来。最小训练命令yolo detect train \ datasmoking_dataset/smoking.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectruns/smoking \ namebaselinemodelyolov8n.pt是 nano 版本参数量小5000 张足够收敛。imgsz640是 YOLO 的默认输入监控场景如果烟体很小可以提到 960但显存和速度会变。batch16在 8G 显存上比较稳如果 OOM 就降到 8。device0指定第一块 GPU。训练日志里重点看mAP50和mAP50-95吸烟检测通常mAP50到 0.85 以上才算能用。3.2 吸烟小目标的关键参数imgsz、anchor 与数据增强吸烟检测的难点是烟体小尤其是远景摄像头。imgsz640时一根烟可能只有 10×10 像素。三个参数要调imgsz优先提到 960 或 1280但推理速度会下降。如果业务要求 25fps先测 640 的基线再决定是否牺牲速度换精度。close_mosaicYOLOv8 默认最后 10 个 epoch 关闭 mosaic 增强。小目标场景建议设close_mosaic20让模型在训练后期多见真实分布。scale和mosaic默认 0.5 和 1.0。如果数据里烟体尺度变化大保持默认如果全是固定摄像头可以降到scale0.3减少无意义的缩放。数据增强里hsv_h、hsv_s、hsv_v对吸烟检测有用因为烟在不同光照下颜色差异大。但flipud上下翻转要慎用吸烟动作有方向性上下翻转会造出不自然的样本。常见做法是fliplr0.5flipud0.0。3.3 训练过程监控与早停训练不是跑满 100 epoch 就好。用patience20早停验证集 mAP 连续 20 轮不升就停。同时开plotsTrue训练完看results.png里的损失曲线。如果box_loss和cls_loss都降但mAP不升大概率是过拟合需要加数据或加增强。如果cls_loss震荡检查标注里有没有把「手拿烟」和「嘴叼烟」混标。yolo detect train \ datasmoking_dataset/smoking.yaml \ modelyolov8n.pt \ epochs150 \ imgsz960 \ batch8 \ patience20 \ close_mosaic20 \ fliplr0.5 \ flipud0.0 \ device0跑完在runs/smoking/baseline/weights/best.pt拿到最优权重。先别急着部署用测试集跑一次val确认没有过拟合。4. 推理、导出与误报排查从 best.pt 到可用服务4.1 测试集验证与混淆矩阵怎么看训练完必须用test集做一次独立验证yolo detect val \ modelruns/smoking/baseline/weights/best.pt \ datasmoking_dataset/smoking.yaml \ splittest \ imgsz960重点看混淆矩阵。如果smoking被大量预测为背景说明召回低可能是正样本太少或conf阈值太高。如果背景被预测为smoking说明误报高需要加负样本或提高conf。吸烟检测的误报主要来自「手靠近嘴」「白色口罩」「笔」。解决办法是在训练集里专门加这类负样本而不是调阈值硬压。4.2 导出 ONNX 与推理脚本部署前导出 ONNXyolo export \ modelruns/smoking/baseline/weights/best.pt \ formatonnx \ imgsz960 \ simplifyTrue推理脚本示例from ultralytics import YOLO model YOLO(runs/smoking/baseline/weights/best.pt) results model.predict( sourcetest.jpg, imgsz960, conf0.35, iou0.5, device0 ) for r in results: for box in r.boxes: cls int(box.cls) conf float(box.conf) xyxy box.xyxy.tolist()[0] print(f类别{model.names[cls]} 置信度{conf:.2f} 框{xyxy})conf0.35是吸烟检测的常用起点。低于 0.3 误报明显增多高于 0.5 漏报增多。iou0.5控制 NMS 合并如果同一个人嘴里和手上都有烟可能会被合并成一个框这时可以适当提高iou到 0.6。4.3 误报与漏报的排查顺序误报先查负样本。把误报的图截下来看是不是「手靠近脸」「白色物体」这类。如果是补进训练集标为背景不标框重新训练。漏报先查imgsz和conf。远景烟体小imgsz640可能直接丢特征提到 960 再试。如果还漏检查标注有没有漏标。最后才考虑换模型比如从yolov8n换到yolov8s参数量翻倍小目标召回会好一些但速度下降。5. 避坑与常见问题5000 张吸烟数据训练翻车记录5.1 现象mAP 很高但实际推理全是误报原因训练集和验证集随机划分同一段视频的相邻帧同时进了训练和验证模型记住了背景而不是烟。解决按视频或摄像头划分确保验证集的场景在训练集里没出现过。如果已经随机划分了重新按时间戳或文件名前缀分组。5.2 现象训练 loss 不降mAP 一直是 0原因smoking.yaml里的names和标注class_id对不上或者path写错导致加载不到标签。解决先跑 2.3 的检查脚本确认图片和标签一一对应再确认nc等于实际类别数。如果标签是 XML 格式没转成 txtYOLO 会直接忽略。5.3 现象模型把「叼笔」识别成吸烟原因负样本里缺少「嘴部有类似烟状物体」的样本。解决专门收集 200~300 张叼笔、叼吸管、手拿白色物体的图标为背景加入训练集。不要试图用conf阈值硬压压了会连带漏掉真吸烟。5.4 现象导出 ONNX 后推理结果和 PyTorch 不一致原因导出时imgsz和推理时不一致或者simplify改变了算子。解决导出和推理用同一个imgsz比如都写 960。如果还不一致检查预处理有没有做归一化和 RGB 转换ONNX 模型不会自动做这些。5.5 现象显存够但训练速度极慢原因batch太小或者workers没设。解决在yolo detect train里加workers8batch根据显存调到 16 或 32。如果数据在机械硬盘上把 5000 张图拷到 SSDIO 会成为瓶颈。6. 把 5000 张用出 5 万张的效果小数据下的进阶技巧5000 张在检测任务里不算多但用对方法可以逼近更大数据集的效果。第一个技巧是「难例挖掘」。先用基线模型跑一遍训练集把置信度在 0.3~0.6 之间的预测框对应的图挑出来人工复核。这些图往往是模型最不确定的补标或修正后重新训练一轮就能涨 2~3 个点。第二个技巧是「复制粘贴增强」。把标注好的烟体抠出来随机粘贴到负样本的嘴部区域生成新的训练图。注意粘贴时要匹配光照和尺度否则模型会学到不自然的边缘。第三个技巧是「多尺度训练」。在yolo detect train里设imgsz640但开multi_scaleTrue让模型在 0.5~1.5 倍尺度间随机切换对远景和近景混合的场景很有效。验证方法上不要只看 mAP。吸烟检测的业务指标是「每路摄像头每天的误报次数」。拿 500 张测试集跑完统计误报数和漏报数换算成单路日误报。如果单路日误报超过 5 次模型还不能上线。我一般会留一个「后悔药」训练时保存最后 10 个 epoch 的权重部署时先用best.pt如果线上误报高回退到last.pt对比有时候最后一个 epoch 反而更稳。最后一个习惯每次改数据或参数只改一个变量记录mAP50、mAP50-95、单路日误报。5000 张的数据集调 3~4 轮就能找到可用配置。别一次改五个参数否则翻车了都不知道是哪儿的锅。希望帮到你。本文还有配套的精品资源点击获取