简介:本资源是面向计算机视觉初学者与YOLO目标检测实践者的吸烟行为识别专用数据集,解决公共场所吸烟监测、智能安防等场景下的细粒度行为识别数据短缺问题。数据集包含5000余张真实场景下的吸烟图像(JPG格式),全部经LabelImg精细标注,提供XML与TXT两种标签格式,分别对应PASCAL VOC与YOLOv5/v8标准输入,目标类别统一为smoke,开箱即用于训练、验证与测试。压缩包共14569个文件,其中4856张图片、4856份XML标注、4857份TXT标注,结构规整、格式兼容性强,整体大小214.87MB,便于本地快速解压与加载。已有4060人学习下载,资源附带实测效果参考链接,涵盖数据清洗逻辑、YOLO训练配置建议及常见误检分析,配套目录清晰划分图像与双格式标签子文件夹,显著降低数据预处理门槛,适合快速开展行为检测模型迭代与部署验证。
1. 这不是“带烟头的图库”,而是一套可直接喂进YOLOv5/v8训练管道的吸烟行为检测数据集
你手头那张拍得模糊、角度歪斜、烟雾飘散的工地监控截图,大概率无法被通用目标检测模型识别为“吸烟”。但这个包含5000+张真实场景图像的数据集,专为解决这类问题设计:所有图片均来自实际安防监控、室内办公、餐厅、工厂等非摆拍环境,标注严格遵循YOLO训练规范——每个smoke实例都对应一个归一化边界框(x_center, y_center, width, height),且同时提供XML(Pascal VOC)与TXT(YOLO格式)双标签体系。它不依赖合成渲染或GAN生成,而是用LabelImg人工逐帧校验,确保烟头尺寸、手持姿态、遮挡比例、光照干扰等真实变量全部保留在数据分布中。适合正在落地施工安全监管、医院禁烟巡查、工厂行为合规审计等场景的算法工程师;也适合作为YOLOv5s/v6n/v8n轻量模型的baseline微调起点——无需清洗、无需格式转换、无需重标,解压即训。
2. 数据结构解析与YOLO训练前的标准化预处理
2.1 文件组织逻辑与两类标注格式的本质差异
该数据集采用明确分层目录结构:
smoking_dataset/ ├── images/ # 所有.jpg原始图像(5392张,含标题所列smoking_1_*.jpg) ├── labels_xml/ # Pascal VOC格式标注(.xml),含<filename>、<size>、<object><name>smoke</name><bndbox>...</bndbox></object> └── labels_txt/ # YOLO格式标注(.txt),每行格式:0 x_center y_center width height(归一化到[0,1]区间)关键点在于:XML标注保留原始图像宽高信息,可用于跨框架迁移(如转为COCO JSON);而TXT标注已按YOLO要求完成坐标归一化——这不是简单缩放,而是将bbox左上角坐标(x_min,y_min)、宽高(w,h)转换为图像中心点相对坐标。例如一张1920×1080图像中,烟头bbox为(840,420,120,80),则YOLO TXT中对应行为:
0 0.4375 0.4333 0.0625 0.0741提示:
x_center = (x_min + w/2) / image_width,y_center = (y_min + h/2) / image_height,width = w / image_width,height = h / image_height。若误用未归一化的像素值,训练时loss会爆炸式增长。
2.2 构建YOLOv8兼容的dataset.yaml配置文件
YOLOv8要求显式声明数据路径、类别数及类别名。需新建smoking_dataset/data.yaml:
train: ../smoking_dataset/images # 注意:此处为相对路径,需与训练脚本位置匹配 val: ../smoking_dataset/images # 实际项目建议划分train/val子目录,此处为简化演示 nc: 1 # 类别数量(仅smoke一类) names: ['smoke'] # 类别名列表,索引0对应smoke注意:YOLOv8默认使用
images目录下所有.jpg作为训练样本,不读取labels_txt目录名——它会自动查找同名.txt文件(如smoking_1_214.jpg→smoking_1_214.txt)。若出现No labels found错误,首要检查labels_txt/中是否存在对应txt文件,其次确认文件名大小写与扩展名完全一致(Linux系统区分大小写)。
2.3 验证标注完整性:用Python脚本批量校验图像-标签配对
手动抽查易漏检。以下脚本可一次性验证5000+样本:
import os from pathlib import Path img_dir = Path("smoking_dataset/images") label_dir = Path("smoking_dataset/labels_txt") # 获取所有jpg文件名(不含扩展名) img_names = {f.stem for f in img_dir.glob("*.jpg")} label_names = {f.stem for f in label_dir.glob("*.txt")} missing_labels = img_names - label_names missing_images = label_names - img_names print(f"总图像数: {len(img_names)}") print(f"缺失标签的图像: {len(missing_labels)} 个") print(f"缺失图像的标签: {len(missing_images)} 个") if missing_labels: print("示例缺失项:", list(missing_labels)[:5])运行后若输出缺失标签的图像: 0 个,说明数据集结构完整。若存在不匹配项,需用labelImg重新导出对应txt文件——切勿手动编辑txt坐标,归一化计算必须由标注工具完成。
3. YOLOv8训练全流程:从环境配置到mAP验证
3.1 环境搭建与依赖安装(Ubuntu 22.04 + CUDA 11.8)
YOLOv8对PyTorch版本敏感,推荐组合:
# 创建conda环境(避免全局污染) conda create -n yolo-smoke python=3.9 conda activate yolo-smoke # 安装CUDA-aware PyTorch(根据NVIDIA驱动版本选择) pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 安装ultralytics(YOLOv8官方库) pip install ultralytics # 验证GPU可用性 python -c "import torch; print(torch.cuda.is_available(), torch.cuda.device_count())"提示:若
torch.cuda.is_available()返回False,需检查nvidia-smi是否可见GPU,以及CUDA Toolkit是否正确安装(nvcc --version应输出11.8)。
3.2 启动训练:关键参数含义与调优策略
执行以下命令启动训练(假设data.yaml位于当前目录):
yolo train \ data=data.yaml \ model=yolov8n.pt \ # 使用nano级模型,适合边缘部署 epochs=100 \ batch=32 \ imgsz=640 \ name=smoke_yolov8n_v1 \ project=runs/train \ device=0 \ workers=4 \ patience=20 \ exist_ok=True参数说明:
| 参数 | 含义 | 推荐值依据 |
|---|---|---|
batch | 单卡批大小 | 32在RTX 3090上稳定,若OOM可降至16 |
imgsz | 输入图像长边尺寸 | 640平衡精度与速度,小目标(烟头)不宜低于416 |
patience | 早停容忍轮数 | mAP连续20轮不升则终止,防过拟合 |
workers | 数据加载线程数 | 设为CPU核心数-1,避免I/O瓶颈 |
训练过程实时输出results.csv,含metrics/mAP50-95(B)(0.5~0.95 IoU阈值平均精度)。重点关注第50轮后的mAP50是否稳定在0.75以上——低于此值说明标注噪声大或模型欠拟合。
3.3 模型推理与结果可视化:验证检测逻辑是否合理
训练完成后,在runs/train/smoke_yolov8n_v1/weights/best.pt获取最优权重。执行推理:
yolo predict \ model=runs/train/smoke_yolov8n_v1/weights/best.pt \ source=smoking_dataset/images/smoking_1_214.jpg \ conf=0.25 \ save=True \ save_txt=True \ line_thickness=2生成结果存于runs/detect/predict/,其中:
smoking_1_214.jpg:叠加bbox的可视化图smoking_1_214.txt:预测结果(格式同label_txt,但置信度附加在末尾)
注意:
conf=0.25是关键阈值——吸烟检测需容忍低置信度(烟头小、遮挡多),但过低(如0.1)会导致大量误报。建议用验证集图像测试不同conf下的FP/FN平衡点。
4. 标注质量诊断与常见失效场景修复
4.1 三类典型标注缺陷及其修正方法
YOLO训练失败常源于标注隐性缺陷,而非代码错误:
4.1.1 “烟头”与“香烟”类别混淆
部分标注员将整支香烟(含过滤嘴)标为smoke,但实际需求是检测正在燃烧的烟头。这导致模型学习到“白色圆柱体”而非“发红光的微小区域”。
修复方案:用labelImg打开对应XML/TXT,将bbox收缩至仅覆盖烟头发光区(通常≤20×20像素),并重新导出YOLO格式。
4.1.2 多尺度目标未均衡采样
数据集中近景烟头(占图30%)与远景烟头(占图2%)比例失衡,模型偏向大目标。
修复方案:在data.yaml中启用rect=True(矩形推理)并添加mosaic增强:
# 在data.yaml末尾追加 augment: true mosaic: 0.5 # 50%概率启用mosaic增强,强制模型学习小目标4.1.3 遮挡场景标注不一致
多人手部遮挡烟头时,部分标注为完整bbox,部分标注为不可见(空txt)。
修复方案:统一规则——只要烟头像素可见≥10%,必须标注;完全不可见则不标。用以下脚本统计遮挡率:
import cv2 import numpy as np def calc_occlusion_ratio(img_path, label_path): img = cv2.imread(img_path) h, w = img.shape[:2] with open(label_path) as f: lines = f.readlines() if not lines: return 0.0 # 解析第一个bbox(假设单目标) cls, cx, cy, bw, bh = map(float, lines[0].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) roi = img[y1:y2, x1:x2] # 计算ROI内非黑像素占比(粗略估计可见度) visible = np.count_nonzero(roi) total = roi.size return visible / total if total > 0 else 0.0 # 示例:检查smoking_1_214.jpg ratio = calc_occlusion_ratio( "smoking_dataset/images/smoking_1_214.jpg", "smoking_dataset/labels_txt/smoking_1_214.txt" ) print(f"可见度: {ratio:.2%}")若ratio < 10%,应删除该标注或标记为ignore(YOLO暂不支持ignore标签,需在训练前过滤)。
4.2 模型性能瓶颈定位:用混淆矩阵分析漏检模式
YOLOv8默认不输出详细分类报告,需手动提取验证集预测结果:
# 先生成验证集预测 yolo val \ model=runs/train/smoke_yolov8n_v1/weights/best.pt \ data=data.yaml \ split=val \ save_json=True # 解析results.json(需自行编写解析脚本,核心逻辑:对比pred bbox与gt bbox的IoU)重点观察:
- 漏检(FN)集中于哪类图像?(如背光场景、戴手套手部)→ 增加对应数据增强(
hsv_h=0.015, hsv_s=0.7增强色彩鲁棒性) - 误检(FP)主要出现在什么区域?(如打火机反光、红色衣袖)→ 在
train.py中添加cls_loss_weight=0.5降低分类损失权重,强化定位精度
5. 工程化部署技巧:将best.pt转为TensorRT加速引擎
5.1 ONNX导出与TensorRT优化链路
YOLOv8原生支持ONNX导出,但需指定动态轴以适配不同尺寸输入:
yolo export \ model=runs/train/smoke_yolov8n_v1/weights/best.pt \ format=onnx \ dynamic=True \ opset=12 \ simplify=True生成best.onnx后,用TensorRT 8.6构建引擎:
trtexec --onnx=best.onnx \ --saveEngine=smoke_yolov8n.trt \ --fp16 \ --workspace=4096 \ --minShapes=input:1x3x640x640 \ --optShapes=input:4x3x640x640 \ --maxShapes=input:8x3x640x640 \ --shapes=input:4x3x640x640关键参数说明:
--minShapes定义最小批处理尺寸(1张图),--optShapes为最优尺寸(4张图并发),--maxShapes为最大尺寸(8张图)。实际部署时,输入batch size必须在此范围内。
5.2 C++推理代码核心片段(省略头文件与内存管理)
// 加载引擎 ICudaEngine* engine = context->deserializeCudaEngine(trtModelStream, size); IExecutionContext* context = engine->createExecutionContext(); // 分配GPU内存 void* buffers[2]; cudaMalloc(&buffers[0], 4 * 3 * 640 * 640 * sizeof(float)); // input cudaMalloc(&buffers[1], 4 * 100 * 6 * sizeof(float)); // output (100 boxes × [x,y,w,h,conf,cls]) // 推理 context->enqueueV2(buffers, stream, nullptr); cudaStreamSynchronize(stream); // 解析输出(YOLOv8输出为[1, 4, 84, 84, 84] → 需reshape为[1, 100, 6]) float* output = new float[100 * 6]; cudaMemcpy(output, buffers[1], 100 * 6 * sizeof(float), cudaMemcpyDeviceToHost); for (int i = 0; i < 100; ++i) { float* box = output + i * 6; if (box[4] > 0.3) { // 置信度过滤 float x1 = (box[0] - box[2]/2) * 1920; // 反归一化到原始分辨率 float y1 = (box[1] - box[3]/2) * 1080; printf("Smoke detected at (%.1f, %.1f, %.1f, %.1f) with conf %.2f\n", x1, y1, box[2]*1920, box[3]*1080, box[4]); } }部署验证要点:对比TensorRT引擎与PyTorch原生推理的mAP50差异,若下降>3%,需检查ONNX导出时是否启用了simplify=True(简化可能破坏某些op)。
本文还有配套的精品资源,点击获取