☰
YOLO手机检测数据集:从数据采集到模型部署全流程解析
2026/10/2 4:01:40 网站建设 项目流程

做手机检测数据集,这个念头最早是从一次商场客流项目里冒出来的。客户想统计顾客在展台前停留时有没有拿手机,后来发现类似的场景越来越多:教室里学生是否低头看手机、工厂车间员工是否违规使用手机、驾驶场景里的分神检测。于是就有了这份2800张的YOLO目标检测数据集。它解决的核心问题很简单:给定一张图片或一帧视频,用目标检测算法把画面里的手机框出来。适合刚接触YOLO、想训练一个自定义检测器的初学者,也适合做移动端边缘部署的工程师。这里我不打算只甩一个下载链接,而是完整记录一下这份数据集的构建思路、标注规范、训练过程和踩过的坑,你可以直接照着跑一遍。

1. 手机检测,到底解决什么问题

1.1 不是识别手机品牌,是检测“手机”这个目标

先澄清一个很多人会误会的点:手机检测不是OCR识别屏幕内容,也不是判断手机型号,而是把手机当成一个目标框出来。目标检测任务的核心输出是边界框和类别,在这个项目里,类别只有一类:phone。为什么不做品牌识别?因为实际业务里客户大多只关心“这个人有没有拿手机”,不关心“拿的是哪个牌子”。检测出手机的位置后,后续才能接业务逻辑——比如判断手机是否靠近耳朵、是否在操作屏幕、是否在口袋里亮着屏。

这个定位直接影响数据集制作策略:我只需要保证手机目标清晰、边界明确,不需要为每个品牌单独收集样本。有些公开数据集里手机分类特别多,品牌型号都分得很细,看起来丰富,但对单类别的手机检测反而是一种干扰。类别越单一,模型越容易收敛,误检率也越低。我在这份数据集里从头到尾只保留了一个标签,训练配置也更简单。

1.2 为什么选YOLO,而不是Faster R-CNN或SSD

选择YOLO不是因为它“新”,而是因为它最适合这个场景。手机检测经常要跑在实时视频流里,比如门店摄像头、课堂摄像头、工厂监控,帧率需求往往是25帧以上。两阶段的Faster R-CNN精度更高,但速度很难拉满;SSD速度快,但对小目标的效果不太理想。YOLO系列从v5到v8再到v11,速度和精度的平衡做得最好,而且ultralytics把训练、评估、导出封装得很干净,新手照着抄就能跑通。

YOLO的生态完整也是一个关键因素。训练完可以一键导出ONNX、TensorRT、OpenVINO这些格式,手机检测的落地设备往往是Jetson、树莓派、工业盒子这类边缘硬件,TensorRT加速后的YOLO模型能在很低的功耗下跑出不错的速度。我在T4上用TensorRT做过1080p视频流的测试,640分辨率输入,单卡具体能扛多少路视频取决于解码能力和batch策略,但YOLO本身不会成为瓶颈。这也是我一直推荐YOLO的原因:算法适配性强,工程化路径也成熟。

2. 2800张数据集是怎么攒出来的

2.1 数据来源与采集多样性设计

2800张听起来不多,但对于单类别目标检测来说,配合迁移学习完全够用。关键不是数量,而是多样性。我采集时特意覆盖了几个维度:场景包括室内、室外、办公桌、车内、街头;光照包括强光、逆光、夜间、室内灯光;手机姿态包括横屏、竖屏、放在桌上、握在手里、靠近耳边;遮挡程度包括全目标可见、被手部分遮挡、被其他物体遮挡。这些维度直接决定了模型能不能在真实环境里站稳脚跟。

数据来源主要有三块。一是自己用手机和相机拍的,贴近真实业务场景,这部分占大头;二是从公开数据集里筛选,很多通用目标检测数据集本身就有手机类别,抽出来重新整理;三是在合规前提下收集身边设备拍摄的素材。最后一块一定要处理好隐私,拍摄时避开可识别的人脸和车牌,或者后期打码。人脸不是我们要检测的目标,打码不影响手机检测,但能省掉一堆麻烦。

容易忽略的一点:不要只拍固定角度。如果你只在桌面上从上往下拍,模型对平视、斜视场景几乎失效。我建议每张图尽量模拟真实摄像头的视角,也就是稍微带点俯角,不是水平正对屏幕。真实监控都是有一定高度的俯拍,数据分布贴近实际使用场景,模型才会好用。

2.2 清洗和筛选标准

数据采集完成后,我过了一遍人工筛选。标准有三条。第一,模糊和运动拖影的直接删,这类图对训练没有帮助,反而会让模型学到错误特征。第二,手机在画面里占比过小的保留一部分,但不能太多,否则模型学不到“手机长什么样”。第三,重复背景的只保留有代表性的几张,避免某一场景在训练集里一家独大,导致模型对特定背景过拟合。

清洗这一步我用脚本做了辅助。先让预训练的YOLO模型跑一遍粗筛,把没有检测到任何手机类别的图片筛出来人工确认,检测到的部分再抽查。这样能节省大概三分之一的人工时间。粗筛不是为了生成标注,只是为了排除明显不合格的图片,减少人工浏览量。清洗完的数据集大概损失了百分之十的图片,剩下的都是清晰、目标可见、场景有区分度的样本。

2.3 数据增强的正确姿势

YOLO训练内置了丰富的增强操作,比如Mosaic、随机翻转、颜色扰动、随机缩放。但增强不是越猛越好。我在2800张的基础上开了默认增强,又额外叠加了随机亮度和对比度扰动,训练时每个epoch看到的图都不一样,相当于把数据集扩大了好几倍。

这里有两个雷区。一是不要做改变目标语义的增强,比如把手机旋转180度。虽然目标还是手机,但真实场景里很少出现倒置手机,强行加入反而可能引入无用特征。二是不要过度使用Mosaic增强。Mosaic本身对小目标友好,但太强的拼接会让边界产生大量截断,模型对“手机完整形态”的记忆会变差。我这边Mosaic比例维持在0.8左右,并且在前10个epoch逐渐关闭,让后半程回归到真实构图。

3. 标注这一步,决定了训练上限

3.1 标注工具选型

标注工具我试过LabelImg、labelme、Roboflow,最后主力是LabelImg和Roboflow配合。LabelImg轻量,直接在本机跑,适合单机批量操作;Roboflow的在线标注和团队协作更方便,但网络环境要自己确认合规。如果只有一两百张图,用LabelImg完全够了;如果多人协作,Roboflow更友好。我不太建议一上来就用很复杂的工具,手机只有一类,画框是最简单的矩形框,不需要多边形,工具越简单,出错越少。

给新手一份工具建议:LabelImg用pip安装,启动后可以直接选择YOLO格式保存。它生成的txt文件每行格式是class x_center y_center width height,坐标已经归一化,省去后续转换。标注效率方面,一个人标一千张图大约要一个工作日,具体取决于每张图里的手机数量。我这份数据平均每张1.2个目标,总标注框大概3400个,两个人花了两个完整的工作日。

3.2 手机目标的边界定义

最有争议的问题:手机被手挡住了一部分,框怎么画?

我的原则是:框出手机可见部分的最大外接矩形,不凭空猜测被遮挡的部分。比如手机横屏拿着,手指挡住左下角,那么框的右边界是机身右边缘,上边界是屏幕上方边缘,下边界以可见的下边缘为准,左边界挡到哪算哪。不要脑补完整手机,否则框里会混入手指和背景,模型学到的是“手机加手”的组合,到了真实场景里手一换,就检测不出来。

第二个原则:手机放在桌上、拿在手里、放在耳边,只要可识别为手机就要框。屏幕亮着算,息屏也算,套着手机壳也算。只有一条充电线伸出来、机身完全在画面外的,不算。我在标注规范里专门加了一条:手机只有极小部分可见时,比如只露出一个角,不标注。这类标注会让模型学习到大量背景干扰,还不如不标。

3.3 转换成YOLO格式的要点

不管用什么工具,最后都要统一成YOLO格式。YOLO的标签是txt文件,文件名和图片名一一对应。格式为:class_id x_center y_center width height,其中x_center、y_center、width、height都是相对图片宽高的比例,取值在0到1之间。

转换时最常见的错误是坐标写反、归一化除以错误的分母、类别id从1开始。YOLO类别id从0开始,只有phone一类时,id就是0。我写过一个转换脚本,把PascalVOC的xml转成txt,核心逻辑就几行:

def convert(size, box): dw = 1.0 / size[0] dh = 1.0 / size[1] x = (box[0] + box[2]) / 2.0 y = (box[1] + box[3]) / 2.0 w = box[2] - box[0] h = box[3] - box[1] return (x * dw, y * dh, w * dw, h * dh)

注意检查:如果一个txt文件为空,代表这张图没有目标,训练时会被当作背景图。背景图不能太多,否则模型会偏向“什么都不检测”,但也不能完全没有,否则容易把所有东西都当成手机。我保留了大概百分之五的空标签场景图,而且专门挑了一些桌面上放着遥控器、充电宝、眼镜盒的图,让模型学会区分“像手机但不是手机”的东西。

4. 从零开始跑通YOLO训练

4.1 环境配置:零基础也能装好

YOLO训练现在最省事的方式是使用ultralytics库。环境配置三步走:先装Python 3.8以上版本,然后创建虚拟环境,最后pip install ultralytics。如果机器有NVIDIA显卡,还需要装好CUDA和PyTorch的GPU版本。没有显卡也能训练,只是会很慢。一两百张的小数据集用CPU能跑完,但几千张还是建议用GPU。

一个零基础容易卡住的点:CUDA版本和PyTorch不匹配。我的建议是别追最新CUDA,12.1左右最稳,PyTorch用官方命令对应安装。如果用的是云GPU,环境一般已经配好,直接pip install ultralytics就行。我在一块RTX 4060上,imgsz=640,batch=16,2800张数据集训练100个epoch大约花了两个小时,速度完全可以接受。

4.2 数据集划分与yaml配置

训练前要把数据集划分成训练集、验证集、测试集。我的划分比例是8:1:1。别看测试集只占10%,它对判断模型泛化很重要。划分时注意:同一场景的连续帧只能放到同一个集合里,绝不能同时出现在训练集和验证集中。否则验证集和训练集高度相似,指标虚高,部署到新场景直接露馅。

划分完成后写一个数据集配置文件dataset.yaml:

path: /path/to/phone-dataset train: images/train val: images/val test: images/test names: 0: phone

文件路径可以用绝对路径,也可以相对于path。names必须从0开始连续编号,这里只有一个类,所以只有0: phone。写错names或者路径不对,训练时会直接报错,最常见的错误是“AssertionError: train dataset not found”,八成是路径少了层级。

4.3 训练命令与参数选择

在ultralytics中,训练命令非常简洁:

yolo detect train data=dataset.yaml model=yolov8s.pt epochs=100 imgsz=640 batch=16

model参数可以指定yolov8n.pt、yolov8s.pt、yolov8m.pt等,分别对应不同大小的预训练模型。复杂场景用s或m,速度优先用n。手机检测不算特别难,我用n也能达到不错效果,但为了稳定还是建议s起步。如果不指定,ultralytics会自动下载预训练权重到本地,第一次训练会联网下载。

超参数方面,imgsz=640是默认值,对大多数场景够用。如果手机在画面里普遍很小,可以试试imgsz=1280,但显存消耗会变大。batch大小根据显存调整,一般用显卡显存的百分之八十作为上限。学习率不用改,默认的AdamW和自动调度已经调得很好。新手最容易犯的错误是epochs设太少,我先用50个epoch看趋势,稳定后加到100。如果到100个epoch损失还没完全平,再加也不迟。

4.4 训练过程监控与常见报错

训练开始后,控制台会输出每个epoch的train损失、val损失,以及precision、recall、mAP50、mAP50-95等指标。我习惯把结果可视化到TensorBoard,ultralytics会自动保存runs/detect目录下的训练结果,用浏览器打开就能直接看曲线,比纯看控制台直观得多。

常见报错我整理一下。显存不足时,把batch调小或者降低imgsz。数据标签格式不对时,报错信息会指向某个txt文件,检查是否有多余空格、缺列、坐标越界。权重下载超时一般是网络问题,可以手动下载后放到指定目录。还有“Zero division”错误,往往是因为某个类别在验证集中完全没有出现,检查一下划分文件。这些坑看着小,但每个都能卡住新手一两个小时。

5. 模型评估、调优与部署

5.1 指标怎么看:mAP和PR曲线

训练结束后,最关心的指标是mAP@0.5、mAP@0.5:0.95和precision、recall。mAP@0.5指的是IoU阈值为0.5时所有类别的平均精度,简单说就是“框得差不多的算对”。mAP@0.5:0.95更严格,从0.5到0.95每隔0.05算一次再平均,更适合评估精细定位能力。

我的数据集是单类别,最后mAP@0.5稳定在0.96左右,mAP@0.5:0.95在0.82左右。这个成绩说明定位基本靠谱。但我不会只看mAP,还会看precision和recall的平衡。precision高、recall低,说明模型非常“谨慎”,宁可不检也不误检;recall高、precision低,就是宁可错杀也不漏检。具体业务里,如果是安全监控场景,我更倾向于高recall,先保证把手机都找出来,再用后处理过滤误检。所以训练后不要只盯着mAP,要结合业务场景选一个合适的置信度阈值。

5.2 调优的几个实用技巧

如果模型效果不达标,我一般按这个顺序排查:数据质量、标注一致性、类别均衡、超参数、网络结构。在手机检测里,最容易出效果的是三件事。

第一,提升小目标检测能力,可以打开ultralytics自带的切片推理,或者把训练尺寸提高到1280,代价是推理变慢。第二,调整anchor。YOLO会自动学习anchor,但如果数据集里手机的长宽比很特殊,比如平板手机偏方形,可以关闭自动anchor并手动指定。第三,用更多负样本抑制误检,采集一些没有手机但长得像手机的东西,比如遥控器、充电宝、反光物体,标注成背景。

我自己早期遇到的问题是遥控器误检为手机。解决办法不是增加正样本,而是收集了两百张包含遥控器的背景图并标记为空,让模型明白“没有框就是没有目标”。这个操作对误检率的压制非常明显。

5.3 部署到实际项目的思路

训练完的模型导出方式很灵活。用ultralytics命令导出:

yolo export model=runs/detect/train/weights/best.pt format=onnx

ONNX是通用格式,可以再接TensorRT、OpenVINO或者OnnxRuntime。如果部署到Jetson上,我一般直接导出TensorRT引擎,速度比ONNX提升不少。部署时输入尺寸一般为640x640,输入RGB图像,输出是检测框。实际项目中,把摄像头帧resize到640,经过前处理、推理、后处理,得到每个检测框的坐标和置信度。

如果你跑的是1080p视频流,一次推理640x640的YOLOv8s在T4上大约几毫秒到十几毫秒,25帧每秒的项目负担不大。要支持更多路视频,可以用批处理或者TensorRT优化,但更常见的瓶颈其实是视频解码和数据拷贝,这部分就不只是YOLO能解决的了。

6. 常见问题与避坑实录

6.1 手机太小导致漏检

真实监控画面里,手机可能只有十几个像素大小。训练时特征很容易丢。建议先用原图训练一版,再看哪些图漏检。如果漏检的都是小目标,优先把imgsz提高到960或1280,其次让Mosaic增强的权重加大,给小目标更多上下文信息。另一个技巧是推理时做切片,把原始大图切成几个子图分别推理再合并结果,对小目标召回率提升显著,但推理时间会成倍增长,要提前算好算力余量。

6.2 把反光物体、遥控器误检成手机

误检说明模型学到了“矩形加高光”的组合特征,而不是真正的手机纹理。解决方法一是加负样本,二是检查标注框是否太松。如果标注框把手机周围的反光桌面也包进去了,模型就可能认为反光边缘是手机的一部分。我在复检时专门把边缘贴得太紧的标注放宽了一点,让框紧贴手机轮廓,误检立刻降了下来。第三是调高过滤置信度阈值,实际部署时把conf设到0.5以上,能滤掉大量低质量预测。

6.3 训练不收敛、损失震荡怎么办

常见原因有三个:标签格式错误导致部分图片没有正确读取;学习率过高;数据集里存在标注严重不一致的样本。建议每训练5个epoch就打开验证集图片看一眼预测结果,而不是只看损失曲线。损失震荡时先降低学习率,ultralytics可以设置lr0,比如从默认0.01降到0.005。另外,如果发现loss一直下不来,检查是否有目标框坐标越界了,有的标注工具会输出超出图片边界的框,YOLO读取后不会立刻报错,但训练效果会受影响。我写了个小脚本,把所有txt标签的坐标限制在0到1之间并打印越界样本,很快就能定位问题。

7. 数据集的下一步与个人体会

这份2800张的YOLO手机检测数据集,目前在我手头的几个项目里表现稳定,但我不认为它是个一步到位的产品。后续我至少会做三件事:一是补充更多夜间红外场景的数据,因为夜间监控的成像风格和白天差异很大;二是加入视频序列标注,连续帧可以让模型在时间维度上更稳定;三是尝试用YOLO实例分割模型,把手机从复杂背景中分割出来,对遮挡场景的效果会更好。

我最大的体会是,数据集的质量永远是第一位。同样的模型结构,用一份标注严谨、场景多样的数据,和一份随便标注的数据,效果可能是天壤之别。2800张图不多,但只要每一张都经得起放大检查,足够训练出能用于真实业务的检测器。如果你也要做类似的自定义目标检测项目,先把数据打磨扎实,再谈算法调优,这条路我是替你验证过的。

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

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

立即咨询