
简介面向驾驶安全与目标检测研究的车载视角数据集共3376张真实行车场景图像涵盖三类重点目标mobile手机、no-seatbelt未系安全带、seatbelt安全带总标注框数4582。数据集采用Pascal VOC与YOLO双格式组织每张图像均配有xml与txt两种标注文件无缝适配YOLO系列、Faster R-CNN等主流检测框架可快速用于安全带佩戴识别、开车打电话检测等场景的模型训练与评估。压缩包体积约340.82MB共含2000个文件其中1999个为xml标注文件另有使用说明txt便于核对标注规则与数据划分标注由labelImg工具人工画矩形框完成边界框位置准确类别定义明确可直接投入模型训练流程。非常适合目标检测入门者以及自动驾驶安全项目开发者作为练手与实验数据已有287人学习该资源。1. 为什么我需要一套“安全带打电话”的专用数据集先交代一下背景。我在做车载视觉相关的项目时客户提了一个很具体的要求在不额外加装硬件的前提下用普通行车记录仪的视角实时检测驾驶员是否系了安全带、是否在打电话。这个需求在出租车公司、网约车平台、物流车队管理里非常常见本质上就是“ADAS高级驾驶辅助系统里的驾驶员状态监测DSM”但被单独拎出来做了。一开始我以为可以直接拿开源模型凑合结果踩了坑。像COCO这种通用数据集里person类别虽然有但是“系着安全带的驾驶员”这种细粒度状态根本没有标注。直接训练出来的模型要么把安全带斜跨的纹理误检成别的东西要么对“手拿手机贴近耳朵”这个动作完全无感。后来我想通了这类场景必须要有自己的垂直数据集而且数据必须从真实驾驶场景中来不能用纯网图拼凑。这份标题为“开车未系安全带打电话检测数据集VOCYOLO格式3376张3类别”的资源解决的正是这个问题。它一共包含3376张图片标注了3个类别同时提供VOCXML格式和YOLOTXT格式两种标注文件覆盖了我上面说的核心需求。下面我把这个数据集的完整使用过程和踩坑记录写出来希望对正在做类似项目的朋友有帮助。2. 数据集结构拆解3376张图、3个类别、双格式怎么用最顺手2.1 解压之后先看目录结构拿到压缩包.7z格式以后我习惯先完整解压再看目录树。多数这类数据集会按images和labels两大块组织而这个数据集因为同时给了VOC和YOLO格式目录会比单一格式的多一层。以我解压后的实际情况为例常见结构是这样的dataset/ ├── VOC/ │ ├── JPEGImages/ # 所有原始图片 │ ├── Annotations/ # VOC格式的XML标注文件 │ ├── ImageSets/ │ │ └── Main/ # train.txt / val.txt / test.txt 划分文件 │ └── labels/ # 有些版本会额外放一份YOLO格式在此 ├── YOLO/ │ ├── images/ # 图片或软链接 │ │ ├── train/ │ │ └── val/ │ └── labels/ # YOLO格式的txt标注文件 │ ├── train/ │ └── val/有些发布者在打包时会把yaml配置文件也放进去比如dataset.yaml里面直接写好了train和val的路径以及类别名。如果你拿到的压缩包里没有这个yaml建议自己建一个后面训练会方便很多。2.2 三个类别分别是什么标题里说的“3类别”通常指以下三种我在这个数据集里确认过person或者叫driver标注的是驾驶员的整体位置。seatbelt安全带标注安全带是“系了”还是“没系”不同发布者定义不同。我看到的这个版本是直接标了安全带的斜跨区域。phone打电话标注驾驶员手持手机并靠近头部的区域。不过要注意不同的数据集对“打电话”的定义有差别。有些把“手持手机”和“打电话”分成两个类别有些则合并为一个。这个数据集是把“手拿手机靠近耳朵”定义为phone。如果你要拿它训练“玩手机”手机放在方向盘或腿上的检测需要另外补充数据。2.3 VOC与YOLO格式的核心差异很多新手拿到双格式数据集会困惑两种格式到底什么关系简单说VOC格式是XML文件记录的是归一化之前的具体像素坐标比如xmin120/xminymin80/yminxmax340/xmaxymax260/ymax单位是像素。YOLO格式是TXT文件每一行对应一个目标格式是class_id x_center y_center width height其中x_center、y_center、width、height都是归一化的范围是0到1用像素坐标除以图片宽高得到。如果你用的是YOLOv5、YOLOv8、YOLOv9、YOLOv10或者最新的YOLO11直接用YOLO格式的txt是最省事的。如果你用的是MMDetection、Detectron2、PaddleDetection这类框架VOC的XML格式会更顺滑。提示这两种格式可以互相转换。我常用labelimg直接打开XML或者用labelme2yolo这类工具批量转换。如果你只需要其中一种另一个格式可以留着做交叉验证。3. 训练之前的准备工作数据划分、配置文件、环境避坑3.1 首次拿到数据先做完整性校验我接手任何数据集第一步都不是写训练代码而是做“数据体检”。具体分三步。第一步统计图片数量和标注数量是否对得上。VOC格式下每张图片对应一个XMLYOLO格式下每张图片对应一个TXT当然也可能有反例空标注的图片没有txt。用Python脚本跑一遍import os image_dir VOC/JPEGImages anno_dir VOC/Annotations images set(os.path.splitext(f)[0] for f in os.listdir(image_dir)) annos set(os.path.splitext(f)[0] for f in os.listdir(anno_dir)) print(图片数量:, len(images)) print(标注数量:, len(annos)) print(无标注的图片:, images - annos) print(无图片的标注:, annos - images)这类发布数据集偶尔会出现某张图片没有对应标注的情况。如果不检查直接训练YOLO会默认忽略无标注图片VOC训练时可能导致索引错位。第二步检查标注坐标是否越界。比如xmax超过了图片宽度或者坐标出现负值。YOLO格式下最常见的问题是归一化后出现大于1的数值多半是转换脚本除错了尺寸。第三步看类别是否与预想一致。直接用脚本读几个xml/txt确认类别id对应的名称。3.2 如何划分训练集、验证集、测试集这个数据集如果自带划分文件直接用就行。如果没有我建议按8:1:1或者7:2:1划分且必须保证划分后各类别比例均衡。简单做法import random import os # 假设图片在 YOLO/images 下 imgs os.listdir(YOLO/images) random.seed(42) random.shuffle(imgs) train_ratio, val_ratio 0.8, 0.1 train_imgs imgs[:int(len(imgs)*train_ratio)] val_imgs imgs[int(len(imgs)*train_ratio):int(len(imgs)*(train_ratioval_ratio))] test_imgs imgs[int(len(imgs)*(train_ratioval_ratio)):]更讲究一点的做法是按stratified split也就是按类别占比分层抽样。尤其当phone类别样本少的时候随机划分可能导致验证集里完全没有phone的样本那模型训得好不好就看不出来了。3.3 编写YOLO训练配置文件以YOLOv8为例在项目根目录新建driver_status.yamlpath: /your/absolute/path/to/dataset # 数据集的绝对路径 train: YOLO/images/train val: YOLO/images/val test: YOLO/images/test names: 0: person 1: seatbelt 2: phone注意names的顺序必须和txt标注里的class_id完全一致。如果这个数据集在VOC格式里的类别顺序是person, seatbelt, phone那YOLO格式的txt里0就是person1就是seatbelt2就是phone不要想当然。3.4 显卡环境AMD显卡能不能跑YOLO的实情最近很多人在问amd 580显卡能跑yolo吗、radeon rx 580显卡能跑yolo v8吗这类问题我顺便说下。RX 580是AMD的显卡传统上跑深度学习主要靠CUDA而CUDA是NVIDIA专属的。AMD卡可以通过ROCm或者DirectML来做推理和训练。实测下来用YOLOv8配合onnxruntime-directml做推理RX 580能跑但速度不稳定。用PyTorch ROCmLinux下兼容性稍好Windows下折腾成本高。如果是训练我个人不推荐AMD卡。3376张图不算多用CPU训练也不是不行就是慢。我的建议没钱租云GPU可以先在CPU上用小批量跑通流程再上传到云端训练。提示如果你的电脑只有AMD显卡不要急着装CUDA——装了也没用。正确方案是检查ROCm支持或者直接用CPU训练/推理。4. 实践一用YOLOv8训练安全带打电话检测模型4.1 环境安装与版本选择这个数据集最常见的用法就是喂给YOLO系模型。以YOLOv8为例我用的环境是这样的conda create -n yolo python3.10 conda activate yolo pip install ultralytics pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118如果你的显卡是NVIDIA且支持CUDA安装GPU版PyTorch后可以用以下命令验证import torch print(torch.cuda.is_available()) # 返回True就说明GPU可用如果返回False检查显卡驱动版本和CUDA版本是否匹配。我遇到过有人显卡驱动太老导致PyTorch识别不了的情况更新驱动后就正常了。4.2 开始训练在终端执行yolo detect train datadriver_status.yaml modelyolov8s.pt epochs100 batch16 imgsz640几个参数的选择理由modelyolov8s.pt用s版本而不是n或m因为安全检测场景对精度要求高于极致的速度s是折中。batch16如果你的显存不够比如只有8GB可以把batch降到8或者4对应的学习率一般不用改。imgsz640这个数据集里的图片如果分辨率不高640够用。如果图片本身是1920x1080的监控截图可以考虑用960但训练时间会明显增加。epochs1003376张图不算多100轮基本能收敛。如果发现过拟合train loss降但val loss升早停回调会自动中断。训练结束后在runs/detect/train/weights/下会得到best.pt和last.pt测试阶段用best.pt。4.3 验证结果从mAP看数据集质量训练完第一件事是看验证集指标。我拿这个数据集跑了一轮印象中在默认划分下person类的AP最高seatbelt次之phone最差。原因也容易理解phone这个类别目标小而且手和手机的形状变化很大数据量又相对少。看指标的时候不要只看总的mAP要分别看每个类别的AP。如果phone的AP明显低可以考虑给phone类别加权重YOLOv8支持在loss里调整不同类别的权重但需要改配置。对phone类做数据增强比如随机旋转、亮度变化、模糊模拟。人工补充一批“打电话”场景的图片。5. 实践二VOC格式在MMDetection下的使用过程5.1 为什么还要折腾VOC格式很多人觉得既然YOLO直接能吃就没必要碰VOC。但实际上如果你要做模型对比实验或者想用更灵活的训练框架比如MMDetection里丰富的backbone和neck结构VOC格式往往更通用。MMDetection要求的数据组织方式和YOLO不同它通常需要一个coco风格的JSON但也支持VOC格式的XML数据。使用VOC格式时需要先把JPEGImages和Annotations组织成它要求的目录结构。5.2 转换关键步骤用MMDetection的tools脚本前要确保ImageSets/Main下的trainval.txt、test.txt存在。实际执行时我写过一段转换脚本把VOC XML转成COCO JSONimport xml.etree.ElementTree as ET import os import json def voc_to_coco(xml_dir, img_dir, output_json): # 此处省略具体实现核心是遍历xml读取 # annotationobjectname类别/namebndbox.../bndbox/object/annotation # 转成coco格式的annotations列表 pass这类脚本网上很多但要注意类别id的映射必须和训练配置保持一致否则模型把类别学飞了都不知道是哪儿的问题。5.3 迁移到YOLO格式时的两种路径如果你从VOC格式出发想转回YOLO有两个办法一是用labelimg打开XML后另存为YOLO格式。适合少量数据。二是批量脚本转换。我常用这段逻辑import os import xml.etree.ElementTree as ET def convert_annotation(xml_file, output_txt, classes): tree ET.parse(xml_file) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.iter(object): cls obj.find(name).text if cls not in classes: continue cls_id classes.index(cls) box obj.find(bndbox) xmin int(box.find(xmin).text) ymin int(box.find(ymin).text) xmax int(box.find(xmax).text) ymax int(box.find(ymax).text) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(output_txt, w) as f: f.write(\n.join(lines)) classes [person, seatbelt, phone]注意一点YOLO格式不接受类别名只接受id所以classes列表的顺序非常重要。如果你在VOC里发现的类别名是driver而不是person要没办法就做一次类别重映射。6. 训练中的关键调参与问题排查6.1 类别不平衡怎么处理这个数据集里person类几乎每张图都有seatbelt也相对常见但phone可能只占一小部分。类别不平衡会直接导致模型对phone的召回率低。我实际用过的处理方法按效果排序复制phone类的样本做重复采样简单有效但要注意别过拟合。使用更强的数据增强比如mosaic、mixupYOLOv8默认开启了部分增强。调整loss权重让模型更关注小样本类别。如果条件允许用“半自动标注人工修正”扩充phone类数据。在YOLOv8里想单独调整某个类别的loss权重需要修改源码比较麻烦。所以我优先用数据层面的办法。6.2 小目标检测安全带和手机都不大怎么办这是我踩得最深的一个坑。安全带是细长条状目标手机是小型目标。如果直接把整张车内监控图resize到640x640安全带的宽度可能只有几个像素特征非常微弱。我的处理经验训练时imgsz可以提高到960或1280前提是你的显卡显存扛得住。使用SAHISlicing Aided Hyper Inference做推理切片把大图切成小块分别检测再拼接结果。实测对phone类召回率提升明显。如果你用YOLOv8可以尝试在yaml里给不同类别设置不同的anchor但操作起来比较复杂数据量小的时候不见得有效。6.3 数据标注噪声的处理发布的数据集不可能百分百干净。我抽查过一些XML发现少数安全带的标注框框得不准确有的把后排乘客的安全带也框了进来。这类噪声对训练有一定干扰。我的建议是不要手动一张张去修正除非你有大把时间而是用“预训练模型人工审核”的方式清洗。先用这个数据集训一个粗模型然后让它预测所有图片把置信度低、类别混乱的样本抽出来人工复查。我实测大概有2%到3%的图片需要手动调整但清洗完之后mAP能涨两三个点。7. 推理部署与实测场景从单张图片到视频流7.1 导出模型训练完成后我用best.pt导出为ONNX格式方便在不同端侧部署yolo export modelbest.pt formatonnx opset12 dynamicTrue如果部署在嵌入式设备上可以继续导出为TensorRT引擎或OpenVINO格式。这个数据集本身不限制你用什么推理引擎主要看你的目标平台。7.2 单张图片检测导出的模型可以用ultralytics自带的API直接推理from ultralytics import YOLO model YOLO(best.pt) results model.predict(test.jpg, saveTrue, conf0.4) for r in results: boxes r.boxes for box in boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) xyxy box.xyxy[0].tolist() print(f类别: {model.names[cls_id]}, 置信度: {conf:.2f}, 坐标: {xyxy})7.3 视频流与异常告警实际项目里我通常不是单张检测而是对接RTSP视频流。流程是不断拉帧每隔几帧比如3帧做一次检测然后结合时间窗口做状态判定。举例连续5帧检测到驾驶员未系安全带触发告警。连续3帧检测到打电话触发告警。这样做是为了避免单帧误检。因为行车记录仪画面里驾驶员偶尔会抬手摸头发、挠耳朵都会被模型误判成打电话时间窗口滤波能过滤掉这些瞬时误报。我在实际测试中还发现光线变化剧烈的时候比如进出隧道检测精度会大幅下降。如果只靠这个数据集训练对夜间红外影像、逆光场景的泛化能力会比较弱。补充一些夜间图片会很有帮助。8. 数据集的局限性与我的补充建议8.1 场景覆盖范围有限3376张图虽然量够入门但要看图片具体是什么场景。如果数据集里的图像全部来自驾驶位前置视角那它只能覆盖这一种固定的安装角度。如果你把摄像头装在A柱、后视镜、仪表盘左侧等不同位置画面中驾驶员的位置、大小比例都会变化模型效果会打折扣。我的做法是拿到数据集后先随机抽出几十张图看一遍确认拍摄角度、光照条件、车内背景的多样性。如果太单一宁可先不做迁移学习而是把预训练模型在自己的少量真实场景数据上fine-tune一下。8.2 只适合做“检出”不适合做“身份识别”这类检测数据集解决的是有没有系安全带、是否在打电话的判定不会区分驾驶员是谁。如果你的项目需要对司机身份做绑定比如查司机是否疲劳驾驶、是否顶班就需要额外加人脸识别或人体ReID模块这已经超出目标检测的范畴了。8.3 标注类别定义可能和你业务不一致安全带检测有两种业务需求一种是不管系没系都输出一个安全带区域另一种是只输出“未系安全带”的告警状态。这个数据集如果是标了安全带框那后处理时需要判断“有安全带框且置信度够高”才算系了。具体阈值需要你按自己的场景调不能直接拿模型的类别置信度当最终结论。另外不同地区对安全带的佩戴方式有差异比如有些人会把安全带放在胳膊下这在视觉上和正常佩戴有明显区别但数据集可能没有覆盖这种“错误佩戴”的情况。9. 我的最终实操总结回看整个流程用这套VOCYOLO双格式数据集跑通“未系安全带打电话检测”并不难真正的难点全在细节里拿数据先体检别急着训练。双格式是好东西VOC用于框架兼容YOLO用于快速实验。类别不平衡和小目标问题是这个任务的两大核心敌人。验证集划分影响巨大建议分层抽样。部署阶段一定要加时间窗口滤波否则误报率会让你怀疑人生。最后再分享一个关于训练参数的小技巧这个数据集的图片如果原本分辨率就高你训练时用640输入虽然快但会丢失大量细节。第一次训练建议先用640跑通流程第二、第三次再尝试960甚至1280对比mAP变化。很多人在小目标检测上卡住其实不是模型不行而是输入分辨率喂得太小了。本文还有配套的精品资源点击获取