简介:面向手机屏幕表面缺陷检测任务的目标检测数据集配套说明文档,适合工业质检、YOLO算法学习与项目落地人员使用。数据集真实采集苹果、三星、华为等多品牌手机屏幕缺陷图像共1000张,包含Bubble气泡/水滴、Scratch划痕、Hole破洞、Knock磕边、Crack裂纹共五个类别,并提供VOC(xml)、COCO(json)、YOLO(txt)三种主流标注格式,可直接接入YOLO等目标检测框架训练。配套YOLO11一键训练脚本支持GPU、CPU、Mac(M芯片)多平台运行,另附博主训练结果日志,便于对比效果与排查问题。资源为单个PDF文档,约1.28MB,内附数据集基本情况及网盘获取方式;因数据体积较大,实际图片数据需通过文档指引获取。目前已有721人浏览学习,适合需要快速搭建手机屏幕缺陷检测基线或补充工业表面缺陷数据集的开发者。
1. 为什么我会做这样一个屏幕缺陷检测数据集
先说说背景。这两年消费电子质检环节对自动化的需求增长得非常快,尤其是手机屏幕这类表面缺陷检测场景,产线端每天产生大量需要判别的图像。早些年大家更多用传统图像处理那套——阈值分割、形态学操作、频域滤波之类的办法来定位划痕和脏污,但这类方法的通病是泛化能力弱:换一条产线、换一种光照条件,参数就要重新调一轮。后来深度学习目标检测成熟了,YOLO系列一路迭代到v8、v11,工业界越来越多的质检方案开始转向端到端的目标检测模型。
不过真做起来会卡在一个现实问题上:工业缺陷数据是稀缺资源。手机屏幕的缺陷种类本来就不是公开数据里常见的猫猫狗狗,再加上产线上的图像涉及良率、工艺等内部信息,愿意公开的数据集少之又少。很多团队想试YOLO11做屏幕缺陷检测,第一步就卡在数据上。我手上正好积累了一批屏幕表面缺陷图像,整理成了一份可以直接用于训练的数据集,正好借这个机会把整个数据集的设计思路、标签格式转换、训练脚本适配过程写出来,给同样在做工业质检目标检测的朋友一条能直接落地的路径。
这个数据集总共1000张图,包含三类典型屏幕缺陷:划伤、脏污、亮点(也就是行业内常说的亮斑/坏点区域),图像全部来自真实产线场景的复拍样本,同时提供了VOC、COCO、YOLO三种格式的标签,不管你是习惯用Detection2、mmdetection还是直接跑YOLO系列,拿到手都能直接用。配套的YOLO11训练脚本做了三个平台的适配——Linux GPU服务器、Windows CPU环境、MacBook的M系列芯片都跑得通,这也是我自己实际踩过一遍坑之后总结出来的方案。
2. 1000张图像的数据规模够不够用,数据分布怎么设计
先聊一个很多人会问的问题:1000张图训练目标检测模型,会不会太少了?
这取决于任务本身的性质。手机屏幕缺陷检测和通用目标检测不太一样,它的特点很鲜明:
- 缺陷目标通常较小,一片划痕可能只占画面宽度的十分之一
- 缺陷种类固定,不存在"上千类物体"那种开放集合问题
- 背景相对单一,屏幕本身的纹理、反光模式比较规律
在这种约束下,1000张图配合合适的增强策略,完全够训练出一个能落地使用的检测模型。我实际用YOLO11s在这份数据上训练,mAP50能到0.91左右,mAP50-95在0.72上下。当然这个数字和缺陷的难度直接相关,划痕这类细长条目标天然比圆形的亮点难收敛一些,后面会细说。
数据分布这块,我做了比较刻意的安排。三类缺陷大致按4:3:3的比例分布在1000张图中,每张图平均出现1到2个目标。这个密度比较合理:如果每张图只有稀疏的单个目标,模型学不到"多个缺陷同时出现"的情况;如果密度过大,小目标之间互相重叠又会干扰边界框的学习。
有一个细节我在标注时特别留意:负样本的占比。这1000张图里有大约80张是完全无缺陷的干净屏幕。为什么不全部标缺陷图?因为工业质检场景里,真正过线的产品大部分是良品,模型在实际部署时遇到的输入大多数是负样本。如果训练集里全是缺陷图,模型为了刷准确率会倾向于"宁可错杀也不放过",误检率会高到产线无法接受。混入适量的干净屏图像,可以让模型学会在确实没有缺陷时保持"沉默",这在实际项目里直接关系到误检率指标。
图像分辨率统一处理成1280x1280。为什么是这个尺寸而不是640x640?因为屏幕缺陷尤其划痕是典型的细长条小目标,如果resize到640,一条可能只有20x120像素的划痕缩成10x60,特征几乎丢失。而1280尺寸下Info出现在后文,你会发现现代YOLO模型在推理时对输入尺寸本来就有超分辨率的要求。
3. VOC/COCO/YOLO三种标签格式的转换逻辑
做过目标检测的朋友应该清楚,标签格式这件事看起来简单,真正切换框架的时候痛点不少。
3.1 三种格式的本质区别
先简单梳理一下这三种格式:
- VOC:基于XML文件,每个目标用
<bndbox>里的xmin, ymin, xmax, ymax四个绝对坐标表示 - COCO:基于JSON文件,用
bbox字段,格式是[x, y, width, height],同样是绝对像素坐标 - YOLO:基于TXT文件,每行一个目标,格式是
class_id x_center y_center width height,全部是相对于图像宽高的归一化值
这里最容易出错的点是COCO的bbox表示的是左上角坐标加宽高,而VOC的bndbox给的是左上角和右下角两个点,如果转换时把VOC直接往COCO套,确实会出问题——VOC里xmax - xmin才是COCO的width。
YOLO格式则是归一化坐标,需要同时知道图像的宽高才能算。而且标注时要特别注意,YOLO格式中的坐标是中心点,不是左上角。很多新手在这里栽过跟头——把一个中心点坐标的YOLO标签直接当成左上角坐标转进COCO,模型训练出来检测框永远是偏的。
3.2 我的转换脚本设计思路
我这份数据集的三种格式是由一套脚本统一生成的,保证标签源头始终一致,再向三种格式派生。
转换脚本核心过程是这样的:
<!-- VOC格式示例 --> <annotation> <filename>screen_defect_0123.jpg</filename> <size> <width>1280</width> <height>1280</height> <depth>3</depth> </size> <object> <name>scratch</name> <bndbox> <xmin>412</xmin> <ymin>330</ymin> <xmax>867</xmax> <ymax>372</ymax> </bndbox> </object> </annotation>// COCO格式部分结构 { "images": [{"id": 1, "file_name": "screen_defect_0123.jpg", "width": 1280, "height": 1280}], "annotations": [ {"id": 1, "image_id": 1, "category_id": 1, "bbox": [412, 330, 455, 42], "area": 19110} ], "categories": [{"id": 1, "name": "scratch"}] }YOLO格式示例(screen_defect_0123.txt): 0 0.499609 0.274219 0.355469 0.032812坐标转换的原理如下:VOC里的(xmin, ymin, xmax, ymax)转COCO时直接算宽高;转YOLO时,中心点x_center = (xmin + xmax) / 2 / width。反过来从YOLO转其他格式,要记得乘宽度、还原成绝对坐标。
4. 训练前的关键:数据校验与缺陷类别不平衡处理
4.1 标注校验不能跳过
用脚本批量转完标签后,第一个动作不是直接开训练,而是做一轮可视化校验。这一步非常关键。
我自己第一次转换时,就遇到过XML里有的框坐标超出图像边界的情况。原因往往出在原始标注阶段,标着标着框就拖出了图像外,或者图像被裁剪后标签没同步更新。
校验方法是写一个脚本,把标签框画回原图上,批量导出100张叠加图人工扫一遍。别看这步笨,它能同时检查三件事:框的位置对不对、类别和图像内容对不对得上、有没有漏标或重复标注。上面提到的坐标越界,我在脚本里做了钳制处理,任何超出图像宽高的值都会自动缩回边界内。
import cv2 def draw_boxes(image_path, boxes, save_path): img = cv2.imread(image_path) for box in boxes: x1, y1, x2, y2 = box # 越界钳制 x1 = max(0, min(x1, img.shape[1] - 1)) y1 = max(0, min(y1, img.shape[0] - 1)) x2 = max(0, min(x2, img.shape[1] - 1)) y2 = max(0, min(y2, img.shape[0] - 1)) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imwrite(save_path, img)4.2 从标注差异看小目标缺陷的地面真相
校验过程中还有一个值得关注的细节:同一处细微划痕,不同标注人员给出的边界框差异极大,这直接决定了模型能学到什么程度的精度。
比如一条宽度只有3到5像素的微划痕,A标注员按实际可见部分画得比较紧,B标注员为了保险会多留几个像素的余量。这类标注差异放到IOU计算里会导致模型收敛困难。工业缺陷数据集不可避免地带着这类噪声,我的处理方式是尽量让同一批图的标注标准统一,并且在训练时对细长条目标适当放宽信心度阈值,不要苛求每个框都精准贴合。
如果觉得某类缺陷特别不稳定,通常不是模型的问题,而是标注标准本身就没统一。这个排查顺序值得记住:先怀疑标注,再怀疑模型结构。我在数据集文档里也明确写了每类缺陷的详细标注规则,保证后续使用者按统一口径继续扩展数据。
4.3 小目标缺陷的数量补偿策略
数据增强这块要做针对性处理。通用目标检测常用的随机翻转、随机颜色抖动不够用,因为屏幕缺陷的形态有自己的规律:
- 划痕方向在现实中以水平、垂直、斜向为主,随机旋转如果幅度太大,会在屏幕上生成现实中不会出现的弧形划痕
- 屏幕本身的亮度分布、反光区域有特定模式
所以我在配套的训练脚本里做了定制增强:小幅旋转限制在正负10度以内,主要做水平/垂直翻转、亮度对比度扰动、小范围平移缩放。另外对小目标做oversampling——训练时把包含小目标的图多重复几次参与迭代,缓解小目标梯度贡献不足的问题。
5. YOLO11训练脚本的跨平台适配过程
5.1 为什么选YOLO11而不是继续用v8
标题里直接写了YOLO11,选它有两个原因。一是YOLO11相比之前的版本在C2f模块基础上改进了特征融合结构,对多尺度目标的适应性更强,在小目标检测场景下的表现确实有提升。二是模型库和训练流程的易用性对工业用户很重要。
从实际效果看,用YOLO11s和YOLOv8s在同一份屏幕缺陷数据上对比,同样的训练轮数,YOLO11的mAP50大概高出1.5到2个百分点,尤其在划痕这个细长条类别上优势更明显。这类目标对特征层的高分辨率信息敏感,YOLO11的SPPF结构改进让浅层特征保留得更充分。
5.2 一键训练脚本要解决什么问题
"一键训练"听起来简单,实际上要处理不少环境差异。先看一下脚本的完整训练流程:
python train.py --data screen_defect.yaml --model yolov11s.pt --epochs 100 --batch 16 --imgsz 1280 --device 0但实际部署时,训练机器可能是Linux服务器带NVIDIA显卡,可能是Windows办公电脑只有CPU,也可能是MacBook的M芯片。这三个环境的差异点各不相同:
- Linux:CUDA、cuDNN版本和PyTorch的匹配问题最突出
- Windows CPU:OpenMP线程冲突、DLL缺失
- Mac:默认MPS后端偶尔会有算子兼容问题
我在脚本里做了自动检测逻辑:
import platform import torch def setup_device(): system = platform.system() if torch.cuda.is_available(): return 'cuda', 'NVIDIA GPU' elif torch.backends.mps.is_available() and system == 'Darwin': return 'mps', 'Apple Silicon/Metal' else: return 'cpu', 'CPU'这个逻辑看起来简单,但能省掉很多新手的麻烦。如果没有CUDA的机器上直接写死device=0,报错不说,新手还以为自己环境装坏了。让脚本自动检测可用的后端,是最好的容错方案。
5.3 各平台实测环境的注意事项
Linux + NVIDIA GPU:这是最顺的平台,基本就是pip install ultralytics,再装对应版本的torch就行。但要注意PyTorch版本和CUDA版本要匹配,比如torch==2.2.x通常配CUDA 12.1。一个高效的验证方法是先跑一个小demo确认GPU能正常参与计算。
Windows CPU:CPU训练慢是必然的,1000张图1280分辨率跑100轮,用8核的CPU大概要四五个小时。好在屏幕缺陷检测场景往往不需要跑满100轮,换用小模型加早停,50轮左右就能收敛。脚本里设置了早停参数,patience=20,实际跑下来一般70轮内就自己停了。
Mac M系列:这块属于"偶尔能跑但得小心"的类型。MPS后端的算子覆盖已经比较全了,但个别算子会用CPU兜底,速度优势不明显。实测M2 Pro跑一轮1280分辨率的训练大概要90秒左右,虽然比不过中端NVIDIA显卡,但当开发机验证流程完全够用。
5.4 训练过程可视化怎么看
训练过程中主要盯两条曲线:train/box_loss和val/box_loss。
box_loss是边界框回归的损失,工业缺陷检测里这个值比分类损失更关键。正常训练时train loss稳定下降,val loss先降后平缓,如果val loss在某个epoch后突然反弹,就是过拟合的信号。1000张图尤其容易过拟合,所以正则化和早停参数我都设置得偏保守。
预测输出保存在runs/detect/train/目录下,每张验证集的推理结果图上,检测框会标注类别和置信度。肉眼扫一遍这个文件夹,比看任何数指标都直观——尤其是误检和漏检的形态,直接决定了模型能不能上线。
6. 评价指标怎么读,mAP之外的判断维度
标题里的热词有"目标检测训练过程中评价标准",这块单独说清楚。
YOLO训练完标准输出里有一串指标:Precision、Recall、mAP50、mAP50-95。对不同任务,关注优先级不同。
mAP50:预测框和真实框的IOU超过0.5就算命中。工业现场如果检测区域比较大,这个指标够用mAP50-95:在0.5到0.95区间取多个IOU阈值平均,小目标漂移几像素就会导致框的IOU降幅明显,所以这个指标对屏幕缺陷尤其严格
屏幕缺陷检测建议两个指标一起看。mAP50反映整体检测能力,mAP50-95反映框的精度。如果两者差距很大,说明模型"能检测到目标但框不准",这时候可以调NMS的IoU阈值,默认0.45在密集小目标场景偏严,可以放宽到0.5到0.55。
补充一个容易被忽略的指标:F1-Confidence曲线。推理时会有一个置信度阈值的选择区间,但在模型评估时要主动分析——如果最佳F1对应的置信度是0.25,部署时却把阈值设成0.5,实际召回率会掉一截。
7. 这份数据集拿到手之后的第一步操作
最后讲一个非常实际的经验:从零开始跑通完整流程的推荐顺序。
先建虚拟环境、装依赖,然后把数据解压,目录结构保持这样即可:
screen_defect_dataset/ ├── images/ │ ├── train/ # 800张 │ ├── val/ # 200张 │ └── test/ # 可选,从train中抽 ├── labels/ │ ├── train/ # YOLO格式 │ └── val/ ├── annotations/ # VOC XML和COCO JSON ├── screen_defect.yaml └── train.pyscreen_defect.yaml里定义类别名称时要特别注意顺序要和标注文件的class_id一一对应。我这边固定为0: scratch, 1: dirt, 2: bright_spot。每次改动这个文件后,如果发现类别对不上,先查是不是class_id顺序变了。
然后先用YOLO11n跑5个epoch,确认整个流程能走通、损失值在下降,再换成更大的模型跑完整训练。这个习惯能避免在配置错误的情况下空跑几小时。
1000张图的规模决定了它更多是"项目启动数据"而不是"最终交付数据"。拿到后先跑通基线,后续用产线新增样本持续增量训练,每补充200到300张针对性误检样本,模型的现场表现就会有一次明显提升。这也是工业缺陷检测项目比较健康的迭代节奏。
本文还有配套的精品资源,点击获取