尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
YOLO抽烟检测数据集实战:从目录解析到训练调优与部署避坑
简介这是一套面向YOLO目标检测任务的抽烟行为检测数据集适合计算机视觉初学者或算法工程师用于模型训练、验证与调优。资源聚焦“抽烟”类别提供297张jpg原始图像与297个xml标注文件二者一一对应可直接转换为YOLO格式并进入训练流程。压缩包共594个文件大小约59.11MB数据规模适中便于快速下载、本地实验与算力要求不高的环境使用。目前已有375人学习使用可作为目标检测入门练习或算法效果对比的基准数据。借助成对图片与标注使用者无需自行采集和标注即可开展数据集划分、模型训练、mAP评估等操作同时可参考已有标注风格熟悉目标框选规范、类别定义与数据组织方式为后续构建自定义数据集打下基础。1. 这份YOLO抽烟目标检测数据集图与标签齐备解压就能进训练工地安全巡检、加油站禁烟区监控、车间工位违规行为提醒抽烟检测往往是这些场景里第一个被提上需求的功能。真去自采数据才发现坑很多办公区不方便拍室外雨天画面糊光组织人力标注几百张图就得耗掉一周。这份YOLO抽烟目标检测数据集把图片和标定数据都打包好了图片是贴近真实监控角度的抽烟场景标签是YOLO格式的txt类别定义清晰既可以当练手的模板素材也可以直接作为训练集复用到自己的检测流程里。适合刚入门目标检测、想快速跑通全流程的开发者也适合做安防项目但不想在数据准备上耗时间的工程师。下面从数据集结构开始拆讲清怎么用、参数怎么设以及我实际训练时踩过的几个坑。2. 数据集内部结构从目录看到单张标注的归一化坐标2.1 解压后的目录images 与 labels 一一对应拿到压缩包先别急着开训第一步是把目录结构看清楚。解压后最常见的组织方式是这样dataset/ ├── images/ │ ├── train/ │ │ ├── smoke_001.jpg │ │ ├── smoke_002.jpg │ │ └── ... │ ├── val/ │ │ └── ... │ └── test/ │ └── ... ├── labels/ │ ├── train/ │ │ ├── smoke_001.txt │ │ ├── smoke_002.txt │ │ └── ... │ ├── val/ │ │ └── ... │ └── test/ │ └── ... └── README.md注意 images 和 labels 下的子目录名必须一一对应同名图片与同名 txt 配对。有些版本会把 train、val 合并到一个文件夹里靠文件名前缀区分这种情况后面需要自己重新划分。还有的包会附带 classes.txt里面写的是类别名比如smoking这个文件建议保留后面写 data.yaml 时能直接抄。我一般会先跑一条命令确认没有孤儿文件——有图片没标签或者有标签没图片都会在训练时报错cd dataset for img in images/train/*.jpg; do name$(basename ${img%.jpg}) [ -f labels/train/${name}.txt ] || echo missing label: ${img} done这段脚本遍历 train 目录下每张 jpg检查同名 txt 是否存在缺了就打印图片路径。批量数据最怕这种隐性缺失YOLO 训练时遇到缺标签的图片不会直接崩但会跳过它导致实际参与训练的样本比预期少曲线看着正常精度却上不去。2.2 YOLO txt 标注格式归一化坐标的读法挑一个 txt 打开内容大致是这样0 0.5123 0.3842 0.1531 0.2167每行是一个目标框共五个数字class_id center_x center_y width height。这里的关键是坐标全部做了归一化除以了图片的宽和高值域在 0 到 1 之间。比如0.5123表示目标中心点在图片横向 51.23% 的位置0.2167表示框高占图片高度的 21.67%。如果你之前用过 VOC 格式的 XML 或者 COCO 的 JSON会注意到三种格式的差异VOC 存的是绝对值xmin ymin xmax ymaxCOCO 存的是x y w hYOLO 统一存中心点加宽高的归一化值。转换关系很简单x int(center_x * image_width) y int(center_y * image_height) w int(width * image_width) h int(height * image_height)实际做可视化验证时我都是先把 txt 转回像素坐标再画框确认标注框跟人、烟的位置对得上这个习惯能排查掉一大批低级错误。2.3 用脚本统计样本量、类别分布与图片规格建议先写个短脚本把家底盘清楚总共多少张图、多少个标注框、类别分布是否均衡。不要靠肉眼数几百个文件数错很正常。import os from collections import Counter from pathlib import Path label_root Path(labels/train) counter Counter() total_files 0 for txt in label_root.glob(*.txt): if txt.name classes.txt: continue total_files 1 with open(txt, encodingutf-8) as f: for line in f: line line.strip() if not line: continue cls int(line.split()[0]) counter[cls] 1 print(f标注文件数: {total_files}) print(f目标框总数: {sum(counter.values())}) for cls_id, count in sorted(counter.items()): print(f类别 {cls_id}: {count} 个目标)这段代码遍历 labels/train 下所有 txt逐行读取类别编号并计数。Counter统计出来的分布能直接告诉你数据是否失衡如果某个类别只有几十个框而主类别有上千个后面训练就要考虑加权或增广。顺带注意有些 txt 文件可能是空文件表示这张图没有任何目标line.strip()会跳过空行不会误判。图片尺寸也要确认一下混用 1920x1080 和 1280x720 本身问题不大YOLO 会统一 resize但如果图片尺寸差异过大比如混入竖屏截图训练时会被强行拉成正方形导致目标变形。from PIL import Image import os img_dir images/train sizes {} for name in os.listdir(img_dir)[:50]: with Image.open(os.path.join(img_dir, name)) as im: sizes[name] im.size unique_sizes set(sizes.values()) print(抽样图片尺寸集合:, unique_sizes)抽样前 50 张图片打印尺寸集合如果出现(720, 1280)这种竖屏尺寸就要考虑单独处理或直接剔除否则会影响预训练权重迁移的效果。3. 接入 YOLO 训练流程数据划分、配置与超参数怎么设3.1 划分训练集与验证集固定随机种子保证可复现如果压缩包里已经分好了 train 和 val可以跳过这一步。如果没分或者你想重新划分我习惯用脚本按 85:15 拆而不是手动拖文件——手动拖出来的验证集往往会带着人类自己的偏好比如总把目标大的图片放进验证集最后指标虚高部署现场露馅。import random import shutil from pathlib import Path random.seed(42) img_root Path(images) label_root Path(labels) imgs sorted(img_root.glob(*.jpg)) random.shuffle(imgs) split_idx int(len(imgs) * 0.85) for split, file_list in [ (train, imgs[:split_idx]), (val, imgs[split_idx:]), ]: (img_root / split).mkdir(exist_okTrue) (label_root / split).mkdir(exist_okTrue) for img_path in file_list: txt_path label_root / (img_path.stem .txt) if not txt_path.exists(): print(f跳过缺失标签的图片: {img_path.name}) continue shutil.move(str(img_path), str(img_root / split / img_path.name)) shutil.move(str(txt_path), str(label_root / split / txt_path.name))random.seed(42)是关键固定住 shuffle 的顺序这样每次划分结果都一样方便对比实验。split_idx按 85% 切分留 15% 做验证集——样本量大可以放宽到 90:10但几百张图的量级15% 的验证集大约有几十张已经够看出模型趋势了。移动文件时检查标签是否存在缺失标签的图片宁可跳过也别带进训练集。3.2 data.yaml 配置路径、类别名与类别数YOLOv5 和 YOLOv8 的训练入口不同但都需要一个 data.yaml 文件来告诉模型数据在哪、有几类。写法如下path: D:/work/smoke_dataset # 数据集根目录必填绝对路径 train: images/train val: images/val nc: 1 names: 0: smokingnc是类别总数这个数据集如果只有抽烟一类写 1 就行。names字典的索引必须和 txt 里的class_id对应txt 里写0那names的键必须是0。我见过有人把 names 写成{smoking: 0}顺序反了训练时装扮跑完精度曲线直接横盘查了半天才发现是配置问题。路径这里多说一句path写绝对路径最稳。用相对路径在本地能跑换台机器或挪了目录就裂开。Windows 下路径分隔符用正斜杠/或双反斜杠\\不要写单反斜杠\YAML 解析会出幺蛾子。3.3 训练命令与超参数从预训练权重开始收敛更快数据量不大的前提下不要从空权重开始训练强烈建议用预训练权重做迁移学习。命令如下# YOLOv5 写法 python train.py --data data.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 100 --device 0 # YOLOv8 写法 yolo detect train datadata.yaml modelyolov8s.pt imgsz640 batch16 epochs100 device0几个参数按经验说imgsz640是速度和精度的平衡点监控画面里烟占比很小设成 960 或 1280 能明显提升小目标召回率但显存占用和推理耗时同步上涨batch取 2 的幂16 在 8GB 显存下配 yolov5s 没压力如果显存紧张先降到 8 或 4epochs100对几百张图的数据集是够的再多就有过拟合风险后面看曲线再决定要不要加。还有个容易被忽略的细节训练时尽量保持终端窗口在前台跑完不要一边训练一边开一堆软件。YOLO 训练过程中如果显存被其他程序抢走可能中途报 CUDA OOM前面跑的几十个 epoch 白搭。建议把训练日志用tee存一份python train.py --data data.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 100 21 | tee train.log这样训练过程实时打印到屏幕同时落盘到 train.log后面画 loss 曲线时直接解析日志文件不用靠记忆复现。4. 训练效果的验证与调优曲线、可视化与增广手段4.1 训练曲线怎么读过拟合的信号是 val loss 掉头向上训练结束后YOLOv5 会生成runs/detect/train/results.pngYOLOv8 对应runs/detect/train/results.csv和曲线图。先把曲线分成两组看train loss 和 val loss。train loss 一直降是正常的关键是 val loss 降到某个点后开始反弹——这个反弹点就是过拟合的起点最佳权重通常保存在 val loss 最低的那个 epoch。import csv with open(runs/detect/train/results.csv) as f: rows list(csv.DictReader(f)) best max(rows, keylambda r: float(r[metrics/mAP50(B)])) print(mAP50 最高的 epoch:, best[epoch])用脚本直接找出 mAP50 最高的记录比肉眼盯曲线快得多。mAP50是 IoU 阈值 0.5 时的平均精度mAP50-95是 0.5 到 0.95 逐档算的平均后者对框的定位精度要求更高。抽烟检测这种场景mAP50 足够衡量但如果做的是精确测量类任务就得盯 mAP50-95。顺带注意 P 和 R 两个指标P精确率高、R召回率低说明模型框出来的基本都对但漏掉了很多目标常见于烟在画面里太小的情况反之 P 低 R 高就是误报多把类似烟的东西也框进来了。评估时两个都要看只看一个容易被带偏。4.2 把标注框画回原图验证标签可信度排除配置错误训练前我总要把原始标注画回图片上检查一遍。方法很多最简单的是直接读 txt 画框import cv2 img cv2.imread(images/val/sample.jpg) h, w img.shape[:2] with open(labels/val/sample.txt) as f: for line in f: parts line.split() if len(parts) ! 5: continue cls, xc, yc, bw, bh parts xc, yc, bw, bh map(float, (xc, yc, bw, bh)) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, fcls{cls}, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) cv2.imwrite(check_annotation.jpg, img)这段代码把归一化坐标乘回图片宽高还原成像素坐标画出矩形框。len(parts) ! 5的过滤条件能顺手找出格式异常的标注行。如果画出来的框明显偏移比如框在人的胸口而不是嘴附近大概率是标注导出时坐标算错这类污染数据留在训练集里会直接拉低精度。4.3 数据增强与类别不均衡用对参数比堆数据更划算YOLOv5 的增强参数集中在hyp.yaml几个影响大的我列一下hsv_h: 0.015 # 色调扰动 hsv_s: 0.7 # 饱和度扰动 hsv_v: 0.4 # 明度扰动 fliplr: 0.5 # 水平翻转概率 mosaic: 1.0 # 马赛克增强 mixup: 0.1 # 混合增强对于抽烟检测fliplr0.5可以开抽左手烟和右手烟在监控里都有。但flipud上下翻转别开监控摄像头装在屋顶视角固定目标永远在画面下方三分之一区域上下翻转会生成现实中不存在的构图白白增加学习难度。类别不均衡的常见解法是给少数类加权。如果数据里有两类比如smoking和cigarettesmoking有 800 个框而cigarette只有 60 个可以在 loss 里给cigarette更高的权重或者在增强时对少数类样本做复制粘贴增强。我自己遇到这种情况第一反应是先检查标注确认少数类是不是漏标了——漏标的样本加到权重里只会放大错误。5. 抽烟检测数据集避坑清单五个高频问题的排查路径5.1 loss 正常下降但 mAP 全程为 0现象训练跑得很顺train loss 一路降到 0.02 左右但验证集 mAP 始终为 0P 和 R 也都是 0。原因最常见的是类别配置错位。data.yaml 里nc值写大了比如只有 1 类却写了nc: 2模型强行学一个不存在的第二类。另一种可能是 txt 里的 class_id 越界标注里写的是2而 names 只定义到1。解决先跑 5.2 的可视化脚本确认标注坐标正常再检查 data.yamlnc必须和标注里的类别数完全一致names索引从 0 开始连续编号。然后用grep -rn ^1 labels/train/ | head看有没有类别 1 的标注有的话就要决定是合并类别还是修改 nc。5.2 中文路径导致图片读取失败现象训练刚开始就报错FileNotFoundError或者cv2.error: cant open file单独打开图片却能正常显示。原因Windows 下数据集放在D:\抽烟检测数据集\images这类带中文的目录里OpenCV 底层用的是imread对中文路径支持不好读不到文件。解决把整个数据集目录改成纯英文路径比如D:/work/smoke_dataset同时检查 data.yaml 里path字段不要出现中文。这是血泪教训分类任务可能不受影响目标检测训练几乎必炸。5.3 标签框坐标出现负值或大于 1现象训练日志里频繁出现WARNING: ignoring corrupt label或者类似提示训练能跑但收敛很慢。原因标注导出过程出错坐标归一化时除错了图片尺寸导致width或height变成负数或者中心点坐标超出 0-1 范围。也可能是某些标注软件保存了0 0 0 0 0这种空框。解决写个清洗脚本把所有越界框裁剪回 0-1 范围内完全在画面外的直接删掉def clean_label(txt_path): lines [] with open(txt_path) as f: for line in f: parts line.split() if len(parts) ! 5: continue cls, xc, yc, bw, bh parts[0], *map(float, parts[1:]) x1, y1 xc - bw / 2, yc - bh / 2 x2, y2 xc bw / 2, yc bh / 2 # 完全越界直接丢弃 if x2 0 or y2 0 or x1 1 or y1 1: continue # 部分越界则裁剪边界 x1, y1 max(0.0, x1), max(0.0, y1) x2, y2 min(1.0, x2), min(1.0, y2) nw, nh x2 - x1, y2 - y1 if nw 0 or nh 0: continue lines.append( f{cls} {(x1nw/2):.6f} {(y1nh/2):.6f} {nw:.6f} {nh:.6f} ) with open(txt_path, w) as f: f.write(\n.join(lines))清洗完再跑一次统计脚本确认没有空文件和异常坐标再训练。5.4 小目标漏检烟在远处只占几个像素现象验证集 mAP 有 0.8 以上但放到真实监控视频里画面远端的人嘴上叼着烟检测框不出来。原因输入图片 resize 到 640x640 后远处的烟可能只有 3x3 像素特征信息基本丢失。YOLO 默认的 anchor 和特征层对这种极小目标不敏感。解决优先把imgsz提到 960 或 1280训练和推理都用同一尺寸。显存不够就切成两段跑先训练 640 尺寸确定模型能收敛再微调时用 1280 尺寸跑几十轮。另外把conf_thres从默认 0.25 降到 0.15 能挽救一部分召回代价是误报增加需要配合 NMS 的iou_thres一起调。5.5 训练到一半显存 OOM现象前几个 epoch 正常跑到第 40 个 epoch 左右突然报CUDA out of memory进程被杀。原因mosaic 增强会在训练途中动态拼接多张图导致实际输入分辨率波动显存占用峰值出现在 epoch 中段而不是开头。如果batch16刚好卡在显存边缘增强一加强直接溢出。解决把 batch 降到 8或者开启梯度累积。YOLOv5 可以用--nbs 64参数自动把大 batch 拆成多次前向累积梯度。再不行就把--cache从ram改成disk把图片缓存从内存挪到硬盘能再省出几个 GB。6. 部署时的压缩与验证技巧从 ONNX 导出到现场视频逐帧确认6.1 导出 ONNX 和半精度模型体积减半速度翻倍训练完的 PyTorch 权重best.pt不适合直接扔到生产环境体积大、依赖重。常规做法是导出成 ONNX再根据部署端转成 TensorRT 或 OpenVINO 格式yolo export modelruns/detect/train/weights/best.pt formatonnx halfTrue imgsz640halfTrue会把权重转成 FP16模型体积直接减半。注意这一步需要推理端支持 FP16NVIDIA 的 GPU 没问题CPU 推理反而可能变慢。导出后用 onnxruntime 做个快速推理确认输出张量形状和预期一致再继续集成。如果部署目标是 Jetson 这类嵌入式设备继续转 TensorRT 能再提速一截但 TensorRT 的 engine 是跟 GPU 型号绑定的换一块卡就要重新转。工程上我一般保留 ONNX 作为中间格式设备端跑转换脚本不直接分发 engine 文件。6.2 用现场真实视频逐帧验证测试集指标好看不等于能用模型训练完最后一个动作是用一段未参与训练的真实场景视频逐帧跑推理观察误报和漏报from ultralytics import YOLO import cv2 model YOLO(best.pt) cap cv2.VideoCapture(site_test.mp4) fps cap.get(cv2.CAP_PROP_FPS) out cv2.VideoWriter( site_test_result.mp4, cv2.VideoWriter_fourcc(*mp4v), fps, (1280, 720), ) while True: ret, frame cap.read() if not ret: break results model.predict(frame, conf0.25, iou0.5, imgsz640, device0) annotated results[0].plot() out.write(annotated) cap.release() out.release()conf0.25是置信度阈值低于这个值的框直接丢弃iou0.5是 NMS 的交并比阈值多个重叠框合并时用。现场光线差时把conf调到 0.2 能降低漏检但也要接受更多误报。想起有回给某仓储项目做抽烟检测测试集 mAP 刷到 0.9 出头结果拿现场实拍视频一过货架阴影里人手的轮廓被框了一堆。仔细排查发现验证集里大多是目标明显的近景样本现场那种远距离影子场景根本没覆盖。从那以后我每次训完模型都会强制跑一段没参与训练的现场视频逐帧确认误报率能接受才交付。希望这个习惯和这份数据集一起帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

Java开源物联网平台实战拆解:选型部署到接入调优

Java开源物联网平台实战拆解:选型部署到接入调优

做Java后端这些年,身边朋友问得最多的方向就是开源物联网平台。前两年有个项目要做设备联网,老板上来就问能不能找一套现成的Java开源框架改一改,别从零造轮子。我花了两周时间把主流开源方案摸了一圈,又花了一个多月搭出第一版可…

📅 2026/10/12 19:55:37
浏览器取证实战指南:从SQLite数据定位到时间线重建

浏览器取证实战指南:从SQLite数据定位到时间线重建

干了这么多年数字取证,我最大的感受就是:只要嫌疑人用过电脑,不管他多小心,都会留下痕迹。而浏览器,恰恰是这些痕迹最集中、最密集的集散地。可以说,一个浏览器就能还原一个人最近几十天的网络行为轨迹。今…

📅 2026/10/12 19:55:37
浏览器取证实战:从SQLite数据库到Cookie解密与痕迹重建

浏览器取证实战:从SQLite数据库到Cookie解密与痕迹重建

1. 浏览器取证:一块硬盘里的“数字人生”接手一台涉案或涉事电脑,第一件事不是翻聊天记录,也不是抠邮件,而是先看浏览器。这不是我个人的偏好,而是浏览器本身的数据特性决定的。浏览器几乎是所有网络行为的“总入口”&…

📅 2026/10/12 19:55:37
MORE NEWS

更多资讯

📰

从栈溢出到堆利用:二进制安全学习路线与PWN实战调试笔记

1. 从栈到堆:为什么我坚持把这条学习路线走完刚接触二进制安全那会儿,我和很多人一样,觉得栈溢出就是全部。一个gets、一个strcpy,配上pattern_create和pattern_offset,算出偏移量,控制EIP,跳转…

📰

RepVGG结构重参数化:图像分类模型训练推理解耦与加速实战

简介:压缩包内含2000个文件,共986.61MB,其中以2435个png图片为数据主体,配合12个Python源码、2个pth权重文件、2个json配置及1个txt说明,构成一套完整的RepVgg图像分类实战项目。项目围绕“VGG式”结构展开&#xff0c…

📰

Python轻量级裁判文书量刑回归建模实战

简介:本资源是一套面向法律科技从业者、司法AI研究者及Python机器学习学习者的裁判文书量刑预测实践项目,聚焦于利用机器学习提升量刑建议的客观性与效率。压缩包共131个文件,含77个Python脚本(覆盖数据清洗、特征工程、模型训练与…

📰

基于VGG-16的图像检索系统:从特征提取到相似度排序的完整落地路径

简介:这份资源面向人工智能与信息检索方向的学习者,提供一套基于VGG-16的图像检索系统完整项目实践。项目以深度学习特征替代传统颜色、形状、纹理等手工特征,采用Keras预训练模型对图像库逐张抽取特征并存入h5文件,检索阶段以夹角…

📰

VHDL实战:分频器+计数器+数码管实现数字频率计

1. 从零拆解一个数字频率计的核心架构分频器、计数器、数码管显示,这三个词放在一起,稍微摸过FPGA或者CPLD的兄弟应该马上就能反应过来——这不就是一个数字频率计的核心链路吗?我当初第一次接触这个组合的时候,脑子里想的是“不就…

📰

深度拆解WPE封包修改:从截包分析、滤镜制作到独立外挂打包的实战路径

简介:WPE(Winsock Packet Editor)是游戏封包分析与修改领域常用的专业工具,主要用于截取网络通信数据包,在游戏调试、外挂原理学习、本地网络数据观察等场景中应用广泛。这份65页的教程系统整理了WPE各版本下载与版本特…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬