ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLOv8玻璃缺陷检测实战:从数据标注到部署推理

YOLOv8玻璃缺陷检测实战:从数据标注到部署推理 简介面向深度学习和目标检测开发者这是一套基于YOLOv8的玻璃表面缺陷检测可运行源码针对点状缺陷、划痕缺陷和擦伤缺陷三类问题提供从数据准备、模型训练到可视化检测的完整实现。资源共7个文件、约10KB包含3个Python脚本、1个YAML配置文件和1个TXT依赖清单分别对应训练流程、GUI检测界面、示例数据生成和运行环境说明结构精简便于快速调试与二次开发。已有95人学习。代码涵盖依赖安装、data.yaml创建、预训练模型加载、训练参数调整及准确率/召回率评估等关键环节搭配8000张玻璃缺陷图像数据集即可直接运行训练流程PyQt5图形界面还能实时展示检测结果降低入门门槛。适合刚接触YOLOv8的初学者也适合需要快速搭建缺陷检测方案的研究者参考。 玻璃缺陷检测一直是工业视觉里的硬骨头传统算法面对划痕、气泡、杂质这些目标时特征设计要费很大劲而且换一条产线、换一种光源规则基本就要推倒重来。YOLOv8出来之后这个问题的解法就变得直白多了——准备好带标注的缺陷数据训练一个检测模型推理阶段直接输出缺陷位置和类别。这篇文章我就围绕“YOLOv8玻璃缺陷检测[可运行源码]”这个项目把数据集制作、环境配置、训练调参、部署推理全流程拆开讲清楚重点说那些代码跑通之后你才会遇到的坑以及我怎么用GTX 1660Ti这种入门卡把模型练到可用的程度。这个项目适合谁如果你是做机器视觉的工程师刚接触深度学习目标检测或者你在学校做相关课题手里已经有一批玻璃缺陷图片但不知道从哪下手这篇内容应该能帮你省掉至少一周的试错时间。我会把GitHub上常见的“可运行源码”背后那些没写出来的细节补齐包括标注格式怎么转、增量训练怎么避免灾难性遗忘、损失函数曲线怎么看以及导出ONNX部署时容易忽略的细节。1. 项目整体设计与方案选型1.1 为什么玻璃缺陷检测选择了YOLOv8玻璃表面的缺陷有一个特点小目标多、对比度低、形态差异大。气泡、结石、划痕、夹杂物每种缺陷的尺寸可能只有十几个像素到几十个像素背景又是透明或半透明的玻璃本体。传统机器视觉用阈值分割加形态学处理只能搞定特定光照下、特定类型的缺陷一旦产品切换算法工程师就得重新调参维护成本非常高。YOLOv8的优势在于它是端到端的检测框架不需要手动设计特征。网络自己从数据里学习“什么是缺陷”对不同缺陷形态的适应能力远强于传统方法。相比YOLOv5YOLOv8在Backbone和Neck部分做了优化引入C2f模块替代原来的C3模块梯度流更丰富小目标特征提取能力有实打实的提升。加上Decoupled Head解耦头把分类和回归分成两个分支收敛速度和精度都比之前的耦合头更好。对于玻璃缺陷这种类别少、目标小的场景YOLOv8的性价比非常高。1.2 可运行源码的完整技术链路一个真正“可运行”的玻璃缺陷检测项目绝对不止是一堆训练代码。把它拆开来看完整链路包含四部分数据端原始缺陷图像采集、标注格式转换LabelMe/VOC格式转YOLO格式、数据集划分训练端YOLOv8环境搭建、预训练权重选择、超参数配置、增量训练策略评估端损失函数曲线、PR曲线、混淆矩阵、mAP指标分析部署端模型导出为ONNX/TensorRT、推理脚本编写、实时检测演示很多“可运行源码”只给了训练部分数据准备和部署部分一笔带过结果新手卡在第一步——标注完的数据不知道怎么转成YOLO格式。我后面会直接给出一段脚本解决这个问题这也是我踩过坑之后沉淀下来的东西。2. 环境配置与数据准备的关键细节2.1 环境版本与硬件适配先说环境。YOLOv8基于PyTorchPython版本建议3.8到3.11之间。我自己的实测环境是Python 3.10 PyTorch 2.0.1 CUDA 11.8GTX 1660Ti 6GB显存。这个组合在Ultralytics官方仓库的requirements.txt基础上没有额外装任何东西直接能跑。如果你是N卡用户CUDA版本确认很重要。命令行里输入nvidia-smi看右上角的CUDA Version那个是驱动支持的最高版本不是当前环境实际使用的版本。PyTorch实际调用的是你通过pip安装的CUDA运行时。所以哪怕驱动显示CUDA 12.2你仍然可以装CUDA 11.8版本的PyTorch只要驱动版本不低于要求的470以上就行。# 创建虚拟环境 conda create -n glass python3.10 -y conda activate glass # 安装PyTorch以CUDA 11.8为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装YOLOv8 pip install ultralytics6GB显存跑YOLOv8s是没问题的训练时把batch size设为8图片尺寸640x640显存占用大概在4GB左右。如果你只有4GB显存就换成YOLOv8n或者把batch降到4也能跑就是训练时间会长一些。别一开始就上YOLOv8x那个在没有24GB以上显存的卡上做训练基本是折磨自己。2.2 数据标注与格式转换是第一个大坑玻璃缺陷检测的数据集常见来源是产线相机采集或者网上公开的玻璃缺陷数据集比如东北大学的带钢表面缺陷数据集思路类似但玻璃的要自己攒。拿到原始图片后标注工具我推荐LabelImg或者X-AnyLabeling。前者轻量后者支持自动标注和交互式分割效率高不少。标注完导出的格式一般是Pascal VOCXML文件或者COCOJSON文件而YOLOv8训练需要的是YOLO txt格式每行一个目标格式为class_id x_center y_center width height坐标是归一化后的值。这里我直接给一个从VOC格式转YOLO格式的Python脚本实测可以直接用import os import xml.etree.ElementTree as ET from pathlib import Path def voc_to_yolo(xml_file, class_names, output_dir): tree ET.parse(xml_file) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) yolo_lines [] for obj in root.iter(object): class_name obj.find(name).text if class_name not in class_names: continue class_id class_names.index(class_name) bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h yolo_lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) txt_path Path(output_dir) / (Path(xml_file).stem .txt) with open(txt_path, w) as f: f.write(\n.join(yolo_lines)) # 使用示例 class_names [bubble, scratch, inclusion, crack] # 根据你自己的类别修改 xml_dir annotations output_dir labels os.makedirs(output_dir, exist_okTrue) for xml_file in Path(xml_dir).glob(*.xml): voc_to_yolo(xml_file, class_names, output_dir)这里特别提醒一下标注的时候框一定要贴合缺陷边缘不要留太多背景。玻璃缺陷本身对比度低如果标注框里包含大量正常玻璃区域模型学到的特征会被稀释收敛后精度会明显下降。我见过有人标注气泡时框比实际气泡大了两三倍最后mAP怎么调都上不去重新标了一轮数据立刻就好了。2.3 数据集划分与类别分布YOLO格式的数据准备好了接下来要准备数据集配置文件。目录结构建议这样组织glass_defect/ ├── data.yaml ├── train/ │ ├── images/ │ └── labels/ ├── valid/ │ ├── images/ │ └── labels/ └── test/ ├── images/ └── labels/data.yaml内容如下path: D:/projects/glass_defect # 数据集的绝对路径 train: train/images val: valid/images test: test/images nc: 4 names: [bubble, scratch, inclusion, crack]划分比例我建议训练集70%、验证集20%、测试集10%。注意一个关键点划分时要按“缺陷样本”划分而不是按“图片”划分。如果一张图片里有多种缺陷就把这张图片整体挪到同一个集合里千万别把同一张图的一部分缺陷分到训练集、另一部分分到验证集那样会造成数据泄露验证指标虚高。3. 训练核心配置与调参实战3.1 预训练权重选择与增量训练策略YOLOv8训练玻璃缺陷检测最关键的决策之一是用预训练权重还是从零开始训练。我的建议是用yolov8s.pt做迁移学习除非你的缺陷数据超过几万张否则不要从零训练。原因很简单玻璃缺陷数据集通常只有几百到几千张这点数据量不够网络从头学到底层特征而预训练模型已经在COCO上见过海量真实世界图片它学到的边缘、纹理、形状特征对玻璃缺陷同样适用。迁学习训练的时候默认情况下Ultralytics会冻结Backbone的权重吗不会整个网络都会参与训练。如果你希望保留更多底层特征只训练头部可以这样写yolo detect train dataglass_defect/data.yaml modelyolov8s.pt epochs100 imgsz640 batch8 device0 freeze10freeze10表示冻结前10层通常是Backbone部分只在Neck和Head上做微调。这种策略适合数据量很小几百张的情况能有效防止过拟合。如果数据量有2000张以上我一般不再冻结让整网络自适应调整效果更好。增量训练是另一个高频需求——产线上隔一段时间就会新增一批缺陷样本不可能每次都从头开始训练。YOLOv8增量训练很简单把model参数从上一次训练得到的best.pt开始接着跑就行yolo detect train dataglass_defect/data.yaml modelruns/detect/train/weights/best.pt epochs50 imgsz640 batch8 device0这里有个惨痛教训增量训练的学习率一定要调小建议lr00.001左右比正常训练小一个量级。如果还用默认的0.01新数据会把已经学好的特征冲掉出现灾难性遗忘表现为旧类别召回率骤降新增数据也没学好。我第一做增量训练就吃过这个亏损失曲线看起来在下降但推理时旧缺陷全部漏检后来把学习率降到0.001才恢复正常。3.2 损失函数曲线图怎么看训练过程中runs/detect/train/下会自动生成results.png这个图包含训练损失、验证损失、精度、召回率、mAP等曲线。很多新手只看train loss下降就觉得万事大吉这是不对的。正确看曲线的方式是同时对train loss和val loss两条线都平稳下降且最终收敛说明训练正常box_loss下降但cls_loss高位震荡说明类别区分度不够回看标注数据看是不是类别标签错了train loss持续下降、val loss拐头上升典型过拟合信号需要增加数据量或加正则化还有个容易被忽略的曲线是labels_correlogram.jpg它把标注框的中心点坐标和宽高分布画出来了。如果你的缺陷目标中心点集中在图片正中间而实际产线上缺陷可能出现在玻璃边缘那说明训练数据的采样有偏差模型泛化到实际场景时会出问题。看到这种情况要主动从产线采集更多包含边缘缺陷的样本补进训练集。3.3 GTX 1660Ti跑YOLOv8的真实体验我用GTX 1660Ti6GB显存跑完整个项目可以负责任地说这张卡跑YOLOv8s完全可行但需要一些策略。YOLOv8s imgsz640 batch8训练100个epoch大概需要4到6小时。如果换YOLOv8n时间可以压缩到2到3小时mAP会掉3到5个点。单张1660Ti推理一张640x640图片大概需要30到50毫秒也就是20到30 FPS。做离线检测完全够用但如果要上产线做实时在线检测要求30 FPS以上建议导出成TensorRT用INT8量化推理速度能提升到60到80 FPS。TensorRT这块细节比较多我在后面部署部分专门说。训练时还有个小技巧开启ampTrue默认开启混合精度训练。1660Ti的Tensor Core支持混合精度训练速度提升接近20%精度几乎没有损失。遇到训练时显存溢出优先减小batch其次是减小imgsz不要直接换模型不然训练时间翻倍。4. 常见报错与部署实操心得4.1 训练和推理中的高频报错我帮不少人排查过YOLOv8跑玻璃缺陷数据的报错这里整理几个出现频率最高的问题报错信息原因解决方法CUDA out of memory显存不足调低batch到4或2或者用YOLOv8nDataset not founddata.yaml路径配置错误检查path是否用了绝对路径路径不能含中文Expected 4D tensor...输入图片通道数异常检查图片是否损坏删除异常图片No labels found in ...标注txt和图片没有对应上确认txt文件名和图片文件名完全相同AssertionError: class number out of range标签中的class_id超出nc范围检查txt文件里的第一个数字是否小于nc这里要单独说一个问题数据损坏。玻璃缺陷数据集中经常混入一些从产线拷出来的损坏JPG文件图片本身打不开或者只有部分像素。YOLOv8加载数据时遇到损坏图片就会报错或者莫名其妙卡住。我写了个简单脚本提前清洗from PIL import Image from pathlib import Path img_dir Path(train/images) for img_path in img_dir.glob(*.jpg): try: with Image.open(img_path) as im: im.verify() except Exception as e: print(f损坏图片: {img_path}) # 记得同时删除对应的labels txt文件4.2 导出ONNX/TensorRT部署的实际操作训练收敛、验证mAP达标之后下一步就是部署。Ultralytics官方封装了导出接口导出ONNX很简单yolo export modelbest.pt formatonnx imgsz640 opset12导出TensorRT需要NVIDIA显卡命令也一行yolo export modelbest.pt formatengine imgsz640 halfTruehalfTrue表示FP16精度精度损失很小速度提升明显。这一步做完你得到的.engine文件就可以在TensorRT Runtime里直接跑了。实际部署时有个坑导出时输入的图片尺寸必须和推理时保持一致。如果你导出用的是imgsz640推理时输入图片如果是1280x720模型不会报错因为YOLOv8内部做了letterbox缩放但检测精度会受影响因为缩放比例和训练时不一致。正确做法是推理前先做letterbox让长边缩放到640短边填充为灰色。Ultralytics默认的predict方法会自动做这个处理但如果你手写推理代码一定要把letterbox这块处理好。代码方式加载引擎推理from ultralytics import YOLO # 加载TensorRT模型 model YOLO(best.engine) # 推理 results model.predict(test_image.jpg, conf0.25, iou0.45) # 结果可视化 for r in results: boxes r.boxes for box in boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) xyxy box.xyxy[0].tolist() print(f类别: {model.names[cls_id]}, 置信度: {conf:.3f}, 框: {xyxy})4.3 玻璃缺陷检测效果优化心得整个项目跑下来我的体会是模型结构层面的调整对最终效果的影响远小于数据层面的精耕细作。我在这个项目里尝试过给YOLOv8引入多头注意力机制MHSA替换过主干网络ConvNeXt V2精度确实有提升但涨幅有限一般就1到2个mAP点。真正让效果有质的飞跃是以下三个操作第一数据增强策略调整。玻璃缺陷是小目标默认的Mosaic增强虽然能提升模型鲁棒性但会导致小目标被裁剪掉。我在配置里把mosaic0.5降到mosaic0.3同时把copy_paste0.3如果使用YOLOv8的增强策略适当调高小目标召回率明显改善。第二负样本的使用。产线上大量图片是合格的玻璃没有缺陷。很多训练数据集只包含缺陷样本导致模型在正常玻璃上有误检。我在训练集里加入了约15%的无缺陷负样本标签文件为空模型的误检率降了一半以上。YOLOv8的训练流程支持空标签文件它能正常学习“这张图里没有任何目标”。第三测试时增强TTA。如果你对单张图片的检测置信度不满意推理时开启TTAyolo predict modelbest.pt sourcetest.jpg ttaTrueTTA会对同一张图片做多尺度缩放和翻转推理把多次预测结果融合精度会提升但速度会慢几倍。适合离线分析场景不适合实时产线。最后再分享一个小技巧。训练完成后除了看mAP一定要亲自拿几张产线实际拍的照片测试尤其是不同光照条件下的图片。我遇到过一次模型在训练集同分布的图片上mAP有0.92但拿到产线在清晨自然光条件下拍的照片API直接掉到0.7。后来发现是训练数据的亮度分布太集中模型把亮度当成了背景特征。解决办法是训练前对图片做随机亮度扰动这也算是数据增强日常被忽视但关键时刻救命的一个点。本文还有配套的精品资源点击获取
返回列表