DMS疲劳驾驶数据集与YOLO训练部署全流程解析

📅 2026/8/27 3:43:46
DMS疲劳驾驶数据集与YOLO训练部署全流程解析
简介驾驶员监控系统DMS是智能座舱与自动驾驶安全的关键技术其核心依靠计算机视觉目标检测算法实时感知驾驶员状态。YOLO作为高效的目标检测框架在疲劳驾驶检测、安全带识别、打哈欠检测等细分任务中展现出极强的工程落地价值。基于深度学习的目标检测原理DMS系统通过标注数据训练模型准确识别驾驶员的多种行为状态从而为疲劳预警、分心提醒等应用提供可靠依据。在实际部署过程中数据集的标注质量、类别分布、训练参数以及模型压缩都直接影响最终效果。本文以一套8511张图像、覆盖六类标签的DMS疲劳驾驶数据集为切入点详细拆解从数据检查、YOLO格式转换、训练调参、评测指标到边缘设备部署的完整流程并针对类别不均衡、域偏移、遮挡等真实场景问题给出实用建议为从事驾驶员监控与目标检测的开发者提供可直接参考的工程实践路径。 做DMS相关项目这几年最头疼的往往不是算法本身而是数据。YOLO模型结构再熟训练技巧再多没有一套覆盖真实驾驶员状态的数据集一切等于空转。最近我在整理疲劳驾驶检测方案时重新过了一遍手上这套DMS疲劳驾驶员数据集8511张图像、带完整标签类别涵盖没系安全带、正常清醒、昏昏欲睡、系安全带、打电话、打哈欠基本覆盖了DMS系统在座舱内要抓的核心事件。这篇文章我就以这套数据为切入点把DMS场景下YOLO算法的落地全流程拆开讲讲数据怎么检查、怎么转换成YOLO格式、训练参数怎么调、模型评测看哪些指标、部署时又容易在哪些地方翻车。不管你是刚接触驾驶员监控系统的新手还是已经在做目标检测但想切入DMS方向的开发者这篇内容应该都能给你一些实际可用的参考。1. DMS场景为什么需要专门的疲劳驾驶数据集1.1 DMS系统的业务边界DMS全称Driver Monitoring System从名字就能看出来它监控的不是车外的道路而是车内驾驶员的状态。国内外的法规和评价体系比如E-NCAP、C-NCAP对驾驶员监控的要求越来越明确车要实时知道驾驶员是不是在专注开车有没有疲劳、分心、没系安全带等行为。这套系统落地到视觉算法层面核心就是目标检测加状态分类。摄像头通常装在方向盘管柱、仪表盘或者A柱位置视角固定拍摄驾驶员的面部、上半身以及安全带区域。算法要做的就是在连续的视频帧中稳定输出驾驶员当前的状态是清醒还是困倦有没有打哈欠手是不是在打电话安全带有没有系好。这套数据集里的六个标签——唤醒、昏昏欲睡、打哈欠、电话、安全带、没有安全带正好对应了DMS功能的两条主线疲劳状态识别和分心/合规行为识别。1.2 座舱场景与通用检测场景的差异在COCO、VOC这类通用数据集上训练出来的YOLO模型直接搬到DMS场景里效果往往不理想。原因很直接视觉环境和目标特征完全不同。通用检测里模型要面对的是开放世界目标种类多、尺度变化大、背景复杂而DMS是典型的固定场景摄像头位置固定视野范围小目标类别少但每个类别的细节差异非常关键。比如打哈欠和张嘴说话在通用检测里可能无所谓在DMS里却是两种完全不同的状态安全带是一条斜跨胸前的带状目标和通用的领带肩带类目标在语义上完全不搭。另一个关键差异是数据分布。通用数据集追求类别均衡DMS场景里正常清醒的帧数远远多于打哈欠和打电话的帧数。如果直接用原始分布训练模型很容易偏向多数类导致疲劳、分心这些关键小类别的召回率很低。这套8511张图像的数据集虽然不算特别大但胜在类别覆盖完整拿到手之后要做的一项重要工作就是类别分布分析再根据分布情况决定采样策略或损失函数调整方案。1.3 疲劳检测的算法本质是序列问题但检测是基础严格的疲劳检测很多团队最终会走向时序模型比如用LSTM、Transformer或者滑动窗口统计眨眼频率、PERCLOS眼睛闭合时间比例。但所有时序分析的前提是单帧检测足够准。连单帧图像里的眼睛闭合打哈欠都检测不出来时序模块拿到的基本特征就是错的后面算出的PERCLOS毫无意义。所以用YOLO处理DMS任务第一步是做好单帧检测准确定位驾驶员、定位面部区域、识别安全带状态、识别手持电话、识别哈欠状态。这套8511张带标签图像的核心价值就在于每张图已经标注好了这些单帧事件可以用它直接训练YOLO检测头再接入时序状态机完成从单帧事件到疲劳状态的判断。2. 数据集拆解类别分布与标注质量直接决定模型上限2.1 六个标注类别与DMS功能的映射关系先看这套数据的类别很多人拿到手后第一反应是直接训练其实应该先做一步类别和业务含义的映射这会直接影响后面怎么用。标注类别标签名对应DMS业务唤醒awake正常驾驶状态注意力集中昏昏欲睡drowsy疲劳状态眼皮低垂、频繁眨眼后闭眼等打哈欠yawn疲劳/困倦的强信号行为电话phone分心驾驶行为手持有手机或贴近耳朵安全带seatbelt驾驶员正确佩戴安全带没有安全带no_seatbelt安全带未系或佩戴错误这里要特别留意唤醒和昏昏欲睡这类状态标签它们不是传统的矩形框目标而是整张图像或驾驶员区域的状态属性。而安全带没有安全带是互斥的同一目标区域电话则是相对较小的手持物体。所以训练时不能简单地把六个类别全部扔进同一套检测管线需要区分哪些是目标检测任务定位框哪些是图像分类/状态属性。在实操中处理这套数据有两种思路。第一种是把所有标签都视为检测框但前提是原始标注里对昏昏欲睡这类状态也标注了框比如框住驾驶员面部或上半身第二种是把安全带状态和疲劳状态拆成两个任务——一个目标检测模型负责输出驾驶员位置、面部、手机、嘴部状态框另一个分类分支或状态分析模块综合判断清醒还是困倦。我建议拿到数据后先画一个可视化脚本检查每类标注框的位置和范围再决定用哪种思路。2.2 目录结构与标注格式解析压缩包解压后典型的组织方式包含images文件夹和labels文件夹对应YOLO训练的标准目录结构。labels里每个txt文件和图像同名每行记录一个标注框五个数值依次是类别id、归一化中心x坐标、归一化中心y坐标、归一化框宽、归一化框高。dataset/ ├── images/ │ ├── 000001.jpg │ ├── 000002.jpg │ └── ... ├── labels/ │ ├── 000001.txt │ ├── 000002.txt │ └── ... └── classes.txt单张图像的标注内容类似这样# 000001.txt 0 0.502341 0.418326 0.284911 0.235433 1 0.644212 0.531908 0.118447 0.146802 3 0.512033 0.446290 0.241823 0.183311拿到标注文件之后我建议先做三件事第一统计每个类别的图像数量看看存在不存在极端不均衡第二随机抽几十张图把标注框画回原图人工检查框的位置有没有偏移、类别和图像内容是否匹配第三检查有没有空标注文件这类文件一般对应的是无目标帧如果数量过多要考虑是否用于负样本训练。2.3 标注质量的常见问题与检查手段标注质量可以说直接决定了模型上限。框的边界差几个像素对模型精度的影响很小但类别标错、漏标、框线完全偏离目标这些问题是致命的。我习惯写一个简单的检查脚本用Python的OpenCV把YOLO格式的标注框画回原图人工快速浏览一批比直接盯着txt文件看效率高太多。下面是我常用的检查逻辑import cv2 import os def draw_yolo_boxes(image_path, label_path, class_names): img cv2.imread(image_path) h, w img.shape[:2] with open(label_path, r) as f: lines f.readlines() for line in lines: parts line.strip().split() if len(parts) ! 5: continue cls_id, xc_norm, yc_norm, bw_norm, bh_norm map(float, parts) xc, yc xc_norm * w, yc_norm * h bw, bh bw_norm * w, bh_norm * h x1, y1 int(xc - bw/2), int(yc - bh/2) x2, y2 int(xc bw/2), int(yc bh/2) label class_names[int(cls_id)] cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, label, (x1, max(0, y1-8)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) return img class_names [awake, drowsy, yawn, phone, seatbelt, no_seatbelt] # 随机抽20张图检查检查的时候重点看两类问题一是没有安全带和安全带这两个类别是否标注在了真正的安全带区域还是随便框了一个上身区域二是打哈欠和昏昏欲睡这类状态标签的标注位置是否一致有的标注员习惯框嘴部有的习惯框整张脸这会导致模型学到的特征完全不同训练前必须统一。3. YOLO训练DMS识别模型从环境到配置3.1 训练环境与依赖训练YOLO模型当前最省事的路子是Ultralytics YOLOv8或者YOLOv11这套代码库它对工程化很友好训练、验证、导出一条龙。Python环境建议3.9以上PyTorch按你的显卡CUDA版本装然后用pip安装ultralytics包就能直接把训练跑起来。pip install ultralytics硬件上我自己的经验是DMS数据集图像通常分辨率在1280x720或1920x1080左右8511张图的数据量不算大一张显存12GB以上的消费级显卡比如RTX 3060/4070以上就足够跑yolov8m或者yolov8l了。如果是入门级的6GB显存建议用yolov8n或者把图像尺寸调小到640x640。训练时间上单卡RTX 4090跑yolov8m、100个epoch、8511张图大概3到5小时能跑完。3.2 数据划分与格式准备在动手训练之前需要把全部数据按比例切分。常规做法是训练集、验证集、测试集按8:1:1或者9:0.5:0.5划分。这里有一个DMS场景特有的注意事项如果数据的采集来自多个不同的驾驶员或时间段划分的时候最好按视频片段或者人员分组来切不要把同一个人的连续帧同时分进训练集和验证集否则验证集里会出现和训练集高度相似的帧指标虚高模型换个人就拉胯。Ultralytics的YOLO格式目录如下datasets/DMS/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yaml是数据集配置内容很直白path: /path/to/datasets/DMS train: images/train val: images/val nc: 6 names: 0: awake 1: drowsy 2: yawn 3: phone 4: seatbelt 5: no_seatbelt3.3 DMS场景下的训练参数选择YOLOv8的训练参数里有几个对DMS场景尤其关键。图像尺寸imgsz。这是第一个要重点调的参数。DMS画面里安全带和手机都算中小目标如果直接把图像resize到640x640安全带这类细长目标可能只占几十个像素检测难度很大。我的做法是先看原始图像分辨率和标注框的像素分布如果安全带框的像素宽度在原始图上还不错可以把imgsz设置为960或者1280。代价是训练速度和显存占用上升但对精度提升通常很可观。epochs。DMS这种小数据集100到150个epoch就足够了。不要一上来就填300个epoch很容易过拟合。配合早停策略如果验证集上的指标连续30个epoch没有提升训练会自动停止。batch size。显存允许的情况下尽量大。DMS数据类别不均衡较大的batch能让每个batch里更有可能出现少数类样本打哈欠、打电话梯度更新会更稳定。数据增强参数。这里要特别注意。Ultralytics默认开启的mosaic增强在DMS场景下可能帮倒忙。mosaic会把四张图拼在一起产生大量不自然的图像拼接痕迹而DMS是固定座舱场景训练时过度使用mosaic会让模型对真实场景的分布产生偏差。我一般在后期把mosaic关掉close_mosaic10意思是最后10个epoch关闭mosaic或者直接把mosaic概率调低。下面是我在一个类似项目里用过的训练命令可以直接参考yolo train \ modelyolov8m.pt \ datadatasets/DMS/data.yaml \ imgsz960 \ epochs120 \ batch16 \ close_mosaic10 \ patience30 \ projectruns/DMS \ nameexp_20243.4 类别不均衡的应对策略DMS数据集的类别不均衡问题很突出。正常清醒awake可能占了一半以上的标注而打哈欠yawn、打电话phone可能只有几百张。对这个问题的处理我按优先级用过三种方案。方案一过采样少数类。在数据加载层面将包含打哈欠、打电话标注的图像重复若干轮使每个epoch里少数类出现的次数更多。Ultralytics没有直接提供按类别采样的参数但可以在数据划分之前手动复制部分少数类样本到训练集里或者写一个自定义Dataset。方案二损失函数加权。给少数类更高的损失权重让模型在训练时更重视这些类别的分类正确性。Ultralytics目前对类别权重没有开放直接参数需要修改损失计算代码适合有一定代码能力的人操作。方案三最简单也最有效——重新审视任务设计。打哈欠检测本质上可以改成嘴部状态分类任务。先用检测模型定位驾驶员脸部然后从脸部区域裁剪出嘴部区域用一个分类小模型判断是否打哈欠。把目标检测任务转换成两步走类别不均衡的问题会变得好处理很多。这套思路在DMS项目里非常实用建议认真考虑。4. 训练完别急着收工DMS模型评测的关键指标4.1 mAP不能说明一切很多新手拿到测试集mAP 0.9就觉得模型已经可以上线了在DMS项目中这是最要命的误判。mAP是综合所有类别、所有IoU阈值下的平均精度它对类别不均衡的数据不敏感。举个例子如果清醒占了数据的70%模型哪怕把打哈欠打电话全部漏掉只要清醒检测得够准mAP依然可以很高。DMS场景应该重点看每类别的recall召回率和F1-score尤其是对昏昏欲睡和打哈欠这两个疲劳信号类别。漏检一次打哈欠可能就意味着一次疲劳驾驶状态没有被上报这种错误的代价远高于把说话误检成打哈欠。我的习惯是训练完立即跑一遍验证集输出每个类别的详细指标yolo val \ modelruns/DMS/exp_2024/weights/best.pt \ datadatasets/DMS/data.yaml \ batch16Ultralytics的验证结果里会输出一个confusion_matrix.png这个是必看的。看混淆矩阵的时候重点看两个地方一是打哈欠和唤醒之间有没有严重混淆二是安全带和没有安全带这两类之间有没有误分。这两组混淆是DMS模型最常见的失效模式。4.2 置信度阈值的选取有了验证结果另一个常被忽略的问题是置信度阈值的设定。检测模型输出的是框和类别概率判断到底算不算一个事件需要一个阈值。阈值调高误报少但漏报多阈值调低漏报少但误报多。DMS报警机制本身有持续帧数确认的机制单帧误报不算严重。所以我一般在DMS场景会把置信度阈值压得偏低比如0.25到0.35用帧间滤波来消化误报。实际操作时可以画一条置信度-召回率曲线找一个召回率开始出现明显下降的拐点作为阈值而不是拍脑袋选0.5。4.3 连续视频帧的时序评测除了看静态指标能跑一段真实或模拟驾驶视频做时序评测比任何指标都更有说服力。我把已经训练好的模型接上视频推理人工观察几个场景驾驶员正常驾驶时模型是否能连续稳定输出清醒状态驾驶员频繁打哈欠时打哈欠事件是否连续帧都能检出来驾驶员从清醒慢慢变成困倦的过渡过程模型输出有没有剧烈抖动。这里我提供一个很直观的测试方法。找一段驾驶员疲劳驾驶的录像用模型逐帧推理在输出帧上叠加检测框和类别标签生成一段标注后的视频然后人工回看yolo predict \ modelruns/DMS/exp_2024/weights/best.pt \ sourcedemo_road_test.mp4 \ imgsz960 \ conf0.3 \ saveTrue回放的时候重点关注模型在驾驶员转头、低头、光线突然变化这些边界情况下的表现。这些场景在训练集里可能很少但实际驾车时很常见。5. DMS模型部署的边界情况5.1 不同摄像头的域差异训练集里的图像如果来自某一种特定的工业相机颜色、亮度、对比度、视角都有特定风格换到另一个品牌的DMS摄像头上效果可能明显掉点。这是典型的域偏移问题domain shift也是DMS项目里很容易忽略的一环。商用DMS摄像头通常是红外摄像头拍摄的图像整体色调偏暗、对比度偏低有些干脆是灰度图。如果训练集里有大量RGB彩色图像部署阶段的画面风格就会不匹配。我能给的建议是训练时加入一部分灰度化和亮度扰动的数据增强让模型对光照变化更鲁棒如果条件允许用目标摄像头的样机采集少量数据微调一小轮模型。5.2 遮挡、人脸角度与眼镜DMS场景里驾驶员戴墨镜、戴口罩、歪头、低头看后视镜、用手遮挡面部这些都是常见情况。眼镜会遮挡眼部区域导致昏昏欲睡这类依赖眼部状态的检测失效口罩会让打哈欠的嘴部特征被遮住。针对这些情况我通常采用多特征融合的兜底策略。检测昏昏欲睡时除了眼睛闭合特征还要融合头部姿态点头和面部整体状态特征检测打哈欠时如果嘴部被遮住可以捕捉肩部耸动、脸部肌肉动作等替代特征。用YOLO做单帧检测时就需要在训练集里尽可能补充这些遮挡样本。这套8511张的数据集如果没有覆盖这些corner case部署时一定要针对性采集补充。5.3 模型压缩与边缘设备部署DMS产品最终大概率要跑在车规级芯片上比如高通8155/8295、地平线征程系列、NVIDIA Jetson Orin、安霸CV系列等。这些平台的算力有限不可能像训练时那样用FP32的yolov8m或yolov8l跑实时视频流。常规做法是导出成TensorRT或者ONNX再转成特定芯片格式并使用FP16或INT8量化。这一环节有几个经验值得分享第一INT8量化需要校准数据集建议从训练集中挑300到500张覆盖各类别的图来校准不要随便选第二对打哈欠这类小目标INT8量化后的精度损失可能明显大于安全带这类大目标量化后要用单独的视频片段评估第三导出时把图像预处理缩放、归一化尽量融入模型或芯片的预处理模块减少主机端CPU开销。best.pt导出成TensorRT FP16的命令很简单yolo export modelbest.pt formatengine imgsz960 halfTrue6. 我在实际项目中的几个建议6.1 先跑通小模型再堆大模型不少做算法的人习惯一上来就训练yolov8x觉得自己显卡好用最猛的模型总能得到最好的结果。DMS这个场景有点特殊它的目标类别少、场景固定yolov8n或者yolov8s的基线水平可能比想象中好很多。而且DMS最终要在嵌入式设备上跑先从小模型开始把训练、验证、部署的完整链路跑通再根据精度缺口决定是否升级模型这是更务实的路径。6.2 别忽视数据集的连续性训练如果手头有历史模型训练新数据集时可以考虑直接用历史模型的weights作为预训练权重而不是每次都从头用COCO预训练权重起步。DMS场景有较强的域特征历史模型已经见过大量座舱内图像微调的收敛速度和最终精度通常都更好。6.3 标注是值得投入时间的基础设施在这套数据集上训练之前多花点时间做标注质量检查这部分时间永远值得。每类标签的框风格统一了训练出来的模型才会稳定。如果你刚拿到这套8511张图像的数据集我会用这样的顺序推进先可视化抽查一批标注确认类和框都符合预期然后统计数据分布判断是否需要过采样少数类接着用yolov8s加imgsz960跑一个快速基线最后根据验证集的混淆矩阵决定优化方向。这套流程走通之后再考虑大模型、量化部署和高难度的corner case优化。做DMS项目做得久了我最大的体会是它是个安全相关的系统对漏报的容忍度极低这决定了我们在数据、训练、评测、部署每一个环节都不能只盯着好看的数字。数据集的完整性、模型的鲁棒性、部署后的边界表现每一项都值得较真。希望这篇内容能给正在做或者准备做DMS方向的你一些切实的帮助。本文还有配套的精品资源点击获取