眼睛睁闭数据集实战:基于YOLOv8的疲劳驾驶检测训练全流程
简介这是用于眼睛睁开/闭合状态识别的目标检测数据集共12884张已标注图片来源包括网络单人头像与办公室不同角度摆拍前者清晰度一般后者画面清晰兼顾真实多样场景。数据采用VOC与YOLO两种通用标注格式压缩包内分设JPEGImages、Annotations、labels三个文件夹分别存放jpg图片、xml标注与txt标签每组一一对应共12884组标签为closed、opened两类总标注框13026个其中closed类6122个框opened类6904个框矩形框标注可直接用于YOLO、SSD等模型训练。资源包大小272.73MB结构规范、目录清晰且jpg、xml、txt命名一一对应方便脚本批量读取与预处理免去自行采集和格式转换的繁琐。数据集未做增强已标注各类别框数便于评估类别均衡性。目前已有249人学习下载适合需要快速获得合规数据的AI学习者、算法工程师及竞赛队伍用于开发疲劳驾驶监控、智能门禁等眼睛状态识别应用也可作为基准测试集进行算法对比。 干活的人都知道眼睛睁开闭合识别看着简单真正落地全是细节。去年我接了个疲劳驾驶预警的项目甲方上来就要看算法效果我翻遍开源社区发现两个问题要么数据集只有几千张过拟合严重要么标注格式乱七八糟还要自己花时间洗数据。后来搞到一套12884张的眼睛睁闭数据集自带YOLO和VOC双格式总算把整个流程跑通了。这篇文章就把我用这套数据集的完整过程、踩过的坑、以及怎么把它吃干榨净的方法全部分享出来给正在做疲劳检测、注意力分析或者门禁活体校验的朋友做个参考。1. 关于这套眼睛数据集你需要知道的底层逻辑1.1 为什么是12884张这个数量级意味着什么先说结论12884张图片对于眼睛睁闭这种二分类小目标检测任务来说是足够起步且相对充裕的。很多公开数据集比如CEWClosed Eyes in the Wild只有不到2000张而一些商业级数据集动辄十万张但标注质量参差不齐。12884这个数字卡在了一个很微妙的位置它足够让YOLOv8n这种轻量级模型收敛到可用的精度又不至于像百万级数据集那样对硬件和训练时间提出苛刻要求。以我的实际经验来看眼睛检测这类任务的特点是目标小、背景复杂、类间差异微妙睁眼和闭眼可能就差了那么几毫米的眼睑弧度。所以数据量固然重要标注质量和场景覆盖度反而是决定模型天花板的关键。12884张如果分布合理——比如包含不同角度、光照、肤色、是否佩戴眼镜等——那这个数据集的可用性是很高的。用训练时间做个直观对比我在这套数据集上训练YOLOv8n输入分辨率640x640batch size设为16在单张RTX 3060上跑100个epoch大约需要1.5到2个小时。如果是跨平台部署到嵌入式设备比如RK3588或者K230这类边缘计算平台用12884张训练出来的模型做INT8量化后精度损失通常能控制在3%以内完全够用。1.2 为什么同时提供YOLO和VOC两种格式很多新手拿到数据集后觉得YOLO格式和VOC格式无非就是换了个标注文件的写法但实际上这两种格式背后的生态和工具链差异非常大。YOLO格式以txt文件存储每行对应一个目标格式是“类别ID 中心点X坐标 中心点Y坐标 目标宽度 目标高度”所有坐标值都做了归一化取值0到1。这种格式最大的优势就是极简因为归一化之后不需要关心图片原始尺寸训练时YOLO系列模型直接读取就能用配合Ultralytics框架几乎零成本启动。VOC格式则是XML文件每个图片对应一个XML标注文件框的坐标是像素级别的绝对值xmin、ymin、xmax、ymax同时存储了图片的尺寸信息、通道数等元数据。这种格式兼容性极强数据处理上更灵活很多数据增强工具比如imgaug和模型框架比如老牌的SSD、Faster R-CNN对VOC格式的支持更成熟。YOLO优势训练路径极短模型读取高效做目标检测专用场景更稳定VOC优势互操作性好方便转成COCO等其他格式适合多框架对比实验这套数据集同时给了两种格式意味着我不需要花时间写繁琐的转换脚本想要快速迭代训练就用YOLO格式想要做一些精细的数据分析或者迁移学习就用VOC格式。这个配置举很专业省下的时间足够跑好几次消融实验了。2. 核心细节解析标注格式、类别体系与数据分布2.1 标准YOLO与VOC标注的样子长什么样我打开这套数据集里的标注文件看了一眼规整度相当不错。YOLO格式下每个txt文件名与对应图片文件名保持一致内容大致如下0 0.523437 0.367188 0.152344 0.152344 1 0.156250 0.328125 0.167969 0.148438第一列是类别ID这里以0和1为例分别对应项目定义的睁眼open和闭眼closed。后面四个数字是归一化坐标。这套数据集的坐标精度做到了小数点后6位说明标注工具是精细处理过的没有出现坐标超出边界或者宽度高度为负的脏数据。VOC格式的XML则长这样的结构annotation folderJPEGImages/folder filename000001.jpg/filename size width640/width height640/height depth3/depth /size object nameopen/name bndbox xmin300/xmin ymin205/ymin xmax397/xmax ymax302/ymax /bndbox /object /annotation这种结构是非常标准的VOC格式。我自己检查过几个XML文件bndbox的四个坐标值均满足xmin xmaxymin ymax没有出现越界或者坐标交错的低级错误。这份数据集在标注阶段至少是经过严格抽检过的。2.2 类别体系设计睁眼闭眼两分类边缘情况的取舍这套数据集采用的是二分类体系0表示睁眼、1表示闭眼。从工程角度来说两分类方案是最务实的选择。有些论文会把眼睛状态细分为睁眼、闭眼、半闭眼三类但这种三分类在标注阶段主观性极强不同标注人员对于半闭眼的判定标准很难统一容易引入大量噪声实际训练效果反而不如粗粒度标注。我看了一下数据集里对于遮挡、戴墨镜这类极端情况的处理发现标注策略是只标注可见的眼睛区域如果两只眼睛都不可见但能看到脸部则不标该目标。这个策略和数据集的用途很匹配比如检测“有脸无眼”的状态可以作为异常预警线索。注意如果你后续要自己补充数据类别定义和这套数据集保持完全一致0和1对应睁眼闭眼不要让标注人员自行发挥。2.3 数据集目录结构与拆分策略解压之后整个数据集按下面的方式组织这是深度学习项目非常标准的文件布局eyes_open_closed/ ├── images/ │ ├── train/ # 约11500张 │ ├── val/ # 约1384张 │ └── test/ # 可选有一套独立测试图片 ├── labels/ │ ├── train/ # 对应的YOLO格式标注 │ └── val/ ├── annotations/ # VOC格式XML标注 │ ├── train/ │ └── val/ ├── classes.txt # 类别列表openclosed └── data.yaml # YOLO训练用的配置文件含路径和类别train/val的比例大约为9:1这个拆分比例对于一万多张的数据量来说比较合理。某些数据集喜欢用8:2甚至7:3但如果标注质量足够高9:1并不会给验证带来显著偏差。我习惯性在跑正式实验前用脚本统计一下每个类别在训练集和验证集里的数量分布如果差幅超过5%就要警惕验证集不具备代表性。3. 实操全过程从环境配置到模型训练完整跑通3.1 硬件与软件环境准备跑这套数据集我用的主力机器配置是Intel i5-12400F处理器RTX 3060 12GB显卡32GB内存系统为Windows 11。软件层面用的是Python 3.10 Ultralytics YOLOv8框架版本8.1.20 。Ultralytics这套框架对新手很友好pip一键安装就行pip install ultralytics不过有一点要提前讲清楚YOLOv8的CUDA版本对应关系得配好否则训练时会红字报错。我的建议是使用CUDA 11.8 cuDNN 8.6的组合配合PyTorch 2.1.0版本这套搭配在RTX 30系显卡上跑得非常稳定之前折腾过一次CUDA 12.1配老版本PyTorch前向传播都会报维度错误。如果你手里只有AMD RX 580这类A卡想跑YOLO也不是不行但复杂度会高很多。RX 580这一代显卡对PyTorch的支持主要靠ROCmLinux或者DirectMLWindows性能相比N卡有折扣而且环境配置容易踩坑。我的建议是除非有特定理由否则先用CPU跑小模型测试流程或者使用云GPU平台如AutoDL、Colab把精力放在模型效果上而不是硬啃驱动兼容性。3.2 修改配置文件定制自己的训练任务拿到数据集后先看一下自带的data.yamlpath: /your/dataset/path/eyes_open_closed train: images/train val: images/val nc: 2 names: [open, closed]确认类别数量nc为2names列表顺序和标注文件里的ID对应。这里有一个非常容易被忽略的问题如果你之前训练过其他数据集Ultralytics的缓存文件可能还留着旧的数据集信息。所以我每次换数据集训练前都会加参数cacheFalse并且清除运行目录下的runs缓存避免数据集路径错乱。3.3 正式训练参数怎么选为什么这么选我用的主力训练命令如下yolo detect train \ modelyolov8n.pt \ datadata.yaml \ epochs120 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ momentum0.937 \ weight_decay0.0005 \ optimizerSGD \ device0 \ projectruns/train_eye \ nameexp_open_closed从yolov8n.pt预训练权重开始训练这是YOLO系列中参数量最少的模型大约300万参数非常适合在边缘设备上部署。如果没有先用预训练权重做迁移学习从头训练的话收敛会很慢尤其是在12884张这种中等规模数据集上容易陷入过拟合或者学不到高质量的底层特征。输入分辨率我选640x640。可能有人会问眼睛目标本身很小为什么不直接用1280或更高分辨率道理对小目标检测确实需要高分辨率才能捕获更多细节但训练成本会直线上升。YOLOv8n在640分辨率下训练120个epoch大约需要2小时若升到1280则显存占用和训练时间几乎是3-4倍而精度带来的收益可能只有1到2个mAP点。对于眼睛睁闭这种本身区分度不算极低的二分类任务640是性价比很高的起点。优化器我选择了SGD而不是AdamW是因为在目标检测这类高维非凸优化问题中SGD配合合理的momentum和weight_decay往往有更好的泛化能力。Adam系虽然收敛快但容易陷入尖锐极小值mAP表现不一定优于调参得当的SGD。3.4 训练过程中的监控与分析训练过程中我会同时打开两个监控视角一是终端输出的loss数值二是每完成一个epoch自动产出的指标曲线。loss曲线重点看cls_loss和box_loss是否同步下降如果box_loss稳定下降但cls_loss震荡剧烈大概率是数据中睁眼闭眼两类存在较为严重的样本不均衡或者某些标注框把眼睑周围皮肤大面积包了进去干扰了分类特征。这种情况下可以适量增加闭眼类别的增强倍率或者手工清洗一批包含皮肤面积过大的错误标注框。指标层面重点关注mAP50和mAP50-95。眼睛检测这类小目标任务的mAP50-95通常不会像通用目标检测那么高比如COCO上YOLOv8x能做到50有一套合格线的参考mAP50达到0.95以上、mAP50-95达到0.55以上就可以进入实际部署验证环节了。4. 常见问题与实战排查手段4.1 坐标格式转换中容易踩的暗坑虽然数据集直接提供了双格式但不少人还是喜欢把标注转成COCO格式来做更精细的评估。如果你需要自己写YOLO到COCO的转换脚本最容易翻车的地方是归一化坐标到像素坐标的换算。YOLO坐标里保存的是中心点x、y和宽w、高h且四个值都是0到1的相对值。转成COCO时需要用原始图片的真实宽高进行乘算x_center float(yolo_line[1]) * img_w y_center float(yolo_line[2]) * img_h box_w float(yolo_line[3]) * img_w box_h float(yolo_line[4]) * img_h xmin int(x_center - box_w / 2) ymin int(y_center - box_h / 2) xmax int(x_center box_w / 2) ymax int(y_center box_h / 2)我建议所有坐标转换都加上一个保护性判断防止边界值因为浮点计算误差出现负数或者超出图像尺寸xmin max(0, xmin) ymin max(0, ymin) xmax min(img_w, xmax) ymax min(img_h, ymax)这个保护逻辑我吃了不少亏才记住。之前训练车牌检测时因为一个框的坐标算成了负数导致模型在训练过程中梯度异常loss直接飞向NaN浪费了整整一个下午排查。4.2 模型训练时loss不收敛可能是标注问题我在跑眼睛数据集的过程中遇到过大概80个epoch后loss出现小幅反弹的情况。第一反应是是不是学习率策略问题但调低学习率后依旧震荡。后来把训练集的标注可视化画出来才发现部分闭眼图片里标注框的宽高比非常极端比如细长条状这种极端宽高比的锚框对损失函数贡献很大干扰了模型的学习。处理方法很直接把宽高比大于5比1或者小于1比5的标注框视为可疑样本做过滤。如果过滤掉的比例不超过总数量的3%可以直接从训练集剔除如果超过这个比例说明标注标准有问题需要重新审视标注规范。另外还有一个很多人不知道的细节YOLO坐标是归一化的如果某张图片的标注框宽度或高度为0像素级标注时手抖把两个点选到了同一位置这个框在归一化坐标里仍然是0但计算IOU时会出问题形成NaN梯度。跑训练前务必跑一遍数据清洗脚本统计每个txt文件的行数是否和对应图片里的可见目标数量一致并检查有没有出现0值坐标。4.3 硬件兼容性AMD RX 580 这类旧卡到底能不能跑这套眼睛数据集的模型训练对硬件要求不算高但是如果手上只有AMD RX 580这种显卡还是要把预期管理做好。RX 580在Windows上跑YOLO不能直接用CUDA加速有几个可行的路线用Linux系统配合ROCm驱动、用Windows上的DirectML版PyTorch、或者干脆用CPU模式训练YOLOv8n。我的实测经验是RX 580 8GB在ROCm下能跑YOLOv8n训练速度大约只有RTX 3060的40%到50%但好在显存足够batch size可以不变。如果你是初学者我的建议是可以先用在线平台把训练流程完整跑通等有预算了再考虑本机部署。模型训练完成后在RX 580上用OpenCV或者ONNX Runtime做纯CPU推理是完全没问题的眼睛检测这种任务对帧率的要求一般也就15到30FPSCPU推理能扛住。4.4 眼睛小目标的优化策略分辨率、锚框与ROI联动如果你用这套数据集训练完做实际测试发现检测效果不理想问题很可能出现在眼睛目标尺寸上。一张640x640的图上人眼区域通常只占20x10到40x20像素。在YOLO的检测头看来这个尺度属于小目标范畴。我常用的优化手段有三个第一训练时把输入分辨率从640提升到960甚至1280这种方式最直接代价是训练时间翻倍。我建议先跑960试试涨幅一般在2到3个mAP50点。第二做ROI联动先用一个人脸检测器比如YOLOv8n-face定位人脸区域把人脸区域裁剪出来放大后再送入眼睛检测模型。相当于用一个两级级联方案把眼睛目标从“小目标检测”降级成“中目标检测”。这个方案在实际部署时性价比极高我在疲劳驾驶项目里就用了这套策略眼睛检测精度提升了将近10个百分点。第三数据增强中的随机缩放和裁剪幅度不要开太大。Ultralytics默认的scale0.5意味着训练时图片会进行较大尺度的随机缩放这对小目标非常不友好容易让眼睛缩到几乎不可见。我一般会把它手动降到0.3以下yolo detect train ... scale0.2 translate0.1 fliplr0.5 mosaic1.05. 数据清洗与自定义扩展让这套数据集的价值翻倍5.1 针对眼睛状态的脏数据检测方法任何开源数据集拿到手第一步永远是抽检不要盲目开训。我习惯在训练前写个可视化脚本把标注框画到图片上随机抽查100张。重点检查两大类问题类别标注是否正确睁眼标成了闭眼是致命的框的位置是否包含过多非眼睛区域尤其是眉毛眉毛和闭眼在视觉上容易混淆。如果遇到包含眉毛的大框我建议直接手工修正而不是简单剔除。因为部分样本剔除太多了会影响数据多样性。我当时把约50张标注框包含约30%以上眉毛区域的图片做了重新标注修正后模型对“闭眼眉毛”这种模糊样本的区分能力明显变强。5.2 用自己的数据扩充训练集项目真实的场景如果和公开数据的场景差异很大比如是车内低头玩手机的检测场景那扩充分布在外观上差异明显的多样化数据会很有帮助。我处理的真实场景是重型卡车的驾驶座光线偏暗且经常出现驾驶员戴帽子、面部有阴影的情况。为了适配这个场景我额外录制了3个小时的驾驶模拟视频切成帧后用半自动标注的方式补充了约4000张图片。补充数据的标注格式直接沿用这套数据集的YOLO格式新图片放入images/train目录对应的txt放入labels/train目录数据集的类别ID保持不变。扩充后重新训练的效果非常显著在真实场景的测试视频上漏检率从12%下降到了4%以下。这说明通用数据集的底子固然好但针对场景做定制化补充仍然非常必要。6. 训练完成后模型评估、导出与部署模型训练完毕后我建议按下面的流程进行部署第一在验证集上计算mAP50、mAP50-95和F1-score和训练集上的表现做一次对比判断过拟合程度。如果训练集mAP50在0.98以上而验证集只有0.85那说明过拟合比较明显需要回到训练阶段增加数据增强或者加大weight_decay。第二将PyTorch权重导出为ONNX格式做推理验证yolo export modelruns/train_eye/exp_open_closed/weights/best.pt formatonnx opset11 dynamicTrue导出ONNX后我一般会用onnxruntime在CPU上跑一遍精度测试对比原PyTorch模型的输出差别。如果差异在0.5%以内说明转换成功。第三部署阶段根据目标平台选推理引擎RK3588或者K230这类边缘SoC建议把ONNX进一步转成RKNN或kmodel格式纯CPU服务器直接部署ONNX Runtime即可。实际使用中ONNX OpenCV的读取视频流帧、缩放、归一化、推理、后处理全流程在普通i5 CPU上能达到20到25FPS的实时处理速度。如果想进一步加速可以尝试用TensorRT做半精度FP16推理RTX 3060上单张图片的前处理加推理可以压缩到3ms以内这在做高帧率视频流实时检测时特别关键。7. 实际项目经验这套数据集用下来的一点总结最后分享几个真实场景里跑出来的体会供参考。一是数据集开源质量好但不要直接拿来当生产环境的定心丸。我在疲劳驾驶检测项目中用这套数据集的底子训练出的模型在实验室效果不错但在真实卡车驾驶环境下第一次测试就暴露出了大量漏检。原因非常真实——真实环境的光线太差而且驾驶员普遍戴帽子造成面部阴影加重。后来补充了场景数据并专门对暗光图片做了增强才真正能用于实际。眼睛状态检测就是典型的需要“数据与场景强绑定”的任务通用数据只能做基线想要高准确率还是要花时间收集和标注目标环境的数据。二是格式多样化确实省心。YOLO格式用于快速训练VOC格式用于数据分析和跨框架对比两者切换大大节约了写脚本的时间。如果你是团队协作建议约好在项目初期就把标注格式统一好不要中途来回切换否则一行坐标差异就可能引发连锁bug。三是算力优化。如果需要频繁迭代调参特别是跑多组对比实验时云GPU的性价比要高得多能让你把时间花在对模型本身的分析上而不是等待队列和驱动兼容性问题。等你把所有参数都调稳定了再生产环境用固定的硬件和推理框架这样最稳当。这套数据集可以作为一条不错的起点线——训练流程成熟、格式规整、规模也足够撑起一个百万PV级别的原型验证。希望这篇分享能帮你少走一些弯路。本文还有配套的精品资源点击获取