ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

手机屏幕缺陷数据集300张带标签YOLO训练全流程指南

手机屏幕缺陷数据集300张带标签YOLO训练全流程指南 简介针对手机屏幕缺陷检测场景这一数据集专供YOLO系列算法进行目标检测训练与验证。资源包含300张手机屏幕缺陷图像及对应标注同时提供YOLO格式txt与VOC格式xml两种标签另附data.yaml配置文件可直接应用于YOLOv5、YOLOv7、YOLOv8、YOLOv9、YOLOv10及YOLO11等主流版本省去自制数据集和格式转换的时间。压缩包共901个文件涵盖300个jpg图像、300个txt标注、300个xml标注和1个yaml配置总大小仅14.37MB体量紧凑、便于快速部署。标签各字段含义清晰class、中心点坐标、宽高均按比例归一化训练时可直接调用。目前已有220人学习下载适合刚接触YOLO的初学者理解标注规范也可供质检项目开发者快速构建手机屏幕缺陷检测模型。1. 300张手机屏幕缺陷图够不够喂饱yolo算法做工业视觉的同行应该都有这种感觉模型结构不是门槛数据才是。拿手机屏幕缺陷检测来说产线上常见的划痕、亮点、暗点、脏污每一类要收集几百张现场图都不容易更别说还要一张张标框。标题里这个yolo算法-手机屏幕缺陷数据集-300张图像带标签.zip解决的问题很直接给一个能直接喂给yolo训练的最小数据集让你先把流程跑通再谈精度。300张这个数量说实话不算多但它是带标签的省掉了最枯燥的标注环节。yolo算法本身对数据量不算贪婪配合预训练权重和在线增强300张足够做一个能出指标的baseline。这个包更适合两类人一是刚接触目标检测、想用真实工业场景练手的二是产线上有定制缺陷类型、需要先验证yolo在这类图像上可行性的。网上讲yolo算法讲解ppt不少但真正卡住新手的往往不是网络结构而是数据从哪来、标签格式怎么转、训练脚本怎么填。这个数据集的价值就在这把最脏最累的活先干完了。2. 拆开压缩包先看家底标签格式与类别定义的两种可能拿到zip不要急着解压训练。先用三分钟搞清楚里面是什么格式这一步能避免后面一整天的翻车。2.1 目录结构与文件命名习惯常见做法是解压后看到类似下面的结构虽然具体文件名可能不同但逻辑基本一致phone_screen_defect/ ├── images/ │ ├── 0001.jpg │ ├── 0002.jpg │ └── ... ├── labels/ │ ├── 0001.txt │ ├── 0002.txt │ └── ... ├── classes.txt ├── train.txt └── val.txt有的压缩包会把标签直接放在图片同目录下命名也是同名txt这取决于打包的人采用VOC格式还是yolo格式。classes.txt里面存的是类别名一行一个顺序不能乱因为yolo的标签文件里第一个数字就是类别索引对应的是classes.txt里的行号。2.2 标签内容是关键VOC的xml和yolo的txt是两种玩法打开一个labels目录下的文件看一眼内容如果是这样的0 0.514648 0.482422 0.073242 0.158203那就是yolo格式五个数字依次代表类别索引、归一化后的中心点x、中心点y、框宽w、框高h。所有坐标都是0到1之间的小数是相对于原图尺寸归一化过的。这种格式可以直接训练不需要任何转换。如果看到的是xml文件那是VOC格式坐标是整数像素值而且有object标签包裹。这时候要先写个脚本转成yolo格式才能喂给ultralytics的yolo系列。转换脚本我在后面第3章给出。还有一种比较坑的情况标签是json格式那可能是labelme标注工具的产物这种格式需要不同的解析逻辑。判断标准其实很简单先看后缀再打开看第一行数字多且都是小于1的小数基本就是yolo或者是其它归一化坐标格式可以直接用是整数且是字典结构多半要先转换。2.3 手机屏幕缺陷数据集常见的类别体系屏幕缺陷在工业检测里类别叫法比较杂但综合行业习惯和数据集打包的常见做法这个包的类别大概率覆盖这几类划痕scratch、亮点bright spot、暗点dark spot、脏污stain、碎屏crack。有的会更细把亮点拆成亮斑和像素坏点但300张图如果分得太细每类样本数就会很少训练效果反而不稳。拿到classes.txt先数一下有几个类别。如果类别少于等于3个可以考虑用yolov8n这种小模型参数量少、收敛快适合小数据集如果类别在5个以上那就要认真做数据增强了否则每个类平均才几十个样本mAP很难看。3. 用yolo跑通最小训练闭环从数据校验到出权重把数据集从zip里解放出来之后我一般会按下面的顺序操作。每一步都验证了再往下一步走不要一口气全跑完那样出错很难定位。3.1 先把标签格式统一成yolo标准如果发现是VOC的xml标注先跑这个转换脚本。用python写依赖只有xml.etree.ElementTree和os不需要额外装包。import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, class_names, img_w, img_h): 将VOC格式的xml标注转换为yolo格式的txt xml_path: 单个xml文件路径 class_names: 类别名列表, 索引即类别id img_w, img_h: 图像宽高, 整数 tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_names: continue bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.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 cls_id class_names.index(name) lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) return lines这个脚本的核心逻辑是坐标系的切换VOC用左上角和右下角的绝对像素坐标yolo用中心点加宽高的相对坐标。注意宽高的计算用减法而不是绝对值这样即使标注框出现反向坐标也能兜住一部分异常情况。运行时需要从xml里读图像的宽高如果xml的size节点里有就直接读没有的话要用PIL.Image打开原图获取。这一步别偷懒归一化坐标一旦用错尺寸所有框都会便宜。3.2 用ultralytics包三行命令开始训练现在社区和产线用得最多的是ultralytics的yolov8系列。确认标签已经是txt且和图片同名同目录后写一个数据集描述文件# screen_defect.yaml path: D:/datasets/phone_screen_defect # 数据集根目录, 用绝对路径 train: images # 训练集图像目录 val: images # 验证集目录, 数据量小就先和训练共用 names: 0: scratch 1: bright_spot 2: dark_spot 3: stainpath这个字段要设置成解压后的根目录train和val写的是相对于根目录的子路径。数据量只有300张时如果压缩包已经分了train/val目录那就跟着它走如果没分建议自己按8:2切一下或者干脆val也指向全量先看loss曲线有没有收敛。训练命令我一般用下面这个默认参数基础上只改了epochs和batchyolo detect train \ datascreen_defect.yaml \ modelyolov8n.pt \ epochs80 \ batch16 \ imgsz640 \ device0几个参数的经验值imgsz用640屏幕缺陷这种小目标不要用太大因为标注框本身占比小放大图像不一定增益反而让显存吃紧。batch取决于显存6G显存跑yolov8n和imgsz640batch16没问题如果报CUDA out of memory就把batch降到8。epochs先给80小数据集训练非常快几分钟就能看到趋势跑完再根据loss决定加还是减。3.3 一个必须做的数据完整性校验训练前花5秒钟做个校验能省下不少排错时间。yolo对于标签和图像不匹配的情况经常是直接跳过训练或意外报错我用下面这段代码提前排查import os img_dir images label_dir labels imgs set(os.path.splitext(f)[0] for f in os.listdir(img_dir)) labels set(os.path.splitext(f)[0] for f in os.listdir(label_dir)) # 只匹配图片和标签共有的部分 common imgs labels print(f图片总数: {len(imgs)}, 标签总数: {len(labels)}, 匹配: {len(common)}) # 找出没有标签的图片, 这些图要么补标, 要么直接从训练集剔除 missing_label imgs - labels for name in list(missing_label)[:10]: print(f缺标签: {name})这个脚本解决的是最常见的标签文件和图片没对上的问题。解压出来的zip如果来自不同渠道经常有部分图片漏标的情况全量拿去训练不仅浪费算力还会让模型学到错误关联。4. 300张太少怎么补迁移学习与数据增强的组合拳300张带标签的工业图像直接从头训练yolo几乎不可能收敛但用预训练权重起步就完全是另一回事了。yolov8n.pt是在COCO上预训练过的模型已经学会了通用的边缘、纹理、形状特征。手机屏幕缺陷的特征——比如划痕是线状的、亮点是圆形小斑——在COCO的物体类别里没有直接对应但低层特征仍然可以迁移。这也是第3章里命令写modelyolov8n.pt而不是yolov8n.yaml的原因前者加载权重后者从头随机初始化。4.1 冻结骨干网络跑前20个epoch小数据集上最怕的是模型把背景纹理当成缺陷特征。我一般做法是前20个epoch冻结backbone只训练检测头让模型先适应新数据的分布20轮之后再解冻全部层微调。冻结操作在ultralytics里不用改代码通过参数控制yolo detect train \ datascreen_defect.yaml \ modelyolov8n.pt \ epochs80 \ batch16 \ freeze10freeze10表示冻结模型前10层对yolov8n来说差不多就是整个backbone。这个参数在数据量小、背景相对统一的时候特别有用能明显减少训练初期的震荡。4.2 在线增强参数怎么设ultralytics在训练时会自动做mosaic、平移、旋转、翻转等增强这也是300张图能跑起来的重要原因。但屏幕缺陷场景有两个特殊性一是缺陷可能出现在屏幕任意位置增强里的平移和缩放可以激进一点二是缺陷本身不旋转比如划痕方向固定、亮点是圆形的过度的旋转反而让模型学到错误的方向无关性。针对这个场景我会在训练命令里覆盖默认增强参数yolo detect train \ datascreen_defect.yaml \ modelyolov8n.pt \ epochs80 \ batch16 \ hsv_h0.01 \ hsv_s0.5 \ hsv_v0.4 \ translate0.2 \ scale0.3 \ degrees0 \ fliplr0.5 \ mosaic1.0hsv_h颜色色调扰动调得很低因为屏幕缺陷的颜色特征是分类的重要线索色调大幅偏移会让亮点变暗点degrees0关闭旋转fliplr0.5保持左右翻转因为屏幕左右对称翻转不会改变缺陷语义。这些参数都是跑过几轮之后根据验证集表现调出来的不同行业的数据集最优值差异很大但屏幕这类灰度背景占比高、缺陷以色块和纹理为主的场景这个组合算是一个稳妥起点。4.3 离线增强把300张变成900张的稳妥办法在线增强虽然每次epoch都会随机变化但样本多样性依然受限于原始图像数量。对于类别不均衡的问题我建议对样本少的类别做离线增强。用imgaug库可以对单张图生成多张变体import imgaug.augmenters as iaa import cv2 import os # 定义增强流水线, 注意和在线增强保持互补 augmenter iaa.Sequential([ iaa.GaussianBlur(sigma(0.0, 0.5)), # 模拟对焦差异 iaa.AdditiveGaussianNoise(scale(0, 10)), # 模拟传感器噪声 iaa.MultiplyBrightness(mul(0.8, 1.2)), # 模拟亮度波动 iaa.Affine(scale(0.9, 1.1), translate_percent{x: (-0.1, 0.1), y: (-0.1, 0.1)}) ], random_orderTrue) # 对指定类别的图像批量生成增强样本 def augment_rare_class(img_dir, label_dir, output_dir, class_id, copies3): for fname in os.listdir(img_dir): label_path os.path.join(label_dir, os.path.splitext(fname)[0] .txt) with open(label_path) as f: labels f.readlines() has_target any(line.startswith(f{class_id} ) for line in labels) if not has_target: continue img cv2.imread(os.path.join(img_dir, fname)) for i in range(copies): aug_img augmenter(imageimg) out_name f{os.path.splitext(fname)[0]}_aug{i}.jpg cv2.imwrite(os.path.join(output_dir, out_name), aug_img) # 标签内容不变, 因为增强操作不改变框位置 with open(os.path.join(output_dir, os.path.splitext(out_name)[0] .txt), w) as f: f.writelines(labels)这个脚本的关键细节是Affine里的平移和缩放都控制在很小的范围目的是不改变框的相对位置。如果平移比例超过0.3目标框的位置就会发生明显偏移那标签就得跟着重新算否则模型学到的就是错位特征。增强操作里不要加CropAndResize、Rotate这类会改变几何结构的算子只加噪声类、亮度类、模糊类标签文件才能原样复制。5. 训练翻车现场yolo训练常见问题与排查300张的小数据集前面工作都做对训练时依然有各种意想不到的状况。这些是我实际跑过的坑按现象到原因到解决的方式记录希望对你有帮助。5.1 box_loss震荡不收敛loss曲线像锯齿现象是训练到30个epoch之后box_loss还在上下跳动验证集mAP也涨不上去看起来模型像是没在学。原因大多是学习率过高或者是mosaic增强在样本量小的前提下导致目标框频繁拼接变形模型学到的是残缺目标而不是完整缺陷。解决把lr0从默认的0.01调到0.005mosaic0.5降低拼接概率。如果loss还是震荡把warmup_epochs从默认的3调大到5让模型先适应数据分布。5.2 验证集mAP很高但新图上一测就漏检这是一个典型的过拟合信号。300张训练图模型完全可能记住训练样本的颜色分布和背景纹理换张新图就不认识了。原因本质上是训练集和验证集来自同一批数据验证指标虚高。解决方法是训练时尽早引入独立的测试集比如从训练集里抠20张完全不同的图或者用留一法交叉验证每次训练拿掉20张图训练完在这20张上评估循环几轮看平均mAP。这个数字才是真实水平。5.3 亮点类缺陷一个都检测不到屏幕亮点是直径只有几个像素的小圆斑在640×640的输入里可能只占十几个像素。yolo的下采样倍数决定了它对小目标的敏感度上限。解决思路有两个方向。一是把imgsz提升到960或1280让小目标占据更多像素但显存和训练时间都上去了二是用yolov8的P2检测头在更大尺寸的特征图上做检测ultralytics里可以通过yolo detect train ... modelyolov8n-p2.yaml启用专门针对小目标场景。5.4 标题里说带标签但部分标签是空的300张图如果分给多人标注漏标空标签的情况很常见。训练时yolo不会报错但会在验证时产生大量漏检的假偏差因为图片里明明有缺陷标签却是空的。解决训练前把空标签文件列出来逐张用图像查看工具确认如果确实有缺陷就补标如果没有就保留。这一步不能省玄学mAP忽高忽低往往就是空标签在捣乱。5.5 换了环境重新训练指标和原来完全不一样同一份数据集换了显卡、换了ultralytics版本跑出来的结果可能差别很大。这不算bug但会让人很困惑。原因包括batch不同导致BN统计量变化、cuda版本不同导致卷积计算的微差异、ultralytics版本更新后默认增强参数改了。解决固定环境版本pip freeze requirements.txt归档依赖训练参数用配置文件而不是命令行散写这样实验结果才可复现。6. 验证一套模型值不值得上产线我在评估阶段盯住的三个指标训练结束拿到best.pt之后不要急着激动。先跑一轮验证看三个数字mAP50、mAP50-95、Precision。小数据集上mAP50容易虚高mAP50-95才是真实力。在验证集上跑一下评估命令然后把结果存下来yolo detect val \ modelruns/detect/train/weights/best.pt \ datascreen_defect.yaml \ conf0.25 \ iou0.5conf是置信度阈值低于这个值的预测会被丢弃iou是NMS的IoU阈值两个参数直接影响报告出来的mAP值。同一个模型用不同的conf评估mAP能差好几个点所以评估时参数要固定。我还习惯加做一步把验证集的预测结果可视化出来存成图片逐张看。mAP是统计指标门掩了单张图的问题比如把坏点误检成脏污这类混淆在数值上只会掉零点几个点但真正上产线的时候就是100%的误报。跑下面这个命令导出带预测框的图片yolo detect predict \ modelruns/detect/train/weights/best.pt \ sourcevalidation_samples/ \ conf0.25 \ saveTrue然后看预测框和真实缺陷有没有对齐、框是不是紧贴缺陷边缘。屏幕缺陷检测尤其要看框的边界框大了会把相邻的正常像素框进去产线判级时容易误判为更大面积的缺陷框小了则说明模型只学到了缺陷中心部分。我的经验是mAP50上90不新鲜但单类别的混淆矩阵才是能不能上线的关键。如果暗点和脏污互相混淆说明这两个类别的特征在模型看来太接近需要回到数据层面去补充边界样本而不是调模型参数。这算是这个方向的血泪教训了。最后说一个习惯每次调完参数我一定把当时的screen_defect.yaml、训练命令、评估结果三个文件放到同一个文件夹里哪怕当时觉得没用。因为小数据集上的实验波动很大今天看着涨了两个点可能只是随机种子的功劳隔几天再跑就回去了。有记录才能回头查是哪个改动真正起了作用。这个数据集方向值不值得做我的判断是值得但要有耐心。300张图跑出的模型可以作为方案可行性的证明也可以作为后续数据扩充的baseline但直接上产线还需要在真实环境里采集更多样本来迭代。如果本身是刚入门yolo做检测的学习者用这个包跑通全流程比看十遍yolo算法讲解ppt都管用。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进