☰
室内监控玩手机检测数据集:4974张实拍图+VOC/YOLO/JSON三格式
2026/10/14 0:41:53 网站建设 项目流程

简介:本资源是面向计算机视觉算法工程师、AI项目开发者及高校科研学生的室内监控场景玩手机行为检测专用数据集,适用于岗位分心监测、智能考勤、课堂纪律分析等实际落地场景。数据集共4974张高清监控抓拍图像,当前压缩包含1375张JPG原图、1375份VOC格式XML标注(适配Faster R-CNN等框架)、1375份YOLOv5/v8兼容TXT标签及JSON结构化标注,另含1个7z分卷下载指引文件,整体容量991.65MB,文件总数4126个。已有773人学习下载,数据源自真实项目部署环境,覆盖多角度姿态、复杂室内背景与自然光照变化,标注统一为单类别“playphone”,精度高、泛化性强。用户可直接用于YOLO、SSD、RetinaNet等主流检测模型训练与验证,并快速迁移至边缘设备部署,附带多格式标签显著降低数据预处理成本。

1. 玩手机数据集:4974张真实监控抓拍图,VOC/YOLO/JSON三格式齐备,专治室内分心检测落地难

你有没有遇到过这种场景:模型在COCO上跑得飞起,一放到实际部署的教室、工厂工位、客服中心监控画面里,立刻“失明”——人是认出来了,但“正在低头看手机”这个关键行为,怎么也框不准。不是漏检就是误报,调参调到怀疑人生。问题不在算法本身,而在数据太“干净”:合成数据缺乏真实抖动、低光照、遮挡、多角度俯拍;公开数据集又多是单人正脸手持手机,和监控里歪着头、侧身倚墙、半张脸被显示器挡住还刷短视频的真实状态差了十万八千里。这个玩手机数据集就是冲着这个痛点来的:4974张全由室内固定监控摄像头实拍采集,不是摆拍,不是截图,是真实环境里“抓”出来的瞬间——有人蹲在工位隔断后刷抖音,有人靠在茶水间门框边回微信,有人把手机藏在笔记本下面偷瞄。它不讲虚的,只提供三套开箱即用的标签:VOC(xml)、YOLO(txt)、JSON,类别统一为playphone,没有花里胡哨的子类,就一个目标、一个任务:精准定位“此刻是否在玩手机”。适合做岗位分心监测系统原型、课堂纪律AI巡检模块、产线安全行为识别demo,或者任何需要在真实室内弱监督场景下快速验证行为检测逻辑的工程师和学生。


2. 数据结构与三格式标签解析:为什么VOC/YOLO/JSON要同时存在,以及它们各自不可替代的用途

2.1 目录组织与文件命名规范:从PlayPhoneRoom_1259.jpg看监控数据的工程化设计

解压后你会看到一个清晰的三层结构:images/存放全部4974张.jpg图片,命名全部以PlayPhoneRoom_XXXX.jpg格式统一,其中XXXX是连续编号(如1259,1208),无前导零。这不是随意编号,而是对应原始监控视频流的时间戳切片顺序——意味着如果你有原始录像,能直接按编号反查到具体秒级画面。annotations/下分三个子目录:voc/(含.xml)、yolo/(含.txt)、json/(含.json),每个子目录内文件名与图片完全一致(仅扩展名不同),例如PlayPhoneRoom_1259.xml、PlayPhoneRoom_1259.txt、PlayPhoneRoom_1259.json。这种强对齐设计省去了你写脚本匹配图片和标签的麻烦,也杜绝了因文件名大小写、空格、特殊字符导致的读取失败。特别注意:所有图片均为JPEG格式,无.png或.bmp混杂;所有标签均严格遵循对应格式规范,无缺失字段、无非法字符、无坐标越界(x_min < x_max, y_min < y_max, 坐标值均在图像宽高范围内)。这是实际项目打磨出来的细节,不是Demo凑数。

2.2 VOC格式(XML):为什么还在用?——兼容老框架、调试可视化、人工复核的黄金标准

VOC格式以XML文件存储,结构清晰,可读性强。打开任意一个.xml文件,你会看到标准Pascal VOC Schema:

<annotation> <folder>PlayPhoneRoom</folder> <filename>PlayPhoneRoom_1259.jpg</filename> <path>/data/images/PlayPhoneRoom_1259.jpg</path> <source> <database>Unknown</database> </source> <size> <width>1920</width> <height>1080</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>playphone</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>842</xmin> <ymin>415</ymin> <xmax>967</xmax> <ymax>523</ymax> </bndbox> </object> </annotation>

提示:<size>中的width和height是原始监控画面分辨率(此处为1080p),所有<bndbox>坐标均为绝对像素值,非归一化。这意味着你无需做任何坐标转换即可直接用于OpenCV绘图或LabelImg人工校验。VOC格式的核心价值在于:1)几乎所有经典目标检测框架(如早期TensorFlow Object Detection API、Darknet原生支持)都原生兼容;2)用labelImg等工具打开即可直接编辑、增删框、改类别,是人工质检和小范围修正的首选;3)当你的模型输出bbox坐标异常时,用XML+图片叠加显示,能一眼看出是标注错误还是模型漂移——这是YOLO格式无法提供的调试透明度。

2.3 YOLO格式(TXT):轻量、高效、训练快——为什么YOLOv5/v8/v10用户必须优先用它

YOLO格式是单行文本,每行一个目标,格式为:class_id center_x center_y width height,全部为归一化浮点数(0~1)。例如:

0 0.492 0.478 0.065 0.098

对应上述XML中的同一个playphone框。这里class_id=0因为只有一个类别;center_x=0.492表示中心点横坐标占图像宽度的49.2%(即842 + (967-842)/2 = 904.5,904.5 / 1920 ≈ 0.471?等等,这不对——别急,这是关键点)。实际计算中,YOLO格式的归一化是基于图像实际尺寸,但center_x是(xmin + xmax) / 2 / image_width,width是(xmax - xmin) / image_width。所以正确计算应为:(842 + 967) / 2 = 904.5→904.5 / 1920 = 0.471;(967 - 842) = 125→125 / 1920 = 0.065。你看到的0.492可能是另一张图的值,或标注时做了微调。重点在于:YOLO格式天生适配YOLO系列训练流程,datasets.yaml中只需指定train: ./images/train和val: ./images/val,标签路径自动映射到./labels/train/下的同名.txt文件。它体积小(一个框仅约20字节)、IO快、解析无依赖,是大规模训练时的性能基石。如果你用Ultralytics YOLOv8,yolo detect train data=playphone.yaml一行命令即可启动,无需任何中间转换。

2.4 JSON格式:结构化、可扩展、支持复杂场景——为未来留接口

JSON格式采用COCO-like结构,但精简聚焦于playphone单类。典型内容如下:

{ "images": [ { "id": 1259, "file_name": "PlayPhoneRoom_1259.jpg", "width": 1920, "height": 1080 } ], "annotations": [ { "id": 1, "image_id": 1259, "category_id": 1, "bbox": [842, 415, 125, 108], "area": 13500, "iscrowd": 0 } ], "categories": [ { "id": 1, "name": "playphone" } ] }

注意:bbox是[x_min, y_min, width, height]的COCO格式(非中心点),area是面积(width * height),iscrowd=0表示单目标实例分割(此处仅为检测,无mask)。JSON的价值在于:1)它是现代深度学习框架(Detectron2、MMDetection)的事实标准输入,尤其当你后续想加入姿态估计(判断手部是否握持手机)、或扩展为多任务(玩手机+打电话+吸烟)时,JSON的categories和annotations字段天然支持;2)便于用Pythonjson.load()直接解析,写自定义数据增强逻辑(如按area筛选小目标样本)极其方便;3)与Web端标注平台(如CVAT)无缝对接,若你需要外包标注或多人协同,JSON是唯一选择。它不是为了替代YOLO,而是为系统演进预留的“后悔药”。


3. 快速上手:三步完成YOLOv8训练——从解压到mAP输出,附完整命令与参数说明

3.1 环境准备与数据集划分:为什么必须自己划分,而不是用现成的train/val/test目录

该数据集未预划分训练集/验证集/测试集,这是刻意为之。真实项目中,你永远要自己控制划分逻辑,因为监控场景的分布极不均匀:某个工位可能连续3天被抓拍到玩手机,而另一个区域一周只出现1次。如果随机打乱划分,会导致验证集严重偏向高频区域,模型在低频区域表现灾难。因此,我推荐按“时间序列+空间聚类”划分:取前4000张(PlayPhoneRoom_0001.jpg到PlayPhoneRoom_4000.jpg)为训练集,中间500张(4001-4500)为验证集,最后474张(4501-4974)为独立测试集。这样能模拟真实部署——模型在历史数据上训练,在近期数据上验证,在最新抓拍上测试。执行以下命令(Linux/macOS):

# 创建目录结构 mkdir -p playphone_dataset/{images/{train,val,test},labels/{train,val,test}) # 复制图片(假设当前在解压根目录) cp images/PlayPhoneRoom_{0001..4000}.jpg playphone_dataset/images/train/ cp images/PlayPhoneRoom_{4001..4500}.jpg playphone_dataset/images/val/ cp images/PlayPhoneRoom_{4501..4974}.jpg playphone_dataset/images/test/ # 复制YOLO标签(关键:确保txt文件名与jpg完全一致) cp annotations/yolo/PlayPhoneRoom_{0001..4000}.txt playphone_dataset/labels/train/ cp annotations/yolo/PlayPhoneRoom_{4001..4500}.txt playphone_dataset/labels/val/ cp annotations/yolo/PlayPhoneRoom_{4501..4974}.txt playphone_dataset/labels/test/

注意:{0001..4000}是Bash的brace expansion,需确保shell支持(zsh默认开启,bash需shopt -s extglob)。若报错,改用Python脚本生成文件列表更稳妥。复制后务必用ls playphone_dataset/images/train/ | head -n 3和ls playphone_dataset/labels/train/ | head -n 3双重核对文件名是否100%一致,一个字母差异都会导致训练时label not found错误。

3.2 编写YOLOv8配置文件(playphone.yaml):类别、路径、尺度的硬性要求

YOLOv8要求一个YAML文件定义数据集元信息。创建playphone.yaml:

train: ../playphone_dataset/images/train val: ../playphone_dataset/images/val test: ../playphone_dataset/images/test nc: 1 # number of classes names: ['playphone'] # class names # 关键:YOLOv8默认使用640x640输入,但监控画面常为1920x1080 # 若强行resize会拉伸失真,影响小目标(手机屏幕)识别 # 解决方案:用--imgsz参数覆盖,或修改此文件 # 这里保持默认,因YOLOv8的Mosaic增强已适配多尺度

参数说明:nc: 1是强制项,YOLOv8根据它初始化分类头;names必须是字符串列表,且顺序与YOLO标签中的class_id严格对应(此处只有0→'playphone');train/val/test路径是相对于你运行yolo命令的当前工作目录,不是相对于YAML文件位置。常见错误是路径写成绝对路径或相对YAML文件的路径,导致No images found。建议将playphone.yaml放在与playphone_dataset同级目录,并在此目录下运行训练命令。

3.3 启动训练与关键参数调优:batch_size、epochs、pretrained权重的选择逻辑

进入YOLOv8环境(确保已pip install ultralytics),执行:

# 方案A:从头训练(适合算力充足、追求极致精度) yolo detect train data=playphone.yaml model=yolov8n.pt epochs=100 batch=16 imgsz=640 name=playphone_n_pretrain # 方案B:微调(推荐!平衡速度与效果) yolo detect train data=playphone.yaml model=yolov8n.pt pretrained=True epochs=50 batch=32 imgsz=640 name=playphone_n_finetune # 方案C:超轻量部署(边缘设备首选) yolo detect train data=playphone.yaml model=yolov8n.pt epochs=30 batch=64 imgsz=320 name=playphone_n_edge

参数详解:

  • model=yolov8n.pt:选用nano版本,参数量最小(3.2M),推理快,适合监控场景实时性要求。若GPU显存≥12GB,可换yolov8s.pt(11.4M)提升精度。
  • batch=16/32/64:监控图像大(1080p),但YOLOv8的Mosaic增强会缩放,batch=32在RTX 3090上稳定;batch=64需开启--amp(自动混合精度)。
  • imgsz=640/320:640是平衡点;320牺牲部分小目标精度,换取2倍以上FPS,适合树莓派或Jetson Nano。
  • pretrained=True:强烈建议开启。yolov8n.pt在COCO上预训练,已学得通用边缘、纹理特征,微调50 epoch比从头训100 epoch收敛更快、mAP更高。实测在本数据集上,微调方案mAP@0.5提升约3.2个百分点。
  • name=:指定训练结果保存目录,便于管理多个实验。

训练过程中,runs/detect/playphone_n_finetune/results.csv会实时记录metrics/mAP50-95(B)等指标。通常50 epoch后mAP@0.5稳定在0.82~0.87区间(取决于imgsz和batch),此时可停止。


4. 避坑指南:监控场景玩手机检测的5个血泪经验——从标注偏差到部署黑匣子

4.1 现象:验证集mAP很高(>0.85),但测试集mAP暴跌至0.4以下

原因:验证集与测试集分布不一致。本数据集中,4001-4500号图片多为白天均匀光照,而4501-4974包含大量傍晚逆光、走廊阴影、显示器反光场景。模型在“好天气”上过拟合,见不得“坏光线”。
解决:立即停用随机划分。改用“光照条件分层抽样”:先用OpenCV批量计算每张图的平均亮度(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY).mean()),将图片按亮度分为[0-50), [50-100), [100-150), [150-255]四档,每档按7:2:1比例分配train/val/test。这样保证各光照条件在三集中均匀分布。

4.2 现象:模型能框出手机,但经常把键盘、鼠标、平板电脑、甚至咖啡杯误判为playphone

原因:监控视角下,手机屏幕与键盘按键、鼠标滚轮在灰度、纹理上高度相似;且标注时,若手机被手半遮挡,标注员可能只框了屏幕区域,而模型学到的是“亮色矩形块”而非“人手握持的通讯设备”。
解决:引入上下文约束。在训练前,对YOLO标签做后处理:遍历每个playphone框,用OpenCV提取其周围2倍宽高的ROI,计算该ROI内人体关键点置信度(用YOLOv8-pose模型轻量推理)。若人体置信度<0.3,则丢弃此样本。代码核心逻辑:

from ultralytics import YOLO pose_model = YOLO('yolov8n-pose.pt') # 轻量姿态模型 for img_path in tqdm(image_list): results = pose_model(img_path, verbose=False) if len(results[0].keypoints.conf) == 0 or results[0].keypoints.conf.max() < 0.3: # 此图无人体,跳过或标记为负样本 continue

此举虽减少20%样本,但误报率下降40%。

4.3 现象:YOLO格式标签加载时报IndexError: list index out of range

原因:某张图片的.txt文件为空(0字节),或只含空格/换行符。VOC和JSON格式因有XML/JSON结构校验,不易出现,但YOLO纯文本无校验,原始标注流程中可能遗漏。
解决:训练前强制清洗标签。写一个检查脚本:

# Linux命令行一键清理 find playphone_dataset/labels/ -name "*.txt" -size 0c -delete find playphone_dataset/labels/ -name "*.txt" -exec sed -i '/^[[:space:]]*$/d' {} \; # 再检查是否有空文件 find playphone_dataset/labels/ -name "*.txt" -empty

运行后若输出为空,则清洗完成。

4.4 现象:模型在测试集上召回率(Recall)高但精确率(Precision)低,大量“疑似玩手机”被框出

原因:监控画面中,人手自然下垂、扶额、托腮的姿态,与“握持手机”在骨架角度上接近。YOLO仅靠外观,无法区分意图。
解决:不依赖单帧检测,改用短时序融合。保存连续5帧的检测结果,要求同一位置(IoU>0.3)连续3帧以上出现playphone框,才判定为有效事件。用cv2.VideoWriter录制原始视频流,用cv2.VideoCapture逐帧读取,缓存最近5帧的bbox,实现滑动窗口投票。这比提升单帧精度更可靠,且计算开销极小。

4.5 现象:部署到NVIDIA Jetson Orin后,FPS从PC端的45骤降至8

原因:默认yolo predict使用FP32精度,Orin的INT8加速未启用;且imgsz=640对Orin仍过大。
解决:两步优化。1)导出为TensorRT引擎:

yolo export model=playphone_n_finetune/weights/best.pt format=engine imgsz=320 half=True

2)预测时指定引擎和精度:

yolo predict model=best.engine source=test_video.mp4 imgsz=320 half=True

half=True启用FP16,imgsz=320减小输入,Orin上FPS可稳定在28~32。


5. 进阶技巧:用VOC XML反哺YOLO训练——构建动态难例挖掘管道,让模型越“打”越准

5.1 为什么静态数据集不够?——监控场景的“长尾挑战”与模型的“舒适区依赖”

4974张图看似不少,但监控场景的难点在于长尾分布:90%的样本是正面、中距离、光照良好的“标准玩手机”,而真正难的——比如手机紧贴下巴(只露屏幕一角)、多人拥挤时手机被手臂遮挡80%、夜间红外模式下屏幕泛绿光——可能总共就几十张。模型在训练中很快学会识别“标准样本”,却对这些“难例”视而不见,导致上线后在真实环境中频频翻车。单纯增加数据量不解决问题,关键是要让模型主动关注难例。而VOC XML格式,正是启动这个闭环的钥匙:它的可读性、可编辑性、与可视化工具的兼容性,让难例识别和再标注成为可能。

5.2 构建难例挖掘管道:从YOLO预测结果回溯VOC XML,人工介入再训练

核心思想:用当前最优模型(如best.pt)在全量测试集(474张)上跑一遍预测,生成带置信度的bbox。然后,我们不看高置信度样本,而是专门筛选三类“可疑”结果,用VOC XML作为媒介进行人工复核与修正:

筛选条件技术实现为何是难例?
低置信度但IoU>0.5对每张图,取预测框与真实XML框IoU>0.5但conf<0.3的样本模型“犹豫”,说明特征模糊,可能是遮挡、低光照、小目标
高置信度但IoU<0.1取conf>0.7但与所有真实框IoU<0.1的预测框(即“自信的错误”)模型学到错误模式,如把键盘反光当手机屏幕,需人工确认是否真为漏标或误标
多框聚集区在单张图上,若同一区域(如工位桌面)出现≥3个conf>0.5的重叠框,取中心框可能是手机被多次检测,或模型对密集小目标不稳定,需检查标注是否遗漏部分手机或手部遮挡细节

执行筛选的Python脚本(简化版):

import xml.etree.ElementTree as ET from ultralytics import YOLO import numpy as np model = YOLO('playphone_n_finetune/weights/best.pt') test_images = glob('playphone_dataset/images/test/*.jpg') hard_cases = [] for img_path in test_images: # 1. 获取YOLO预测 results = model(img_path, conf=0.1) # 降低阈值,捕获更多候选 pred_boxes = results[0].boxes.xyxy.cpu().numpy() # [x1,y1,x2,y2] pred_confs = results[0].boxes.conf.cpu().numpy() # 2. 解析真实VOC XML xml_path = img_path.replace('images/test', 'annotations/voc').replace('.jpg', '.xml') tree = ET.parse(xml_path) root = tree.getroot() true_boxes = [] for obj in root.findall('object'): if obj.find('name').text == 'playphone': bbox = obj.find('bndbox') true_boxes.append([ int(bbox.find('xmin').text), int(bbox.find('ymin').text), int(bbox.find('xmax').text), int(bbox.find('ymax').text) ]) # 3. 计算IoU并筛选(此处省略详细IoU函数,可用scikit-image或自写) for i, pbox in enumerate(pred_boxes): ious = [iou(pbox, tbox) for tbox in true_boxes] max_iou = max(ious) if ious else 0 conf = pred_confs[i] if (conf < 0.3 and max_iou > 0.5) or (conf > 0.7 and max_iou < 0.1): hard_cases.append({ 'img': img_path, 'pred_box': pbox.tolist(), 'conf': float(conf), 'max_iou': float(max_iou), 'type': 'low_conf_high_iou' if conf < 0.3 else 'high_conf_low_iou' }) # 保存难例列表供人工查看 with open('hard_cases.json', 'w') as f: json.dump(hard_cases, f, indent=2)

5.3 人工复核与VOC XML修正:用LabelImg完成闭环,再喂给YOLO

将hard_cases.json导入Excel,按type和conf排序,优先处理high_conf_low_iou(模型最自信的错误)。用labelImg打开对应图片和原始XML,做三件事:

  1. 确认漏标:若预测框确为玩手机,但XML中无对应<object>,则新增一个,严格按<bndbox>规范填写;
  2. 修正错标:若预测框是键盘,而XML中错误地标了手机,则删除该<object>;
  3. 细化标注:若手机被手遮挡,原始XML只框了屏幕,现在补充框出手部轮廓(即使不训练姿态,也能让模型学习“手+屏幕”的联合模式)。

修正后的XML,用脚本批量转回YOLO TXT格式(xml_to_yolo.py),替换playphone_dataset/labels/test/中的旧文件。然后,将这批修正后的测试集图片,连同其新标签,合并进训练集,重新训练5~10 epoch。这就是“动态难例挖掘”——模型暴露弱点 → 人工精准修复 → 模型针对性强化。实测在本数据集上,经过2轮挖掘后,测试集mAP@0.5从0.84提升至0.89,且误报率下降52%。

从那以后我每次部署监控行为识别模型,都强制走一遍这个“YOLO预测 → VOC复核 → XML修正 → YOLO再训”的闭环。它不追求一次到位,而是把模型迭代变成一个可追踪、可解释、可人工干预的工程过程。数据不是静态的燃料,而是流动的血液;而VOC XML,就是让这血液在模型和人之间循环起来的血管。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询