资讯详情

资讯详情

DMS安全驾驶数据集:从YOLO标签体检到TensorRT部署的完整指南

简介面向汽车安全驾驶与分心行为识别场景这份DMS安全驾驶数据集提供了9728张带标签图像覆盖吸烟、未系安全带、使用手机等典型危险动作可支撑驾驶员状态监测、违规预警等模型的训练与验证。数据已按训练集、验证集和测试集划分并内置适用于YOLOv5、YOLOv7、YOLOv8、YOLOv9、YOLOv10及YOLO11等模型的data.yaml配置文件下载后无需额外整理即可直接训练和测试。压缩包共2000个xml标注文件其中YOLO txt标签与VOC xml标签分目录存放便于在不同训练框架间切换YOLO格式中类别索引从0开始目标中心点与宽高坐标均以图像尺寸归一化可直接被YOLO系列读取VOC格式则便于用通用工具查看和修改。整体大小约240.88MB目录结构清晰定位明确。目前已有86人学习下载适合有一定目标检测基础、需要真实驾驶场景数据快速验证算法效果的研发人员也可作为课程设计或算法对比实验的基准数据集。1. DMS安全驾驶数据集是什么为什么标注比模型更值钱做商用车主动安全和网约车合规监管时最耗时间的往往不是YOLO算法本身而是带标签的DMS安全驾驶数据。这套DMS安全驾驶数据集一共9728张图像标签集中在香烟、安全带、电话三类每张图都带对应的YOLO格式txt标签解压后就能直接丢进训练脚本。它解决的是起步阶段最现实的问题你不用先花两周趴在监控视频里画框可以先拿它把检测pipeline、训练参数和部署流程完整跑通。适合两类人一类是做ADAS/DMS算法的工程师想快速验证YOLO在驾驶员行为识别上的效果另一类是准备自建标注产线需要一个基准数据集做验收对照。提醒一句这套数据能直接训练但直接拿去做全场景部署夜间和遮挡会先给你上一课。2. 先过一遍标签DMS三类的YOLO格式长什么样怎么体检9728张图听起来不少但DMS场景有个特点同一个司机连续几十帧长得几乎一样姿态、光照变化都很小。如果不体检直接训练你会遇到“loss降得漂亮一上实车全是误检”。所以拿到zip的第一步不是写训练脚本而是把标签完整读一遍。2.1 拆包后先看这三样标签格式、文件对应、类别编号先把包解开看清楚目录长什么样。我一般会建一个纯英文目录来解压避免后面训练时路径里带中文或空格出幺蛾子。unzip -q 数据集.zip -d dms_work cd dms_work find . -maxdepth 2 -type d | sort ls images | head -3 cat classes.txt如果包内是images和labels两个平铺目录那么每张jpg对应一个同名txt如果还有子目录先按上面find的结果理清层级。classes.txt里一般按行写着smoking、seatbelt、phone注意行号就是类别idtxt文件里的第一列就是它。YOLO格式每行5个数class_id x_center y_center width height坐标全部归一化到0-1。一个高频疑问是“coco80怎么读”这种COCO80是COCO数据集的80类和这个包没有关系它只有3个自定义类id从0开始排不是从1。想确认就打印一个标签文件cat labels/000001.txt看到类似0 0.52 0.31 0.14 0.12就说明格式正常。这里要强调的是DMS的类别口径不是“物体”而是“行为状态”同一帧司机手里拿着烟这个框可能标成smoking安全带框是细长条标注的是带子本身。类别id一旦理解错后面data.yaml里names顺序跟着错整个训练就白给。2.2 用OpenCV把标签画回图上空标签和越界框一查便知格式看完了下一步是把框画回图上肉眼扫一遍。这个步骤能发现程序读不出来的问题标签路径对不上、类别id越界、坐标超过1.0。import cv2, glob, os os.makedirs(check, exist_okTrue) class_colors [(0, 0, 255), (0, 255, 0), (255, 0, 0)] for img_path in sorted(glob.glob(images/*.jpg))[:30]: img cv2.imread(img_path) if img is None: print(read fail:, img_path) continue h, w img.shape[:2] disp cv2.resize(img, (960, int(h * 960 / w))) sx, sy 960 / w, int(h * 960 / w) / h label_path img_path.replace(images, labels).replace(.jpg, .txt) if not os.path.exists(label_path): print([missing label], img_path) continue for line in open(label_path): cid, cx, cy, bw, bh map(float, line.split()) if not (0 cx 1 and 0 cy 1 and 0 bw 1 and 0 bh 1): print([invalid box], label_path, line.strip()) continue x1 int((cx - bw / 2) * sx) y1 int((cy - bh / 2) * sy) x2 int((cx bw / 2) * sx) y2 int((cy bh / 2) * sy) cv2.rectangle(disp, (x1, y1), (x2, y2), class_colors[int(cid) % 3], 2) cv2.putText(disp, str(int(cid)), (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, class_colors[int(cid) % 3], 1) cv2.imwrite(check/ os.path.basename(img_path), disp)这段脚本把归一化坐标乘回显示尺寸转成像素坐标画框同时在框左上角写类别id。print里的invalid box判断是重点id不在0-2、cx/cy不在0-1、宽高不在0-1的框全部打印出来。这些非法框在训练时要么被忽略要么被数据增强裁剪掉是后面“标签没问题但指标不对”的常见来源。安全带这类目标又细又长人工标注时很容易把框拉出图像边界越界部分归一化后超过1.0训练时就被yolov8内部过滤了。2.3 按司机的行驶片段划分数据集不要随机划分很多人的惯例是把9728张图按比例随机一split就开训这在DMS数据上是错的。DMS视频里同一个司机相邻帧几乎一模一样随机划分会让val集里全是train的“孪生帧”val指标虚高部署时才现原形。划分之前先统计类别分布和空标签率import numpy as np from glob import glob label_paths sorted(glob(labels/*.txt)) counts np.zeros(3, dtypeint) empty 0 for p in label_paths: lines open(p).read().strip().splitlines() if len(lines) 0: empty 1 continue for line in lines: cid int(line.split()[0]) if cid 3: counts[cid] 1 print(class totals:, counts) print(empty label rate: %.2f%% % (100.0 * empty / len(label_paths)))跑完先看三类数量差多远。如果某一类只有几百张后面要针对它做增强或过采样。划分时按视频片段切而不是按单帧随机切常见的做法是70%司机做train15%做val15%做test同一辆车主机的连续帧始终进同一个集合。如果数据包里没有车主id字段就按文件名前缀或者时间戳聚类来分实在分不出来就用文件名排序后按块切。test集必须严格留到最后所有调参、早停、选模型都在val上做最后用test算一次终版指标。3. 让YOLO训练起来目录改造、data.yaml与三组关键参数标签体检完接下来把这套DMS数据改造成YOLO训练工程。这里以ultralytics YOLO为例因为它是目前把自定义数据集训练做得最省事的工具链。重点不在命令本身而在目录结构和names顺序这两个翻车点。3.1 目录改造成ultralytics能直接吃的形状ultralytics默认约定的数据集结构是images和labels平行下面再按train/val/test分目录。先建目录再把上一步划分好的文件复制进去。mkdir -p dms_yolo/images/{train,val,test} mkdir -p dms_yolo/labels/{train,val,test}import shutil, os from sklearn.model_selection import train_test_split names [os.path.splitext(f)[0] for f in os.listdir(images) if f.endswith(.jpg)] train_names, test_names train_test_split(names, test_size0.15, random_state42) train_names, val_names train_test_split(train_names, test_size0.15 / 0.85, random_state42) for split, subset in [(train, train_names), (val, val_names), (test, test_names)]: for n in subset: shutil.copy(fimages/{n}.jpg, fdms_yolo/images/{split}/) shutil.copy(flabels/{n}.txt, fdms_yolo/labels/{split}/)这里用sklearn做两次切分第一刀切出test第二刀在剩余85%里切val。注意文件名必须一一对应labels目录里不能出现没有对应jpg的txt反之亦然。一个常见问题是用shell的cp *.jpg和cp *.txt分开复制结果图片和标签数量对不上训练时大量warning。复制完后检查一遍数量三个split下jpg和txt数量必须严格一致。3.2 data.yaml里的path与names错一个就全部学歪data.yaml是整个训练里最容易出错的文件而且错了不一定报错而是模型学出一个“看起来收敛但完全没法用”的结果。path: ./dms_yolo train: images/train val: images/val test: images/test names: 0: smoking 1: seatbelt 2: phone先解释path它写的是数据集根目录train和val是相对path的相对路径。names的key顺序就是标签txt里的class_id这一点必须和类别定义严格对齐。如果原始标签里0是phone这里就必须写0: phone否则模型会把所有电话框当成香烟去学。还有个细节nc类别数可以不写ultralytics会自动根据names的长度推断。但names的key必须是从0开始的连续整数不能跳号否则内部映射会错位。我见过一个翻车案例names里写了1、2、3三个key训练正常跑完但val时mAP全部为0因为标签里的0号类根本没有对应名字。3.3 训练命令怎么下imgsz、batch、epochs先按这套来目录和配置就绪训练命令本身反而不复杂。下面是我在DMS这类小目标、细长目标数据集上常用的起点yolo train datadms.yaml modelyolov8s.pt \ imgsz640 batch16 epochs100 seed42 \ optimizerAdamW lr00.001 patience10 \ mosaic1.0 close_mosaic10参数逐个说清楚方便你按自己机器改参数建议值理由imgsz640和部署分辨率保持一致不要用1280训练再用640部署两套尺寸会引入精度损失batch16T4或4090够用显存小的降到8配合AMP半精度训练epochs100DMS数据量小一般40-70轮就能收敛后面靠早停兜底optimizerAdamW小数据集上比SGD收敛稳lr0用0.001起步seed42不固定seed后面换参数对比就没法归因mosaic1.0close_mosaic10前90轮开mosaic提升小目标召回最后10轮关掉防止过拟合训练中断也不用从头来ultralytics支持断点续跑yolo train resumeTrue它会自动找到runs/detect/train目录下最近的权重继续。这里提醒一句resume会沿用中断时的所有超参数你改了data.yaml或者换模型resume不会生效必须先删除原训练目录或换一个新的project/name。4. 训练后的DMS指标怎么读mAP之外要看误检和细长框训练结束后终端会打出一行指标很多人只看mAP50就收工了。但DMS场景里mAP50是远远不够的误检率和细长目标的定位质量才是部署时真正肉疼的地方。4.1 看P、R、mAP50重点看AP50而非AP50-95先跑一遍val把指标固化下来yolo val modelruns/detect/train/weights/best.pt datadms.yaml输出里主要看四个数含义和参考范围如下指标含义DMS场景参考说明Precision检出的框里有多少是真正目标0.85以上误报会直接触发合规告警宁高勿低Recall真实目标里有多少被检出0.80左右漏检在夜间场景容易崩单独看夜间子集mAP50IoU阈值0.5下的平均精度0.85以上DMS框通常稀疏AP50比AP50-95更能反映落地效果mAP50-95多IoU阈值的综合精度0.60以上就够对细长框和遮挡目标过于苛刻DMS的框大多是小目标电话、香烟和极端长宽比目标安全带mAP50-95被这些框拉低是正常的。如果一个模型mAP50-95只有0.55但mAP50有0.88在DMS场景里完全可以用不要为了刷高那个0.95去换大模型部署成本不划算。4.2 安全带框是长条电话框是小目标分开看混淆矩阵val输出里会生成混淆矩阵图但图只能看整体我把标签统计脚本再跑一遍按类别看宽高比分布import numpy as np from glob import glob ratios {0: [], 1: [], 2: []} for p in sorted(glob(dms_yolo/labels/train/*.txt)): for line in open(p): cid, cx, cy, w, h map(float, line.split()) if cid in ratios and h 0: ratios[cid].append(w / h) for cid, name in [(0, smoking), (1, seatbelt), (2, phone)]: arr np.array(ratios[cid]) print(f{name}: median w/h{np.median(arr):.2f}, p95{np.percentile(arr, 95):.2f})如果seatbelt的宽高比中位数大于3说明这个类里绝大多数是长条框默认锚框对它不友好。遇到这种情况开autoanchor让YOLO根据真值重新聚类锚框yolo train datadms.yaml modelyolov8s.pt imgsz640 autoanchorTrueautoanchor通常能把mAP50拉高1-2个点代价是训练轮数稍长。另外提醒一句DMS是水平框场景别拿mmrotate那套旋转框思路来处理安全带DMS摄像头视角下安全带就是斜长条水平框完全够用旋转框只会把标注和部署复杂度拉高。4.3 loss曲线、过拟合信号和夜间数据增强的加码顺序训练日志目录下的results.png里画了train/val的box_loss和cls_loss曲线。读法很直接如果train loss一直降、val loss先降后升就是过拟合如果train和val的loss都在降但val的P/R波动大通常是val集划分方式不对回到第2章按片段重切。DMS数据几乎必然面临夜间样本不足。白天样本占多数时模型会倾向把低光照区域的框全部漏掉。加夜间增强时按这个顺序来不要一上来就叠mixupyolo train datadms.yaml modelyolov8s.pt \ hsv_h0.015 hsv_s0.7 hsv_v0.5 degrees5 \ flipud0.0 fliplr0.5先加亮度对比度扰动hsv_v再加轻微旋转degrees最后才考虑mixup。DMS场景里司机的脸被翻转后语义还在但方向盘仪表盘的位置关系会被破坏所以flipud保持0。夜间不足的根本解法是补数据增强只是让模型在测试集上不那么难看而已。5. 做DMS数据集的常见问题排查5个坑从zip解压到夜间漏检这一章把做DMS数据集时最常踩的5个坑按“现象-原因-解决”写清楚每个都是真实发生过的问题。5.1 zip解压后中文目录乱码标签读到一半全部丢现象训练时大量image not found或标签文件打不开检查发现images目录下文件数对但txt文件数量少了三分之一。原因zip包内中文文件名在Windows下用GBK编码压缩Linux下解压默认按UTF-8解析文件名变成乱码程序按乱码路径找不到标签。解决解压时指定编码并检查文件数是否对齐。unzip -O gbk 数据集.zip -d dms_work find dms_work -name *.txt | wc -l如果文件数对不上再试jar xf或把zip拷到Windows下用解压软件解一次。这一步的验收标准只有一个jpg数量和txt数量完全相等且每个txt都有对应的同名jpg。5.2 标签编号和data.yaml的names顺序不一致模型全学错现象训练loss正常下降val的mAP却是0或者奇低draw混淆矩阵发现预测类别永远偏向某一类。原因包内的类别编号和data.yaml的names顺序对不上比如原始标签里0是phone但yaml里把0写成了smoking模型拿“电话”的框去学“香烟”的特征越学越歪。解决先读包内自带的类别定义文件再写data.yaml。cat classes.txt包内如果有classes.txt就以它为准没有就找标签txt里出现过的最大id加1就是类别数。names顺序必须和这个文件逐行对应这是整个DMS训练里优先级最高的一条检查。5.3 安全带这类细长框被阈值裁掉训练时坐标越界现象训练日志出现大量WARNING ⚠️ invalid boxval阶段安全带召回率明显低于电话。原因安全带框宽度极窄归一化后可能只有0.01量级输出层量化后容易被过滤还有一部分标注框超出图像边界归一化后宽或高大于1。解决训练前跑一遍标签清洗脚本把越界框直接删掉或裁剪到边界内。def sanitize(label_path): out [] for line in open(label_path): cid, cx, cy, w, h map(float, line.split()) if 0 cx 1 and 0 cy 1 and 0 w 1 and 0 h 1: out.append(line) if len(out) len(open(label_path).read().strip().splitlines()): with open(label_path, w) as f: f.writelines(out)清洗后重新跑一遍2.2的可视化脚本确认没有误删正常框。细长框的另一个解法是训练时把imgsz从640提到800或960让安全带在图上占更多像素但部署端分辨率就得跟着改属于涨点换延迟的取舍。5.4 夜间样本只有白天的零头白天mAP500.82、夜间0.25现象val的整体mAP50在0.75左右按时间段拆开看白天0.8夜间0.2。原因数据集采集时段偏白天夜间、黄昏、隧道场景样本严重不足模型的增强里亮度扰动幅度还不够。解决先统计夜间比例再分层增强。标注文件里没有时间戳的话按图像亮度均值粗筛import cv2, glob, numpy as np dark_files [] for p in glob.glob(dms_yolo/images/train/*.jpg): gray cv2.imread(p, cv2.IMREAD_GRAYSCALE) if gray is not None and gray.mean() 80: dark_files.append(p) print(dark rate: %.2f%% % (100.0 * len(dark_files) / len(glob.glob(dms_yolo/images/train/*.jpg))))夜间不足时把hsv_v加大到0.7并额外加高斯噪声模拟传感器暗光噪点。这一步能缓解症状但替代不了夜间数据。如果这个数据集是给产线用的我一般会把它当预训练起点再补至少2000张目标车型的夜间图来做二次微调。5.5 单人单视角的数据做跨车型泛化验证集刷分虚高现象val指标很好换到另一款车上部署召回掉一半。原因DMS摄像头通常装在A柱或方向盘正上方角度固定但不同车型座椅高度、仪表台形状、方向盘遮挡都不一样。数据包如果采自单一车型或单一车主模型学到的是“这个司机的姿态”不是“驾驶员行为”的通用特征。解决划分val/test时按车主或车型分组不要按单帧随机切。条件允许的话val里放一个完全没见过的司机视频mAP50掉5个点以上是正常的这才是有参考价值的评估。部署前还可以做一次车道级路测专门收集不同车型的误检案例回灌训练集。6. 部署前的性价比验证用TensorRT在T4上推640分辨率模型在val上看得过去下一步是看它能不能在T4这类边缘推理卡上扛住产线流量。先把权重转成TensorRT engineyolo export modelruns/detect/train/weights/best.pt formatengine device0 halfTrue imgsz640halfTrue打开FP16DMS这类三分类检测任务FP16精度损失基本可以忽略延迟能降一半左右。转完后用trtexec拿真实延迟trtexec --loadEnginebest.engine --shapesimages:1x3x640x640 --warmUp500 --streams1读输出的End-to-End Host Latency的P99值。这里回答一个常被问的问题T4上用TensorRT推640分辨率YOLO1080p25帧每秒的视频流能支持多少路按我的经验yolov8s的FP16 engine单帧P99大概在8-15ms如果要求每路25帧全帧检测单卡只能跑2-3路这个结果会让很多人失望。但DMS场景根本不需要25帧全检驾驶员点烟、接电话是持续数秒的动作产线常见做法是每路每秒抽1-2帧做检测再叠加一个帧间动作保持逻辑。按抽帧1fps来算单路每帧预算1000msT4实测15ms延迟意味着单卡同时处理几十路都够抽帧5fps时每帧预算200ms单卡支撑15路以上仍有余量。所以“一张T4能带多少路DMS”这个问题的答案取决于你的抽帧策略而不是模型的原始延迟。我吃过一次亏第一次做DMS项目时按25fps全帧检测去做预算结果2路就把T4塞满了后来改成5fps抽帧加动作保持硬件成本直接砍掉一个量级。这套流程走完你会发现9728张图的价值不只是训练了一个模型更是帮你把数据体检、训练、评估、部署的整条链路建立了基准。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →