
你有没有遇到过这类需求教室后排想自动统计学生是不是在低头刷手机办公区想看看下午有多少人摸鱼停车场出口想提醒司机别在开车时碰屏幕。真动手做的时候你会发现卡住你的往往不是YOLO怎么调参也不是模型选v8还是v5而是手里根本没有一份能直接用来训练的手机检测数据集。我整理的这套2800张YOLO目标检测数据集就是为这类场景准备的。图片全部完成人工标注标签统一为phone格式可以直接接入YOLOv5/YOLOv8训练流程。下面我会把整个数据集的构建逻辑、标注约定、训练实测和踩坑记录都摊开来讲打算做课堂玩手机检测、工位监察、驾驶分心提醒这类项目的朋友可以直接照着来。1. 为什么非要做一套专门的手机检测数据集1.1 通用数据集里的手机根本不够用很多人第一反应是“用COCO不就行了”COCO里面确实有cell phone这个类但当你单独去检测手机时就知道它有多不靠谱。COCO是80类的大杂烩手机在所有标注里占比很小而且绝大多数是近景、大目标、干净背景的样张。真实场景里的手机是什么样的可能只有画面里十几个像素可能握在手里只露出三分之一可能在夜间被屏幕照得一片惨白。拿通用权重直接去测最常见的结果是人倒是框得挺准手机要么没框出来要么把平板、笔记本适配器都框成了手机。专门做一套手机检测数据集就是为了把这些通用数据集留下的坑全部填上。我印象很深的一次测试是直接用COCO预训练权重跑办公室摄像头画面画面上同事手里拿着黑色手机从工位走过模型全程没有给出一个手机框反而把桌面上的黑色笔记本电源误检成了手机置信度还高达0.7。这种结果其实不意外COCO里的手机样本一般出现在近景的人像照片里角度正、遮挡少、背景干净模型学的特征偏理想化。一旦场景变成中远距离的室内监控视角目标小、角度杂、光照乱原来那套特征就全对不上了。1.2 手机小目标的检测难点到底卡在哪这套数据集设计时我重点思考的就是“为什么手机检测比想象中难”。我把它拆成四类问题小目标问题监控摄像头位置高手机在画面里经常只有几十个像素YOLO默认的640输入下小目标特征很容易被池化层吃掉。反光与屏幕干扰屏幕点亮时整个矩形区域过曝边缘被光晕糊掉模型容易把亮斑当特征换个角度就不认识了。形变与遮挡手持、揣兜、贴耳、横屏打游戏手机的形状变化很大加上手部的遮挡一个完整的矩形框经常装不下。背景混淆黑色手机放在黑色桌面上银色手机放在不锈钢设备旁边边框和背景融为一体模型很容易漏掉或者把类似色块误检出来。这些问题直接影响数据采集和标注策略。比如同一个场景我至少要保证三个时间段的样本白天、黄昏、夜间同一个目标要覆盖“拿在手里”“放在桌上”“贴在耳边”三种姿态目的就是让模型在训练阶段就把这些变化都见过。下面这个表是难点和数据集层面对策的对照后面所有操作基本都围绕着这张表来展开难点对检测的影响数据集层面的对策小目标漏检率高保留大量远景样本配合Copy-Paste增强屏幕反光特征漂移覆盖亮屏/息屏两种状态避免只学亮斑形态遮挡框不完整标注遮挡可见部分加入手持、贴耳姿态背景混淆误检补充黑色桌面、深色衣物等难负样本2. 2800张图是怎么攒出来的2.1 数据来源分三路但每一路都要过脑子攒数据我用了三条路同时走。第一条是公开合规来源。像Open Images、AI Challenger这类目标检测数据集里本身含有手机相关图片我从里面筛出手机占比较高的样张按许可协议确认可用后拿来作为基础样本。这里提醒一句从公开数据集筛图时一定要看授权条款商用项目和实验室项目对版权的要求不一样别踩了坑。第二条是自己拍摄。我找了几部不同颜色、不同尺寸的手机当道具分别在办公室、教室、走廊、户外、夜间街道等环境里拍摄手机屏幕设置为亮屏、息屏、半亮三种状态。拍摄时不要只拍“好看的构图”要刻意模拟真实监控视角——俯拍、远拍、隔一个工位侧拍。第三条是视频抽帧。自己录几段自然场景的视频按每3到5帧抽一帧能得到大量背景略有变化但目标姿态连续的图片。抽帧的好处是后续训练时模型能看到同一个手机在不同瞬间的位置变化对小目标跟踪类任务特别友好。我做了一个简单的配比实验第一版只有公开筛选样本测试集漏检率明显偏高加入自拍和抽帧样本后漏检率下降很明显。原因是公开样本里“摆拍感”太强让模型学偏了。我按下面这个场景清单来控制数据配比最终凑齐2800张场景光线条件手机状态张数办公室工位日光灯亮屏/息屏/桌面/手持600教室后排混合光桌面/手持/遮挡500走廊过道自然光手持/贴耳400户外街道白天/黄昏手持/揣兜/贴耳500夜间室内弱光屏幕亮起/息屏400车内驾驶舱混合光支架/手持4002.2 清洗筛选宁缺毋滥图片攒回来粗算有4000多张最后只留了2800张剩下的全删了。删掉的主要是这三类手机在画面中占比小于1%的远景图。这种图不是不能学而是在640分辨率下目标只有十几个像素对训练YOLO的性价比太低。严重运动模糊到人眼都认不出的图。手机被快速拿起放下时很容易拍出这种帧视觉上有个形状但完全没有边缘信息标注了也是给模型喂噪声。目标被遮挡超过70%的图。只露出一个角或者只剩耳机线连着手机这种标注框会给损失函数传递错误信号。这个筛选过程不要心疼。数据量从来不是第一优先级数据质量才是。2800张干净样本的训练效果经常比4000张混入大量低质量样本的效果还要好。我当时把每一张被淘汰的图都记了个原因回头再看运动模糊占了四成小目标占了三成遮挡占了两成多真正有价值却不小心删掉的图其实很少。2.3 划分数据集时的“分层”技巧训练、验证、测试我按2300/300/200来分但这一步有个容易被忽略的细节不要直接随机打乱划分而是按场景先分层再在各层里随机抽。也就是说办公室场景、教室场景、夜间场景、户外场景各占多少比例在划分时保持一致。如果直接随机划分很可能验证集全落在白天办公室场景上测试集却全是夜间场景最后跑出来的指标虚高一到真实环境就露馅。另外还有个数据泄露问题要留意同一个视频抽帧出来的图片内容高度相似如果一部分进了训练集另一部分进了测试集测试指标会被大幅高估。我的做法是按“视频片段”而不是按“单帧”来划分保证同一个视频片段要么全在训练集要么全在测试集。这个细节做目标检测的人容易忽视但对于视频抽帧类型的数据它影响非常大。3. 标注规范一个框也是有讲究的3.1 标注工具选择与流程2800张图如果纯手工框一个人大概要连续标两天半很容易标到后面手抖。我的做法是先用X-AnyLabeling做半自动预标注加载一个通用YOLO权重比如YOLOv8s先跑一遍预测生成一批初始框然后人工在工具里逐个修正。这样直接把标注时间压到一天以内。小批量数据或者你只是临时补几百张图用LabelImg手动框也完全够不用过度工具化。这里有一个操作上的顺序建议先把预标注模型调整到一个偏低的置信度比如0.15宁可多框出来一些错框也不要在预标注阶段漏掉目标。漏掉的目标如果你没注意到就会被直接跳过比错框更麻烦。错框至少还在画面上能被你一眼看到然后修正漏框就彻底隐身了检查的时候也很难发现。3.2 标注边界约定什么时候框框哪里拿手机检测这种单类标注来说最容易出现分歧的就是边界。我定了一套自己的规则也建议你提前定好否则两个人标出来的框风格完全不同只框肉眼可以明确识别为手机完整轮廓的可见部分哪怕只有50%可见有条件判断是手机就框。屏幕点亮时产生的光晕不算手机边界按照机身轮廓来框光晕属于背景。手机被手握住时框可见的机身部分不要把整个拳头框进去。画面里出现多个手机全部标注不因为距离远、看不清就不标——除非目标确实小到人眼无法判断。这些规则看着琐碎但直接影响模型学到的边界回归能力。我第一版标注时没管光晕问题结果模型把屏幕上的一片白光学成了手机特征亮屏手机大量误检后来花了一整天把亮屏图片重新过了一遍标注再训练才恢复正常。3.3 两轮校验机制全部标注完成后我做两轮检查。第一轮是脚本检查框坐标是否越界、是否出现负值、同一目标是否有重复框、类别ID是否越界。第二轮是人工抽检按场景各抽10%到20%重点看难例标注是否一致。抽检不合规的标注比例超过5%就让标注者统一重看一遍规则再修。这一步建议不要省标注质量差一个等级训练出来的模型就差一个等级后面再去调loss曲线浪费时间不如老老实实把框标好。脚本检查我有几个可以直接用的规则x_center、y_center必须在0到1之间width、height必须在0到1之间且不为0单个框面积不能超过全图面积的0.9同一张图里两个框的IoU超过0.8时人工复查。这些规则写成一个几十行的Python脚本就行跑一遍输出可疑样本列表比肉眼扫几千张图靠谱得多。4. YOLO训练实录参数和坑4.1 为什么先用YOLOv8n打底选型我建议从YOLOv8n开始而不是一上来就上YOLOv9或YOLOv10。原因有三第一手机检测属于单类目标检测任务本身不复杂n级的容量已经足够学出一个不错的baseline第二n参数量小训练和推理都快方便快速迭代数据质量第三后续如果用TensorRT部署到边缘设备n级模型在Jetson这类平台上跑起来更现实。如果你想追求更高精度可以在同一套数据集上直接升到YOLOv8s或m数据不需要重新标注。4.2 一份可以直接抄的训练配置我用的是Ultralytics的YOLOv8训练流程数据文件按YOLO格式写好标签是txt文件每行“class x_center y_center width height”目标类别只有phone一类。数据集YAML长这样# phone_dataset.yaml path: /data/phone_dataset train: images/train val: images/val test: images/test names: 0: phone下面这组参数是我实验下来比较稳的起点配置参数取值说明modelyolov8n.pt用预训练权重做初始化不是从零训imgsz640后续可以试1280看小目标增益batch16单卡显存16G以内建议别超过16epochs300配合早停实际跑不到300optimizerSGD配合warmup稳定性和精度都还行lr00.01学习率bn异常时降到0.005mosaic1.0前200轮开启后期可以关闭hsv_h/hsv_s/hsv_v0.015/0.7/0.4色彩增强对暗光场景很有用训练命令大概是这样yolo train data/path/to/phone_dataset.yaml \ modelyolov8n.pt \ epochs300 \ imgsz640 \ batch16 \ optimizerSGD \ lr00.01 \ patience60这里说下mosaic这个参数。mosaic增强对小目标检测很有帮助因为它把小图拼接成大图让模型在训练时更多看到相对小尺寸的目标。但它有个副作用如果目标跨拼接边界被切断标签框其实是不准的。所以我通常让mosaic一直开着跑到最后几十轮再关掉让模型最后在干净分布里稳定一下。4.3 训练中我踩过的两个坑第一个坑是BN崩溃。这个词看起来吓人其实就是训练没跑几步loss突然飙升到几十上百然后输出全是NaN。我在实际训练中遇到过两次一次是显存不够把batch调成8之后出现的一次是手滑把lr0设成了0.05。原因无非是学习率在warmup阶段之后设置得太激进或者batch过小导致BN统计量不稳定。解决办法很简单把lr0从0.01降到0.005或者把batch从8提到16重新跑一次基本就正常了。如果你用了自动找到的lr也要人工看一眼曲线再往下训。第二个坑是验证集loss在200个epoch附近开始回升训练集loss还在往下降。这是典型的过拟合信号说明模型开始背训练样本了。我的处理方式不是调模型而是回数据把HSV增强拉大一点加入平移和轻微旋转增强同时把早停patience设为60让它自己在指标不再涨的时候停下来。手机检测本身类内差异很大如果数据增强到位300轮epoch通常到150到200轮就收敛了。训练过程中我还会盯着三个曲线box_loss稳步下降说明定位在学cls_loss有波动是正常的但整体趋势必须向下如果val曲线出现“掉下去又拉上来”的锯齿状大概率是学习率太大把lr减少一半再看。5. 实测效果和边界分析5.1 测试集表现和真实场景感受在这套2800张数据集的测试集上我跑了几组实验最终YOLOv8n的mAP50能稳定在0.94到0.96附近mAP50-95在0.75到0.8之间。这个指标对单类检测任务来说属于正常偏好的水平。不同场景的表现也有差异我简单记录了一下场景类别表现情况室内日光灯很稳定误检少夜间屏幕亮起置信度很高特征明显黑色手机配黑色桌面容易漏检对比度不够隔着玻璃反射面偶尔出现重影框快速拿起手机瞬间拖影导致模糊漏检不过指标只能说明一部分问题。真正部署到实际场景后我感受到的是“场景变了效果变化很大”夜间屏幕亮起的帧检测置信度很高因为屏幕亮斑特征太明显了但黑色手机放在黑色桌面上的背影经常被漏掉。这说明测试集里没有完全覆盖极端低对比场景后面要补的正是这类难负样本。5.2 最容易漏检和误检的三种情况黑色手机加黑色桌面加俯拍目标和背景几乎同色模型很难区分边线。隔着玻璃或反光面拍摄手机轮廓被倒影干扰容易出现重影框。运动过程中的短时拖影比如快速拿起手机时画面边缘模糊到只剩一个虚影。误检方面最常见的是把黑色钱包、充电宝、手机壳色块、书脊误检成手机。这些误检来源都有一个共同点尺寸和长宽比跟手机相似纹理又被模糊掉了。想压制这种误检最好的办法不是调NMS而是把这些负样本收集起来单独作为背景图混进训练集让模型见过“长得像手机但不是手机”的东西。5.3 提升真实场景召回率的三招第一招把Copy-Paste增强打开。将小目标手机随机粘贴到其他背景图中可以在不增加人工标注的前提下让模型看到更多小尺寸样本。这个增强对手机检测尤其有效因为手机是刚性物体粘贴后不会像猫狗那样变形失真。第二招测试时用TTA。把图片做水平和轻微旋转增强后多次推理再融合结果模糊、低光场景的召回能提升代价是推理时间翻倍。如果你做的是离线视频分析TTA完全可以用做实时检测的话就要慎重。第三招后处理阶段把置信度阈值调到0.2到0.25配合更高IoU的NMS保留更多候选框对误检较高的场景再单独调回来。这里要说明的是阈值调低会带来更多误检框所以一定要结合具体场景试验没有一劳永逸的设定。6. 后续迭代从2800张到一个闭环数据集的真正价值不在于一次性训练而在于能不能滚起来。我现在用的迭代方式是半自动标注闭环先用第一版模型对海量未标注视频抽帧做预测产生一堆“预标注”人工只修正那些置信度低于0.5的框一天时间就能把数据集从2800张扩到5000张以上。扩完后再训练一版新模型又能在更难的数据上工作就这样滚雪球。想把这个数据集往产品方向推的朋友我建议下一步把“手机”拆成“手机普通状态”和“手机屏幕点亮”两类。这一点在实际项目中很重要比如课堂玩手机检测屏幕亮起时抓拍更有说服力也可以减少误报。再加一个“耳机”类也不错很多场景下戴耳机本身就是需要重点关注的行为特征。部署层面的经验是不要拿着nano模型直接上线先在服务器上用高精度模型做离线评测确认好误检率可接受再导出ONNX用TensorRT或OpenVINO加速。精度和速度之间怎么权衡一定要拿真实监控视频测别拿测试集指标自嗨。我见过不少项目死在“测试集很漂亮、现场一塌糊涂”这一步根源多半是数据场景覆盖不够而不是模型结构不行。这套数据集我自己迭代过程中最大的体会是真正花时间的不是标注本身而是定标准、筛数据、按场景分层、反复测边界。数据干净了YOLO训练反而很快。你如果也在做类似的手机检测项目建议先把这套流程走一遍哪怕只凑几百张图把数据和标注规范立住后面所有调参和模型迭代都会顺手很多。