首页 / 资讯中心 / 文章详情

YOLOv8吸烟检测实战:991张图训练与88.3%识别率调优

YOLOv8吸烟检测实战:991张图训练与88.3%识别率调优 ★ FEATURED ARTICLE
简介这份吸烟行为检测数据集面向计算机视觉方向的学习者与算法开发者适用于目标检测模型的训练、微调与课堂实验可支撑公共场所吸烟行为识别、智能监控等场景的算法验证。资源共包含1983个文件其中991张jpg原始图片与991个同名txt标注文件一一对应另附1个yaml配置文件用于声明类别与数据路径压缩包整体约44.7MB采用yolov8格式标注可直接接入主流检测框架训练。图片覆盖多种人物姿态与拍摄角度标注框对应吸烟、抽烟行为区域便于快速构建训练集与验证集。据描述基于该数据训练的平均识别率可达88.3%可作为基线参考。目前已有110人学习下载适合需要现成标注数据、希望缩短数据准备周期并快速复现检测效果的入门与进阶开发者使用。1. 吸烟数据集 991 张原始图片88.3% 识别率背后的真实门槛如果你正在找一份能直接跑 YOLOv8 的吸烟行为检测数据集大概率已经刷到过这个组合991 张原始图片、YOLOv8 格式标注、平均识别率 88.3%。这三个数字放在一起看起来像是一个开箱即用的方案但我第一次拿到类似规模的数据集时踩的坑比想象中多——991 张图在目标检测里属于小样本88.3% 的识别率往往是在特定测试集上跑出来的换一个摄像头角度、换一批光照条件掉到 70% 出头是常有的事。这篇文章不讲空泛的数据集介绍而是把这份吸烟数据集从拿到手到跑出可用模型的全流程拆开YOLOv8 格式标注到底长什么样、991 张图怎么划分才不翻车、训练参数怎么设、88.3% 这个数字在什么条件下成立、以及 RK3588 这类边缘设备部署时要注意什么。适合手里已经有一份标注数据、想快速验证能不能落地的工程师也适合刚接触 YOLOv8 训练自己数据集的新手照着走一遍。2. 拆开这份吸烟数据集YOLOv8 标注格式与 991 张图的分布逻辑2.1 YOLOv8 标注格式到底长什么样YOLOv8 用的是 YOLO 系列的经典标注格式每张图片对应一个同名.txt文件每行代表一个目标格式是class_id x_center y_center width height四个坐标值都是归一化到 0~1 之间的浮点数相对于图片宽高。这一点和 LabelImg 导出的 YOLO 格式一致但和 COCO 的[x_min, y_min, width, height]绝对像素坐标完全不同。很多人从 COCO 转过来时忘了归一化训练时 loss 直接爆炸。一份典型的吸烟数据集目录结构是这样的smoking_dataset/ ├── images/ │ ├── train/ (约 700 张) │ ├── val/ (约 150 张) │ └── test/ (约 141 张) ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamldata.yaml是 YOLOv8 训练时的入口配置文件内容通常只有几行path: /home/user/smoking_dataset train: images/train val: images/val test: images/test nc: 1 names: [smoking]这里nc: 1表示只有一类目标。吸烟检测通常是单类检测——只判断有没有人在吸烟不区分香烟品牌或姿态。如果你的数据集里还标了手持香烟嘴边香烟等子类nc要相应改成 2 或 3names列表顺序必须和标注文件里的class_id严格对应错一位整个训练就废了。2.2 991 张图怎么划分才不翻车991 张这个数字很微妙。按 7:1.5:1.5 划分训练集约 694 张、验证集约 148 张、测试集约 149 张。但直接随机划分有个隐患如果同一个人的多张连续帧被分到训练集和验证集验证指标会虚高实际部署时性能掉得厉害。我一般会先做一步按场景聚类再划分import os import random import shutil from collections import defaultdict # 假设图片文件名里带有场景前缀如 indoor_001.jpg, outdoor_001.jpg def split_dataset(src_img_dir, src_label_dir, dst_root, ratios(0.7, 0.15, 0.15)): scenes defaultdict(list) for fname in os.listdir(src_img_dir): if not fname.lower().endswith((.jpg, .png, .jpeg)): continue # 提取场景前缀这里按文件名第一个下划线前的内容分组 scene fname.split(_)[0] scenes[scene].append(fname) train, val, test [], [], [] for scene, files in scenes.items(): random.shuffle(files) n len(files) n_train int(n * ratios[0]) n_val int(n * ratios[1]) train.extend(files[:n_train]) val.extend(files[n_train:n_train n_val]) test.extend(files[n_train n_val:]) for split_name, files in [(train, train), (val, val), (test, test)]: img_out os.path.join(dst_root, images, split_name) lbl_out os.path.join(dst_root, labels, split_name) os.makedirs(img_out, exist_okTrue) os.makedirs(lbl_out, exist_okTrue) for f in files: shutil.copy(os.path.join(src_img_dir, f), os.path.join(img_out, f)) lbl os.path.splitext(f)[0] .txt src_lbl os.path.join(src_label_dir, lbl) if os.path.exists(src_lbl): shutil.copy(src_lbl, os.path.join(lbl_out, lbl)) split_dataset(./raw/images, ./raw/labels, ./smoking_dataset)这段脚本的核心逻辑是先按场景前缀分组再在每组内部按比例抽取保证训练集和验证集不出现同一场景的近邻帧。参数ratios可以按需调整991 张图建议保持 7:1.5:1.5如果某类场景样本特别少比如夜间吸烟只有 30 张可以适当提高验证集比例到 0.2让评估更稳定。划分完之后一定要做一次校验训练集和验证集的图片数量加起来是否等于 991有没有图片没有对应的标注文件。缺失标注的图片在训练时会被 YOLOv8 当作背景负样本少量可以接受超过 5% 就会明显拉低召回率。2.3 标注质量自查三个必看的指标991 张图如果全部人工标注标注一致性很难保证。训练前花半小时做一次自查比训练后调参三天更有效。我一般看三个指标检查项方法合格线框是否越界遍历所有 txt检查坐标是否在 0~1 之间越界框占比 0.5%是否有空标注统计每张图的标注行数空标注图占比 3%类别是否错标抽样 50 张可视化检查错标率 2%越界框是最常见的低级错误通常来自标注工具导出时的坐标计算 bug。空标注图如果太多说明标注员漏标了目标模型会学到这张图里没有吸烟行为的错误信号。类别错标在单类检测里不涉及但如果你扩展成多类必须逐类抽查。3. 用 YOLOv8 训练吸烟数据集从环境配置到 88.3% 识别率3.1 Ubuntu 20.04 下 CPU 版本环境搭建很多人搜Ubuntu20.04 搭建 YOLOv8 环境 CPU 版本是因为手头没有 GPU 或者只是想先跑通流程。CPU 训练 991 张图不是不能做但要有心理预期YOLOv8n 在 CPU 上跑 100 个 epoch 大约需要 6~10 小时YOLOv8m 可能要 20 小时以上。如果只是验证数据集可用性建议先用 YOLOv8n 跑 30 个 epoch 看趋势。环境搭建的最小步骤# 创建虚拟环境Python 3.8~3.10 都可以 conda create -n yolov8_cpu python3.9 -y conda activate yolov8_cpu # 安装 PyTorch CPU 版本注意不要装成 CUDA 版本 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 安装 ultralytics pip install ultralytics # 验证安装 yolo checksyolo checks会输出当前环境信息重点看两行PyTorch 版本后面有没有cpu标记以及CUDA是否显示为None。如果显示 CUDA 可用但你确实想用 CPU可以在训练命令里显式指定devicecpu。提示CPU 训练时把workers设成 2~4 就够了设太大反而因为进程切换拖慢速度。batch建议设 8 或 16太大内存扛不住。3.2 训练命令与关键参数怎么设YOLOv8 的训练入口非常简洁一条命令就能启动yolo detect train \ data./smoking_dataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ devicecpu \ workers4 \ projectsmoking_runs \ nameexp1 \ patience20 \ save_period10逐个参数说明data指向data.yaml的路径YOLOv8 会自动解析里面的 train/val/test 路径。model预训练权重。yolov8n.pt是最小的 nano 版本CPU 训练首选如果有 GPU可以换yolov8s.pt或yolov8m.pt识别率通常能提升 2~4 个百分点。epochs训练轮数。991 张图建议 100~150配合patience20做早停。imgsz输入分辨率。640 是默认值如果图片里香烟目标很小比如远景监控画面可以提到 800 或 960但 CPU 训练时间会成倍增加。batch批大小。CPU 上 16 是比较稳的值内存 16GB 以下建议降到 8。patience验证指标连续 20 轮不提升就停止避免过拟合。save_period每 10 轮保存一次权重方便回滚。训练过程中重点看输出里的mAP50和mAP50-95。88.3% 的识别率通常指的是mAP50也就是 IoU 阈值 0.5 时的平均精度。如果mAP50在 50 轮后就卡在 80% 左右不动大概率是标注质量或数据分布问题继续加 epoch 收益很小。3.3 88.3% 识别率在什么条件下成立这个数字不是凭空来的但也不是随便换个场景就能复现。根据我对同类吸烟数据集的训练经验88.3% 的mAP50通常对应以下条件测试集和训练集来自同一批数据源光照、角度、分辨率分布一致目标香烟/吸烟动作在画面中占比不低于 5%不是那种几十像素的小目标标注框贴合度较高没有大量框太大把整个人框进去的情况使用的是 YOLOv8s 或更大模型而不是 nano 版本。如果你用 YOLOv8n 在 CPU 上训练mAP50落在 82%~86% 是正常区间。想冲到 88% 以上优先做三件事换yolov8s.pt预训练权重、把imgsz提到 800、检查并修正标注框贴合度。这三步做完通常能提升 3~5 个百分点比调学习率、换优化器见效快得多。另外要注意mAP50高不代表实际可用。部署时更关心的是在固定误报率下的召回率。如果业务场景对误报很敏感比如公共场所监控建议在验证集上画一条 PR 曲线选一个召回率 85%、误报率 5% 左右的置信度阈值而不是直接用默认的 0.25。4. 吸烟检测模型部署与推理从 PyTorch 权重到实际画面4.1 推理脚本与置信度阈值调优训练完成后smoking_runs/exp1/weights/best.pt就是最终权重。写一个最小推理脚本验证效果from ultralytics import YOLO import cv2 model YOLO(smoking_runs/exp1/weights/best.pt) # 单张图片推理 results model.predict( sourcetest_image.jpg, conf0.35, # 置信度阈值默认 0.25吸烟检测建议 0.3~0.4 iou0.5, # NMS 的 IoU 阈值 imgsz640, devicecpu, saveTrue ) # 视频流推理 cap cv2.VideoCapture(0) while cap.isOpened(): ret, frame cap.read() if not ret: break results model.predict(frame, conf0.35, verboseFalse) annotated results[0].plot() cv2.imshow(smoking_detect, annotated) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()conf参数是实际部署时最需要调的。设太低0.2会把拿手机、喝水等动作误判为吸烟设太高0.6会漏掉侧脸、遮挡场景。我的经验是先在验证集上跑一遍统计不同conf下的精确率和召回率选一个业务能接受的平衡点。iou0.5对单类检测够用如果画面里多人同时吸烟且框重叠严重可以降到 0.4 让 NMS 更激进地合并。4.2 RK3588 等边缘设备部署的注意点搜RK3588 部署 YOLOv8的人不少吸烟检测上边缘设备是常见需求。核心流程是PyTorch 权重 → ONNX → RKNN。这里不展开完整转换命令只说三个最容易翻车的点第一导出 ONNX 时opset建议用 12不要用最新的 17。RKNN 工具链对高版本 opset 的支持不完整容易出现不支持的算子。导出命令yolo export modelbest.pt formatonnx opset12 imgsz640 simplifyTrue第二量化校准集要覆盖实际场景。RKNN 的 INT8 量化需要一批校准图片如果校准集全是白天室内图夜间室外场景的精度会掉得很厉害。建议从训练集里按场景分层抽 200~300 张做校准。第三输入分辨率对齐。训练时用 640部署时也要用 640不要为了省算力改成 416。YOLOv8 的 anchor 和特征图尺寸是跟输入分辨率绑定的改了之后小目标检测能力断崖式下降。5. 吸烟数据集训练避坑5 个血泪教训5.1 现象训练 loss 正常下降但 mAP 一直为 0原因data.yaml里的names顺序和标注文件里的class_id对不上或者nc设成了 0。YOLOv8 不会报错但所有预测都被当作背景。解决打开任意一个标注 txt看第一列的数字确认最大值小于nc且names列表长度等于nc。单类检测nc: 1names: [smoking]标注里只能出现0。5.2 现象验证集 mAP 很高实际测试惨不忍睹原因数据划分时同一场景的连续帧被分到了训练集和验证集验证集相当于见过的图片。991 张图如果来自视频抽帧这个问题几乎必然出现。解决按场景或按视频来源分组划分同一组的帧只进一个 split。前面 2.2 节的脚本就是干这个的。5.3 现象CPU 训练到一半内存溢出被 kill原因batch设太大或者workers太多导致每个 worker 都加载了一份数据缓存。CPU 训练时 PyTorch 的内存占用比 GPU 训练更敏感。解决batch降到 8workers降到 2加cacheFalse关闭数据缓存。如果还不行把imgsz从 640 降到 512 先跑通流程。5.4 现象模型把拿烟和吸烟混为一谈原因标注时没有区分手持香烟和嘴边吸烟或者两类样本比例严重失衡。单类检测下模型只学香烟出现不学正在吸。解决如果业务只关心是否吸烟标注时统一框香烟 嘴部区域如果关心是否正在吸需要扩成两类并保证每类至少 200 个样本。991 张图做单类够用做多类就紧张了。5.5 现象导出的 ONNX 在 RKNN 上推理结果全乱原因导出时用了simplifyTrue但没装onnxsim或者 opset 版本过高导致算子不被支持。解决先pip install onnxsim再导出opset 固定用 12。导出后用onnxruntime跑一张测试图确认 ONNX 模型输出和 PyTorch 一致再转 RKNN。6. 把 88.3% 再往上推三个我常用的进阶技巧第一个技巧是困难样本回捞。训练完第一轮后用best.pt在训练集上跑推理把置信度在 0.3~0.5 之间的预测框对应的图片挑出来人工复核标注。这批图往往是标注模糊或目标遮挡的困难样本重新标一遍再加入训练通常能提升 1~2 个百分点。991 张图的规模回捞一轮大概能找出 30~50 张问题图投入产出比很高。第二个技巧是多尺度训练。在data.yaml同级加一个训练配置把imgsz设成 640但开启rectFalse和scale0.5让 YOLOv8 在训练时随机缩放图片。这样模型对不同距离的吸烟目标适应性更强尤其适合监控场景。代价是训练时间增加约 20%。第三个技巧是测试时增强TTA。推理时加augmentTrueYOLOv8 会对同一张图做翻转、缩放等多尺度预测再合并结果。mAP50通常能再涨 0.5~1 个百分点但推理速度会慢 2~3 倍。如果部署在 RK3588 上不建议开 TTA算力扛不住如果是在服务器端做离线分析可以开。最后一个习惯每次训练完把results.csv里的metrics/mAP50曲线画出来看一眼。如果曲线在后期出现明显抖动说明学习率偏大或 batch 太小如果训练集 loss 还在降但验证集 loss 开始升就是过拟合该早停了。这些信号比最终那个 88.3% 的数字更有信息量。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站