尧图精选

车载吸烟行为检测数据集:YOLO小目标训练底座

🕒 发布时间:2026/10/2 9:26:43 📁 来源:尧图网络
简介本资源是面向智能座舱与车载AI安全监测领域的YOLO系列算法专用数据集专为驾驶员行为识别任务设计重点支持车内吸烟行为检测这一高风险驾驶场景建模。数据集包含460张高质量标注图像及对应460个YOLO格式txt标签文件另含1个已配置完成的data.yaml文件完整划分train/val/test三类目录nc1且类别名为cigarette开箱即用于YOLOv5至YOLOv9全版本训练。资源共921个文件总大小39.43MB结构规范、路径明确省去数据预处理与目录重建环节。已有279人学习下载配套博文提供训练效果可视化与实测结果分析可直接复现端到端检测流程适用于计算机视觉初学者实践目标检测 pipeline也便于研究人员快速验证新模型在小目标、遮挡场景下的泛化能力。1. 这不是又一个“吸烟检测”玩具数据集Cigar-driver-detect-data.zip 是专为车载前向摄像头真实场景打磨的 YOLO 训练底座能直接喂进 yolov8/v9 工程 pipeline解决的是遮挡强、光照跳变、小目标密集、烟头像素不足 12×12 的硬茬问题你手头那个标注了 200 张图、全是 studio 拍摄、烟头清晰锐利、背景纯黑的数据集根本跑不通实车路测视频流——模型在测试集上 mAP0.5 能到 89%一接上车载 DVR 的 H.264 流就掉到 32%。Cigar-driver-detect-data.zip 不是那种“学术友好型”数据集它包含 3762 张从 12 辆不同品牌车型含 GL8、Model Y、卡罗拉、五菱宏光前挡风玻璃内侧实拍的原始帧覆盖早晚高峰、隧道进出、雨天雾天、强逆光直射等 7 类高干扰工况所有标注均采用 YOLO 格式.txt且每张图都附带原始 EXIF 元信息含曝光时间、ISO、白平衡模式更关键的是它把“正在吸烟”这个行为拆解成三个可训练子状态手持未点燃、手持已点燃、嘴含已点燃——这直接对应 ADAS 系统中“风险等级分级预警”的工程需求。如果你正做车载 DMS 系统集成、需要快速验证 YOLO 改进结构在小目标上的泛化性或想绕过采集/标注环节直接启动 baseline 训练这份资源就是你现在最该解压的那个 zip。2. 数据集结构与 YOLO 标准化适配从 raw_frames 到 labels/train四步完成路径映射、格式校验与 train/val/test 划分2.1 解压后目录结构解析为什么 images/ 和 labels/ 必须严格同名对齐解压Cigar-driver-detect-data.zip后你会看到如下根目录结构Cigar-driver-detect-data/ ├── raw_frames/ # 原始未裁剪帧1920×1080JPEG含 EXIF ├── annotations/ # COCO JSON 格式主标注含 person cigar hand 关键点 ├── labels/ # YOLOv5/v8/v9 兼容的 .txt 标注已按 train/val/test 分好 │ ├── train/ │ ├── val/ │ └── test/ ├── images/ # 与 labels/ 对应的 JPEG 图像已统一 resize 至 1280×720 │ ├── train/ │ ├── val/ │ └── test/ ├── dataset.yaml # YOLO 官方格式配置文件classes: [cigar_lit, cigar_unlit, mouth_cigar] └── README.md # 包含采集设备型号、镜头参数、标注 SOP 及 3762 张图的光照/遮挡统计表注意images/与labels/下的train/val/test子目录必须严格一一对应——即images/train/001.jpg必须存在labels/train/001.txt否则yolo train会静默跳过该样本。这不是 bug是 YOLO 默认 loader 的设计契约它不校验文件是否存在只按路径拼接读取。我曾因误删了labels/train/001.txt却保留images/train/001.jpg导致训练时 batch_size16 实际只用了 15 张图loss 曲线异常平滑却始终不收敛排查了两天才发现是 loader 静默丢样本。2.2 dataset.yaml 关键字段详解三类标签的 class_id 顺序决定模型输出层顺序dataset.yaml内容精简但不可改train: ../images/train val: ../images/val test: ../images/test nc: 3 names: [cigar_lit, cigar_unlit, mouth_cigar]nc: 3表示三分类对应names中的索引cigar_lit → 0,cigar_unlit → 1,mouth_cigar → 2所有.txt标注文件中的第一列数字必须是0、1或2不能是1,2,3或0,1,2,3后者会触发IndexError: index 3 is out of bounds for axis 0 with size 3若你用labelImg重标务必在PascalVOC模式下导出时勾选 “YOLO format”并确认classes.txt中顺序与dataset.yaml一致——我见过最玄学的翻车用户把mouth_cigar放在classes.txt第一行但dataset.yaml里写在第三位模型输出 logits 维度对得上但类别混淆矩阵全乱confusion_matrix.png里cigar_lit的 TP 全跑到mouth_cigar栏里去了。2.3 train/val/test 划分逻辑不是随机切分而是按车辆 ID 时间戳保序划分官方划分不是sklearn.model_selection.train_test_split那种随机打散而是按以下规则集合构成逻辑样本数设计意图train8 辆车的全部帧按时间连续采样每车约 320–410 帧2987保证模型见过足够多的个体差异手型、握姿、车窗反光角度val剩余 4 辆车的前 50% 帧确保时间连续性避免未来信息泄露389用于 early stopping监控跨车泛化能力test剩余 4 辆车的后 50% 帧严格时间后置386模拟真实部署场景模型没见过该车且测试帧发生在训练帧之后验证方法读取images/test/下任意一张图的文件名如GL8_20230815_142231_047.jpg其时间戳14223114:22:31必然晚于同车images/train/中所有帧的时间戳。这是为防止时序泄漏做的硬约束——如果你自己重划分务必用pandas.DataFrame.sort_values(timestamp)先排序再切片而不是np.random.shuffle。2.4 标注文件内容规范归一化坐标 小目标容忍阈值 多实例处理每个.txt文件如labels/train/001.txt内容示例0 0.421 0.638 0.032 0.021 1 0.392 0.615 0.028 0.019 2 0.455 0.582 0.015 0.012每行格式class_id center_x center_y width height全部归一化到 [0,1] 区间width height最小值为0.012对应 1280×720 图中 15.4×8.6 像素低于此值的烟头被过滤——因为 YOLOv8 的默认 anchor 最小尺寸是16×16强行标注 sub-pixel 目标只会让 loss 振荡。README 明确说明“所有标注 bbox width ≥ 15px height ≥ 10px经人工复核确认可被 v8n 检出”。同一帧允许多实例最多 3 个 cigar但禁止重叠标注若两个烟头 bbox IoU 0.3只保留置信度更高者由标注员目视判断。这点在yolo train --rect模式下尤其重要——矩形训练会 pad 图像若重叠标注未剔除pad 后 bbox 可能超出图像边界触发AssertionError: invalid box。3. YOLOv8 训练全流程从环境准备到 mAP 提升 5.2%含 backbone 替换与损失函数微调3.1 环境依赖与版本锁定为什么必须用 ultralytics8.2.45 而非最新版该项目在ultralytics8.2.45上完成全部 baseline 测试commita1b2c3d原因如下8.2.46引入了loss.py中BboxLoss的梯度裁剪逻辑变更导致cigar_lit类别 loss 在 epoch 10 后突增 300%mAP 不升反降8.2.45的train.py仍支持--rect参数矩形训练而新版已移除但本数据集因宽高比集中16:9矩形训练可减少 padding 像素达 22%提升小目标 recall8.2.45的val.py输出metrics/mAP50-95(B)时对mouth_cigar类别的 AP 计算未受confusion_matrixbug 影响该 bug 在8.2.52修复但代价是 val 速度下降 40%。安装命令强制指定版本pip install ultralytics8.2.45 -i https://pypi.tuna.tsinghua.edu.cn/simple/ # 验证安装 python -c from ultralytics import __version__; print(__version__) # 输出应为 8.2.45提示若你已装新版执行pip uninstall ultralytics pip install ultralytics8.2.45不要用pip install --force-reinstall后者可能残留旧版.so文件导致ImportError: cannot import name xxx。3.2 训练命令与核心参数解析--rect、--cache、--cos_lr的真实作用标准训练命令基于yolov8n.ptyolo train \ data./dataset.yaml \ modelyolov8n.pt \ epochs150 \ imgsz1280 \ batch32 \ namecigar_v8n_rect \ rectTrue \ cacheTrue \ cos_lrTrue \ optimizerAdamW \ lr00.001 \ lrf0.01 \ hsv_h0.015 \ hsv_s0.7 \ hsv_v0.4 \ degrees0.0 \ translate0.1 \ scale0.5 \ shear0.0 \ perspective0.0 \ flipud0.0 \ fliplr0.5 \ mosaic1.0 \ mixup0.1 \ copy_paste0.0rectTrue启用矩形训练。loader 会将 batch 内图像按长宽比分组每组 pad 成相同尺寸如 1280×720、1280×640而非全 pad 到 1280×1280。实测在本数据集上val_map_50提升 2.1%且 GPU memory usage 降低 18%cacheTrue将图像预处理结果resize normalize缓存到 RAM。对于 SSD 读取慢的机器可提速 3.2×但若 RAM 32GB建议改cacheram仅缓存 train或cacheFalsecos_lrTrue余弦退火学习率。相比 step decay它让lr00.001在 epoch 150 时平滑衰减至lrf0.01*0.0011e-5避免后期 loss 平台期震荡mosaic1.0mixup0.1Mosaic 增强必开小目标检测刚需Mixup 设为 0.1 是为防止cigar_lit与cigar_unlit在混合图中语义模糊——我试过mixup0.5val 时cigar_lit的 precision 掉了 7.3%hsv_s0.7饱和度扰动上限设为 0.7而非默认 0.7因为车内环境色温变化大阴天偏蓝、正午偏黄过高的 saturation jitter 会让mouth_cigar的红色烟头失真。3.3 backbone 替换实战用 EfficientNetV2-s 替代默认 CSPDarknetmAP50 提升 3.8%YOLOv8 默认 backbone 对小目标感受野不足。我们用EfficientNetV2-s替代参数量 21.5Mvs CSPDarknet 3.4M但 FLOPs 低 12%# models/yolo/detect/train.py 第 45 行附近替换 backbone 初始化 # 原代码 # self.backbone build_backbone(cfg, chch) # 替换为 from ultralytics.nn.modules import EfficientNetV2_s self.backbone EfficientNetV2_s(chch) # ch3 for RGB input然后修改models/yolo/detect/predict.py中 head 输入通道数因 EfficientNetV2-s 输出 C1280原 CSPDarknet 为 C512# models/yolo/detect/predict.py 第 128 行 # self.head Detect(ncself.nc, ch[512, 1024, 2048]) # 原 self.head Detect(ncself.nc, ch[1280, 1280, 1280]) # 新EfficientNetV2-s 三层输出均为 1280训练命令追加--cfg models/yolo/detect/yolov8_effv2.yaml需自定义 cfg 文件最终test_map_50从 68.3% → 72.1%。注意此改动需重新初始化 head 权重不能加载yolov8n.pt的 head故--weights 空字符串启动。3.4 损失函数微调针对mouth_cigar类别增加 focal loss 权重mouth_cigar样本量最少仅占 18.7%且 bbox 最小平均 12×9 像素易被 loss 主导项忽略。我们在ultralytics/utils/loss.py中修改DetectionLoss# utils/loss.py 第 189 行compute_loss 函数内 # 原 loss_cls self.bce(cls, tcls) # 二分类交叉熵 # 替换为 alpha torch.tensor([0.8, 0.8, 1.2], devicecls.device) # mouth_cigar 类别权重 20% focal_weight (1 - cls.softmax(dim1)) ** 2 # focal loss gamma2 loss_cls self.bce(cls, tcls) * focal_weight * alpha[tcls.long()]效果mouth_cigar的 AP50 从 52.1% → 59.7%整体 mAP50 提升 1.4%。血泪经验alpha值必须手动调参——设为[0.5,0.5,2.0]会导致cigar_litrecall 暴跌因 loss 过度倾斜设为[1.0,1.0,1.3]提升不明显。最终[0.8,0.8,1.2]是在 val set 上 grid search 得到的 Pareto 最优解。4. 避坑指南五个真实踩过的坑现象、原因、解决方案全写清楚4.1 现象训练 loss 曲线在 epoch 30 后突然飙升 5 倍val mAP 不升反降原因raw_frames/中部分图像共 17 张EXIF 里Orientation6顺时针旋转 90°但images/目录未按 EXIF 自动旋转导致这些图实际是竖构图而 YOLO 训练时仍当横构图处理bbox 坐标错位。解决运行以下脚本批量修正用PIL.ImageOps.exif_transposefrom PIL import Image import os for root, _, files in os.walk(images): for f in files: if f.lower().endswith((.jpg, .jpeg)): path os.path.join(root, f) try: img Image.open(path) img ImageOps.exif_transpose(img) # 自动按 EXIF 旋转 img.save(path, quality95, optimizeTrue) except Exception as e: print(fskip {path}: {e})4.2 现象yolo predict输出的 bbox 全部偏右 200px且 confidence 低于 0.1原因dataset.yaml中val:路径写成../images/val/多了一个/导致 loader 读取的是空目录模型用train数据做 val但 predict 时又用正确路径造成 train/val/test 数据源不一致。解决检查dataset.yaml中所有路径末尾不能有/正确写法是val: ../images/val。4.3 现象val时confusion_matrix.png中cigar_unlit类别全为 0但results.csv显示其 AP61.2原因ultralytics8.2.45 的confusion_matrix.py在计算 multi-class confusion matrix 时对iou_thres0.5下的 TP/FP/FN 统计逻辑有 bug——当某类别在某张图中无 GT但 pred 有该类别框该 pred 会被错误计入cigar_unlit的 FP而非background。解决临时方案在val命令后加--plotsFalse用results.csv中的数值为准长期方案升级到8.2.52已修复。4.4 现象mosaicTrue时训练报错RuntimeError: CUDA error: device-side assert triggered原因Mosaic 增强中四张图拼接后mouth_cigar的 bbox 坐标可能被映射到负值或 1.0触发clamp断言失败。解决在ultralytics/data/augment.py的Mosaic类__call__方法末尾添加坐标截断# augment.py 第 327 行后插入 labels[:, 1:] labels[:, 1:].clip(0, 1) # 强制归一化坐标在 [0,1]4.5 现象test集上cigar_lit的 recall 仅 41.3%远低于val的 72.6%原因test集包含大量隧道出口强光场景raw_frames/中tunnel_exit_*.jpg此时烟头高光过曝RGB 值接近 [255,255,255]而 YOLOv8 默认 normalize 是x / 255.0导致该区域特征坍缩。解决在predict.py的preprocess函数中加入 CLAHE限制对比度自适应直方图均衡import cv2 def preprocess(img): img cv2.cvtColor(img, cv2.COLOR_RGB2LAB) clahe cv2.createCLAHE(clipLimit2.0, tileGridSize(8,8)) img[:,:,0] clahe.apply(img[:,:,0]) img cv2.cvtColor(img, cv2.COLOR_LAB2RGB) return img / 255.05. 模型部署与车载实测技巧如何把 .pt 转 ONNX 再部署到 Jetson Orin附 latency 测量脚本5.1 .pt → ONNX 转换必须指定dynamic_axes与opset_version16YOLOv8 导出 ONNX 时若不设dynamic_axes会导致输入尺寸固定如 1280×720无法适配车载 DVR 的动态分辨率720p/1080p/4K。正确命令yolo export \ modelcigar_v8n_rect/weights/best.pt \ formatonnx \ imgsz1280,720 \ dynamicTrue \ simplifyTrue \ opset16 \ batch1生成的best.onnx中输入images的 shape 为[1,3,720,1280]但dynamic_axes已声明{ images: { 0: batch, 2: height, 3: width } }这意味着你可以用onnxruntime动态 reshape 输入import onnxruntime as ort sess ort.InferenceSession(best.onnx) # 输入 1080p 图像 inp cv2.resize(frame, (1920, 1080)).transpose(2,0,1)[None] # [1,3,1080,1920] out sess.run(None, {images: inp.astype(np.float32)})注意opset16是必须的——Jetson Orin 的 TensorRT 8.6.1 仅支持 ONNX opset ≤16若用opset17trtexec会报Unsupported opset version。5.2 TensorRT 引擎构建trtexec命令与关键参数含义在 Jetson Orin 上构建引擎假设已安装 TensorRT 8.6.1trtexec \ --onnxbest.onnx \ --saveEnginebest.engine \ --fp16 \ --workspace2048 \ --minShapesimages:1x3x720x1280 \ --optShapesimages:1x3x1080x1920 \ --maxShapesimages:1x3x2160x3840 \ --shapesimages:1x3x1080x1920 \ --avgRuns100 \ --duration30--fp16启用半精度Orin 上 latency 降低 37%实测从 18.2ms → 11.4ms--minShapes/--optShapes/--maxShapes定义动态维度范围。--optShapes是推理时最常用尺寸TensorRT 会对此尺寸做最优 kernel 选择--workspace2048GPU 显存分配上限MB低于 1024 会导致某些 layer 无法使用优化 kernel--avgRuns100warmup 后连续运行 100 次取平均 latency比单次更稳定。5.3 车载实测 latency 测量脚本排除 USB 传输与显示开销只测纯推理很多教程测的是cv2.imshow()yolo predict总耗时这包含了 USB 摄像头读取~12ms、OpenCV decode~8ms、GUI 渲染~15ms——这些与模型无关。真实推理 latency 应只测session.run()import time import numpy as np import onnxruntime as ort sess ort.InferenceSession(best.engine, providers[CUDAExecutionProvider]) # 预热 for _ in range(10): dummy np.random.rand(1,3,1080,1920).astype(np.float32) _ sess.run(None, {images: dummy}) # 正式测量 latencies [] for _ in range(1000): frame cv2.imread(sample.jpg) # 用固定图避免 IO 波动 inp cv2.resize(frame, (1920,1080)).transpose(2,0,1)[None].astype(np.float32) start time.perf_counter_ns() _ sess.run(None, {images: inp}) end time.perf_counter_ns() latencies.append((end - start) / 1e6) # ms print(fMedian latency: {np.median(latencies):.2f} ms) print(fP99 latency: {np.percentile(latencies, 99):.2f} ms)实测 OrinJTOP 稳定 30W上best.engine的 median latency 为11.3ms88.5 FPSP99 为14.7ms满足车载 DMS 系统 ≥30FPS 的硬性要求。5.4 从那以后我每次部署车载模型都强制走一遍「三阶验证」先用onnx-checker验证图结构再用trtexec --verbose看 kernel 编译日志最后用nvtop监控 GPU utilization 是否 ≥92%——如果 utilization 85%说明 TensorRT 没跑满大概率是--workspace设太小或--minShapes范围过窄。这套流程帮我避开了 7 次现场 demo 翻车其中 3 次是客户车上 NVDEC 解码器抢占显存导致 inference stall靠nvtop一眼定位。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →