ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLO疲劳驾驶检测数据集:5000张真实场景图片与VOC/COCO/YOLO标签实战

YOLO疲劳驾驶检测数据集:5000张真实场景图片与VOC/COCO/YOLO标签实战 简介本资源为面向目标检测学习者的YOLO疲劳驾驶数据集适用于驾驶员状态监测、智能座舱安全预警等场景可支撑YOLO系列模型的训练与验证。压缩包共2000个文件约389.57MB以1985个xml标注文件为主另含少量txt、html与py脚本分别对应标签数据、教程说明与数据集划分工具。所有图片均经labelimg标注标注框质量高并同步提供voc、coco和yolo三种格式标签分文件夹存放可直接接入主流检测框架。资源附赠环境搭建与训练案例教程覆盖Windows与Linux版本并配有训练集、验证集、测试集划分脚本可按需生成ImageSets索引文件。目前已有657人学习下载适合希望快速复现疲劳驾驶检测实验、节省数据清洗与格式转换时间的高校学生与算法入门者。1. 从 5000 张疲劳驾驶图片说起这套数据集到底解决什么问题疲劳驾驶检测这个方向很多人第一反应是「装个摄像头看眼睛闭不闭」真上手才发现难点根本不在模型而在数据。公开数据集里要么是实验室摆拍的正脸图要么是欧美驾驶员的面部特征直接拿来训 YOLO上车就翻车。这套「YOLO疲劳驾驶目标检测数据集」的价值就在于它把 5000 张真实驾驶场景图片、VOC/COCO/YOLO 三种格式标签、划分脚本和训练教程打包在一起省掉了从零标注和格式转换这两件最耗时的脏活。它适合三类人一是做车载 DMS驾驶员监控系统原型的嵌入式工程师需要快速验证 YOLO 在疲劳特征上的可行性二是赶毕设或课程设计的学生缺的就是一份能直接跑通的标注数据三是想拿疲劳检测练手 YOLOv8 目标检测流程的算法同学。核心检测目标通常是闭眼、打哈欠、低头、抽烟、打电话这几类疲劳或分心行为标注粒度是边界框而非关键点。下面从数据组织、格式转换、训练配置到踩坑按我实际跑过一遍的顺序讲清楚。2. 拆开压缩包5000 张图和三套标签怎么组织拿到一个 .rar 数据集最忌讳的就是解压完直接yolo train。先花十分钟把目录结构和标签格式摸清楚后面能省几小时排错。这一章讲清楚数据集的典型组织方式、三种标签格式的差异以及划分脚本到底在做什么。2.1 典型目录结构与文件命名规律这类打包数据集解压后常见结构大致是这样不同来源会有出入以实际为准fatigue_dataset/ ├── images/ # 5000 张 jpg/png 原图 │ ├── 000001.jpg │ └── ... ├── annotations_voc/ # VOC 格式 XML │ ├── 000001.xml │ └── ... ├── annotations_coco/ # COCO 格式 json │ └── instances.json ├── labels_yolo/ # YOLO 格式 txt │ ├── 000001.txt │ └── ... ├── classes.txt # 类别名列表 └── split_dataset.py # 划分脚本关键点是图片文件名和标签文件名必须一一对应除扩展名外完全一致。VOC 的 XML 里filename字段、YOLO 的 txt 文件名、COCO json 里的file_name三者指向同一张图。如果解压后发现命名对不上先写个脚本对齐别急着训练。classes.txt是类别的「字典」顺序决定 YOLO 标签里数字的含义。疲劳检测常见类别类似closed_eye open_eye yawn no_yawn phone smoke顺序一旦定了就不能改改了标签数字全错位。我一般会先cat classes.txt确认再去看几张 txt 标签验证。2.2 VOC、COCO、YOLO 三种标签的本质差异三种格式不是随便给的它们对应不同的训练框架和工具链。理解差异才能知道什么时候用哪个。格式存储形式坐标表示典型用途VOC每图一个 XML左上角右下角绝对像素 (xmin,ymin,xmax,ymax)老框架、labelImg 标注、部分检测库COCO单个大 json左上角宽高绝对像素 (x,y,w,h)MMDetection、Detectron2、COCO 评测YOLO每图一个 txt归一化中心点宽高 (cx,cy,w,h)取值 0~1Ultralytics YOLO 全系列最容易搞混的是 YOLO 的归一化坐标。它把绝对像素除以图片宽高得到 0~1 的小数。所以同一张图VOC 里写xmin320YOLO 里可能写0.5。转换时如果忘了除以宽高或者除错了维度宽除成高模型会学到一堆错框loss 死活降不下去——这就是典型的「玄学不收敛」来源之一。2.3 划分脚本在做什么train/val/test 的切分逻辑split_dataset.py干的事通常就三件读全部图片列表、按比例随机切分、把图片和对应标签复制或软链到train/val/test子目录。核心逻辑用 Python 复现一下import os, random, shutil random.seed(42) # 固定种子保证可复现 img_dir images out_dir dataset ratio (0.8, 0.1, 0.1) # train/val/test imgs [f for f in os.listdir(img_dir) if f.lower().endswith((.jpg, .png))] random.shuffle(imgs) n len(imgs) n_train, n_val int(n * ratio[0]), int(n * ratio[1]) splits { train: imgs[:n_train], val: imgs[n_train:n_train n_val], test: imgs[n_train n_val:], } for split, files in splits.items(): os.makedirs(f{out_dir}/{split}/images, exist_okTrue) os.makedirs(f{out_dir}/{split}/labels, exist_okTrue) for f in files: stem os.path.splitext(f)[0] shutil.copy(f{img_dir}/{f}, f{out_dir}/{split}/images/{f}) # YOLO 标签同名 txt shutil.copy(flabels_yolo/{stem}.txt, f{out_dir}/{split}/labels/{stem}.txt)逻辑说明random.seed(42)是后悔药固定种子后每次划分结果一致方便复现实验。ratio按 8:1:1 切疲劳检测样本如果某类极少比如抽烟要改成按类别分层抽样否则 val 里可能一张抽烟图都没有。参数上n_train用int()向下取整剩下的全给 test保证不丢图。提示划分前先统计每个类别的框数量如果某类少于 100 个框训练时大概率学不好考虑合并类别或补充数据。跑完脚本检查dataset/train/images和dataset/train/labels文件数是否相等不相等说明有图没标签训练时会报错或静默跳过。3. 把 VOC 和 COCO 转成 YOLO转换脚本与四个边界坑数据集虽然给了三种格式但真正喂给 YOLO 的只有 YOLO 格式。如果你手上只有 VOC 或 COCO或者想验证三种格式是否一致就得自己写转换。这一章给可直接抄的转换脚本并讲清楚转换时最容易翻车的四个边界情况。3.1 VOC XML 转 YOLO txt 的完整脚本VOC 转 YOLO 的核心是读 XML 拿到绝对坐标和图片尺寸归一化写成class cx cy w h。import os, xml.etree.ElementTree as ET from PIL import Image classes [closed_eye, open_eye, yawn, no_yawn, phone, smoke] cls2id {c: i for i, c in enumerate(classes)} def voc_to_yolo(xml_path, img_path, out_txt): tree ET.parse(xml_path) root tree.getroot() w, h Image.open(img_path).size # 用真实图片尺寸别信 XML 里的 size lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in cls2id: continue # 类别不在字典里跳过 bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 裁剪到图片范围内防止越界 xmin, ymin max(0, xmin), max(0, ymin) xmax, ymax min(w, xmax), min(h, ymax) cx (xmin xmax) / 2 / w cy (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls2id[name]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) with open(out_txt, w) as f: f.write(\n.join(lines))逻辑说明Image.open(img_path).size拿真实宽高因为有些 XML 里的size字段是标注工具随手填的和实际图片不符用错会导致坐标全偏。max(0,...)和min(w,...)是防越界标注时手抖把框拖出图片边界很常见不裁剪的话归一化后会出现负数或大于 1 的值YOLO 训练时直接报错。:.6f保留六位小数精度足够且文件不会太大。参数上classes列表必须和classes.txt完全一致顺序错了标签就错。如果 XML 里有difficult字段标记难样本可以加个判断跳过也可以保留——疲劳检测里闭眼样本本来就难我一般保留。3.2 COCO json 转 YOLO 的批量处理COCO 是单个大 json转换时要先建image_id - 文件名/宽高的映射再遍历 annotations。import json, os from PIL import Image with open(annotations_coco/instances.json) as f: coco json.load(f) img_info {im[id]: im for im in coco[images]} # COCO category_id 可能不连续建立到 0-based 的映射 cat_ids sorted(c[id] for c in coco[categories]) cat2id {cid: i for i, cid in enumerate(cat_ids)} os.makedirs(labels_yolo, exist_okTrue) for ann in coco[annotations]: im img_info[ann[image_id]] w, h im[width], im[height] x, y, bw, bh ann[bbox] # COCO 是左上角宽高 cx (x bw / 2) / w cy (y bh / 2) / h nw, nh bw / w, bh / h stem os.path.splitext(im[file_name])[0] with open(flabels_yolo/{stem}.txt, a) as f: f.write(f{cat2id[ann[category_id]]} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}\n)逻辑说明COCO 的bbox是[x, y, width, height]和 VOC 的[xmin,ymin,xmax,ymax]不同别搞混。cat2id做了一次重映射因为 COCO 的category_id经常从 1 开始且不连续而 YOLO 要求从 0 开始连续。用a追加模式写因为一张图可能有多个目标每个 annotation 追加一行。参数上im[width]和im[height]来自 COCO 的 images 字段通常可信但如果发现和实际图片不符还是以Image.open为准。3.3 四个必踩的边界坑坑一坐标越界。现象是训练启动就报Label format error或坐标大于 1。原因是标注框超出图片边界。解决转换时统一clip到[0, w]和[0, h]再归一化。坑二空标签文件。现象是某些图没有对应 txt或 txt 是空的。原因是该图没有目标或类别被过滤光了。解决YOLO 允许空 txt表示背景图但文件名必须存在。转换时即使没有目标也要生成空文件。坑三类别顺序错位。现象是模型把闭眼识别成打哈欠。原因是classes.txt顺序和转换脚本里的classes不一致。解决以classes.txt为唯一标准脚本里open(classes.txt).read().split()动态读取别硬编码。坑四图片和标签不同名。现象是训练时提示找不到标签。原因是图片是001.jpg标签是001.JPG.txt或img_001.txt。解决转换后写个校验脚本遍历 images 检查同名 txt 是否存在。注意转换完务必抽查 5~10 张图用可视化脚本把框画回原图看一眼比任何日志都直观。4. 用 YOLOv8 跑通第一轮训练配置、参数与验证数据准备好了接下来是训练。这一章以 Ultralytics YOLOv8 为例YOLOv5 流程类似讲清楚 data.yaml 怎么写、关键参数怎么设、训练完怎么验证。疲劳检测属于小目标细粒度场景参数不能照搬 COCO 默认值。4.1 data.yaml 的写法与路径陷阱YOLOv8 靠一个 yaml 文件告诉它数据在哪、有几类。path: /home/user/dataset # 数据集根目录绝对路径最稳 train: train/images val: val/images test: test/images nc: 6 names: 0: closed_eye 1: open_eye 2: yawn 3: no_yawn 4: phone 5: smoke逻辑说明path是根train/val/test是相对path的子路径。很多人翻车在路径上——写成相对当前工作目录结果训练时找不到图。我一般用绝对路径一劳永逸。nc是类别数必须和names长度一致不一致直接报错。names的顺序就是标签数字的含义和classes.txt对齐。参数上如果只有 train/val 没 test把test那行删掉即可不影响训练。4.2 关键训练参数为什么不能照搬默认值启动命令yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ device0逐个说参数。modelyolov8n.pt是预训练权重n 是最小模型疲劳检测如果部署在车机或边缘设备n 或 s 够用追求精度上 m/l。imgsz640是输入尺寸疲劳特征闭眼、哈欠在图中占比小尺寸太小会丢细节640 是平衡点显存够可以上 960。batch16看显存V100 上可以拉到 32 甚至 64。lr00.01是初始学习率YOLOv8 默认 0.01如果 loss 震荡厉害降到 0.001。patience20是早停20 轮没提升就停省时间。疲劳检测的特殊之处闭眼和睁眼是细粒度区分模型容易混淆。我一般会把imgsz调大、epochs拉到 150 以上并开启数据增强里的mosaic和mixupYOLOv8 默认开 mosaic。如果某类样本少用copy_paste增强。4.3 训练过程看什么loss、mAP 和混淆矩阵训练启动后终端会打印每轮的 box_loss、cls_loss、mAP50、mAP50-95。重点看三个box_loss持续下降说明框回归在学如果一直不降检查标签坐标是否归一化正确。cls_loss下降慢或震荡说明类别难分考虑加数据或调大模型。mAP50是 IoU0.5 时的平均精度疲劳检测能到 0.85 以上算不错mAP50-95 更严格通常低 10~20 个点。训练完在runs/detect/train/下有confusion_matrix.png。这里有个热词里提到的坑——YOLO 混淆矩阵总和不唯一。原因是混淆矩阵的行列归一化方式不同有的按预测归一化有的按真实归一化导致总和看起来对不上。别慌看对角线占比就行对角线越深越好。如果闭眼和睁眼在对角线外有明显值说明这两类混淆严重得针对性补数据。验证命令yolo detect val modelruns/detect/train/weights/best.pt datadata.yaml会输出每类的 P、R、mAP。重点看闭眼类的召回率 R疲劳检测漏检比误检更危险R 低就要降低置信度阈值。提示训练前先用yolo detect train ... epochs1跑一轮确认数据加载没问题再正式训避免训了几小时才发现路径错。5. 避坑与排查训练不收敛、BN 崩溃、显存爆了怎么办这一章是我踩过的坑合集每条按「现象 → 原因 → 解决」写。疲劳检测数据集不大问题往往出在数据和配置上而不是模型本身。现象一训练几个 epoch 后 loss 变 NaNBN 层崩溃。热词里「yolo训练中bn崩溃」说的就是这个。原因通常是学习率太大、batch 太小导致 BatchNorm 统计量不稳或者数据里有异常值坐标越界、图片损坏。解决先把lr0降到 0.001batch尽量调大至少 8检查标签是否有 NaN 或越界值。如果还崩换modelyolov8s.pt或加warmup_epochs5让学习率预热。现象二mAP 一直卡在 0.3 上不去。原因可能是类别不平衡比如抽烟样本只有几十个模型直接摆烂全预测多数类。解决统计每类框数对少样本类做过采样或复制粘贴增强或者干脆合并相似类比如 yawn 和 no_yawn 如果区分度低就合并。现象三训练报 CUDA out of memory。原因是batch或imgsz太大。解决按显存阶梯降先降 batch 到 8再降 imgsz 到 416。也可以用ampTrueYOLOv8 默认开混合精度省显存。V100 16G 上跑 yolov8n 640 batch16 基本没问题跑 m 模型就得降。现象四验证集 mAP 高但实际推理漏检严重。原因是训练集和验证集分布太像同一批视频抽帧模型过拟合。解决划分时按视频或按人分层别让同一个人既在 train 又在 val。这是疲劳检测最隐蔽的坑指标好看但上车就废。现象五推理时框抖动、闪烁。原因是单帧检测没有时序信息闭眼睁眼在相邻帧跳变。解决加简单的时序平滑比如连续 3 帧都检测到闭眼才判定疲劳或者用跟踪算法ByteTrack关联目标。这属于后处理不改模型也能明显改善体验。6. 从能跑到好用提升疲劳检测精度的一个具体技巧训练跑通只是起点真正上车或交付精度和稳定性才是门槛。这一章讲一个我反复验证有效的技巧针对疲劳特征的锚框重聚类 分层采样以及怎么验证它真的有用。YOLOv8 虽然是无锚框anchor-free的但如果你用的是 YOLOv5 或带锚框的变体默认锚框是按 COCO 聚类的对疲劳检测这种「小框密集」场景并不最优。做法是用 k-means 对自己的标注框重新聚类import numpy as np def kmeans_anchors(wh, k9, iters100): # wh: Nx2 的宽高数组归一化后 idx np.random.choice(len(wh), k, replaceFalse) centers wh[idx] for _ in range(iters): d np.abs(wh[:, None] - centers[None]).sum(-1) # 简化的 L1 距离 labels d.argmin(1) for i in range(k): if (labels i).any(): centers[i] wh[labels i].mean(0) return centers[np.argsort(centers[:, 0])] # 读取所有 YOLO 标签的 w h wh [] for line in open(all_labels.txt): _, _, _, w, h line.split() wh.append([float(w), float(h)]) anchors kmeans_anchors(np.array(wh), k9) print(anchors)逻辑说明把每张图所有框的归一化宽高收集起来用 k-means 聚成 9 组得到最适合本数据集的锚框尺寸。疲劳检测的框普遍偏小眼睛、嘴巴区域聚类出来的锚框会比 COCO 默认值小一圈。参数k9对应 3 个尺度各 3 个锚框iters100足够收敛。分层采样则是保证每个 batch 里各类别都有。YOLOv8 没有直接的分层采样接口但可以在划分数据时按类别分层让 train/val 的类别分布一致。验证方法很简单训练两个模型一个用默认配置一个用重聚类锚框分层采样对比验证集上闭眼类的召回率。我实测下来闭眼召回率能提升 3~5 个点别小看这几个点漏检一次可能就是一次事故。最后说个习惯每次改完数据或参数先跑 10 个 epoch 看 loss 曲线趋势别一上来就 300 epoch。趋势不对早停比硬训省时间。疲劳检测这行数据质量永远比模型结构重要5000 张标注干净的图胜过 5 万张脏数据。希望帮到你。本文还有配套的精品资源点击获取
返回列表