ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

磁瓦缺陷检测为何首选分割模型?YOLO11-seg落地实践

磁瓦缺陷检测为何首选分割模型?YOLO11-seg落地实践

磁瓦缺陷检测,为什么非得上分割模型?

做了几年工业视觉落地,我发现一个挺有意思的现象:一说做缺陷检测,很多人第一反应还是“目标检测框一下就行了”。但在磁瓦这类产品上,纯目标检测的方案,往往在车间现场跑不了俩月就会被工艺师傅吐槽到怀疑人生。

磁瓦是什么?简单说就是电机里用的瓦形磁性材料,长这样——半圆环状、表面要么是磨削后的亮面、要么是烧结后的暗面,尺寸不大,但表面缺陷的种类却不少:崩边、裂纹、气孔、划痕、凹坑、分层、霉斑,有时候还有细如发丝的应力纹。这类缺陷有个共同特点:形状不规则、边界模糊、对比度低,而且经常只占整块磁瓦面积的不到百分之一。

用矩形框去标这类缺陷,问题马上就来了:一个框里可能同时框住了缺陷和正常区域,训练出来的模型,定位精度根本满足不了产线要求。线上质检工人关心的其实不只是“有没有缺陷”,更是“缺陷在哪个位置、边缘到底延伸到哪里、面积大概多大”,因为这直接决定废品判级和后续磨削余量是不是够。

所以到了YOLO11这个阶段再做磁瓦缺陷检测,我的选择是:直接用分割模型(YOLO11-seg),把逐像素分类当成核心任务来做,缺陷边界用掩码输出,而不是用矩形框去凑合。这篇文章就是把整个项目从选型、数据、训练到部署,完整捋一遍,中间踩过的坑也一并说清楚。

1. 项目整体思路:从检测升级到分割,到底改了什么

1.1 矩形检测框解决不了的三个问题

先说说我为什么坚定地弃用纯检测方案。磁瓦缺陷的形态普遍有一个特点——长径比悬殊。崩边属于“边缘缺块”,裂纹属于“长条形”,气孔是“近似圆形”,划痕是“长条细线”。你用一个水平的矩形框去包住一条45度角的裂纹,你会发现框里90%以上的面积全是正常区域。

这带来三个连锁问题:

  • 训练监督信号稀疏且错位:矩形框内的背景像素占据主导,模型很难学到“缺陷的真实纹理特征”到底是什么,误检率居高不下。
  • 定位精度无法计算:客户要求你给出“缺陷边缘到磁瓦边界的距离”,矩形框根本给不出来,只能靠估算,这在一线交付时根本说不服工艺人员。
  • 面积测量失真:对于崩边、分层这类需要评估缺陷面积的场景,矩形框的面积和真实缺陷面积差了十倍以上,毫无参考价值。

分割模型的输出是掩码(Mask),逐像素标记“是缺陷/不是缺陷”,天然提供了边界坐标、真实面积、几何中心、最小外接矩形等全部信息,这些才是工业检测终端真正需要的数据。

1.2 为什么最终选定YOLO11-seg,而不是传统语义分割网络

一开始我试过U-Net系和DeepLabV3+这类经典语义分割方案,精度确实不错,但落地时暴露了两个致命短板:

  • 速度太慢:在边缘设备上,比如Jetson系列或者工控机上的消费级显卡,一个1024×1024的输入跑到50ms以上,产线节拍根本顶不住。
  • 预训练权重适配差:这类通用分割网络主要在自然图像数据集上预训练,迁移到工业近景表面纹理时,需要从头训练的时间成本太高。

YOLO11-seg的优势在于,它本身就是一整套目标检测+分割的混合体系。你既可以拿到实例级别的掩码,也能同时获得类别置信度和检测框,而且在推理结构上做了大幅优化,解码头共享特征,几乎不额外增加耗时。之前我在类似的小型工件缺陷检测项目上,用分割模型跑单张640×640的图,平均推理时间能压到20ms以内,这在产线现场是实实在在的优势。

不过我必须提醒一句:YOLO11除分割外也包含了分类、检测等多个系列,但做磁瓦缺陷,只建议用分割系列,不要用纯检测系列硬扛,否则后面后处理代码会越写越痛苦。

2. 数据准备与标注:90%的项目死在这里,而不是死在模型

磁瓦项目实际落地时,数据环节通常占掉整个工期的60%以上。很多团队在模型选型和训练调参上花了大把时间,最后发现效果上不去,回头一查,训练集本身就是个灾难现场。

2.1 磁瓦缺陷样本采集与清洗

工业相机采集的磁瓦图像有几个天然的特点:

  • 表面反光剧烈:磨削面会形成镜面反射,氧化铁皮和砂轮痕迹在图像上会形成大面积的高亮区域,缺陷信号经常被淹没在这些高亮噪声里。
  • 光照一致性差:不同工位的环形光源角度稍有偏差,同一块磁瓦在不同时段拍出来的图像灰度分布可以差到30%以上。
  • 小目标占比高:如果相机视野内同时拍多块磁瓦,每个缺陷可能只有20×20像素,这是小目标检测里最折磨人的工况。

采集阶段我的建议非常直白:宁可多拍,不要精修。每一条缺陷形态,至少拍够3个批次(不同光照、不同摆放角度、不同表面状态)。同时,把正常的合格品图像也大量纳入训练集,这部分通常占总量的40%左右,作用是抑制误检。

清洗环节,一个容易忽略的坑是:把模具压痕当成了缺陷标注。磁瓦表面在烧结阶段会有模具纹理,属于正常工艺特征,但如果标注员不懂工艺,会把它们全部标成裂纹,模型训练出来之后就会把正常产品全判为废品。所以标注之前,必须要让熟悉产线工艺的人先做一轮“缺陷白名单”评审,明确哪些外观特征允许存在。

2.2 标注标准与掩码细化技巧

分割模型最忌讳的标注问题就是:边界拖泥带水。我在验收标注结果时,通常要求标注员做到以下几点:

  • 所有缺陷使用闭合多边形精确描边,不允许用矩形框或者粗略的椭圆替代。
  • 崩边、缺口这类缺陷,多边形必须贴着磁瓦实际轮廓边缘走,不能留出一圈“安全余量”。
  • 裂纹类缺陷如果细到只有1-2像素宽,也要尽量以1像素精度标注,不要为了省事只标一小段。

如果标注工具用的是LabelMe这类开源工具,存出来的是JSON格式,每个对象包含多边形顶点坐标。转成YOLO分割格式时,要注意归一化坐标的计算方式:

import json import numpy as np def convert_labelme_to_yolo_seg(json_path, img_w, img_h, class_id): with open(json_path, 'r', encoding='utf-8') as f: data = json.load(f) yolo_lines = [] for shape in data['shapes']: label = shape['label'] # 这里根据自己的类别映射处理 label points = shape['points'] # [[x1, y1], [x2, y2], ...] # 归一化 norm_points = [] for x, y in points: nx = x / img_w ny = y / img_h norm_points.extend([str(round(nx, 6)), str(round(ny, 6))]) line = f"{class_id} " + " ".join(norm_points) yolo_lines.append(line) return "\n".join(yolo_lines)

这里有一个细节:多边形顶点的顺序必须是顺时针或逆时针的闭合顺序,不能乱序,否则训练时解析出来的掩码会变成自相交的多边形,损失函数直接崩掉。我见过不少新手在这上面反复踩坑,一个很土但有效的验错方式是:转换完成后,随便抽几张图,用OpenCV把yolo格式的坐标画回原图上,肉眼看一眼有没有乱序错位。

2.3 数据增强策略的取舍

磁瓦表面缺陷有个特殊性:它是典型的“纹理型小目标”,常规的几何增强(旋转、缩放、平移)可以放心用,但色彩增强要极其克制。比如Hue、Saturation这类改变色相的增强,在磁瓦这种灰暗金属表面上反而会引入虚假颜色特征,导致模型学到的颜色分布偏离真实工况。

我最终采用的增强组合如下:

  • 随机旋转(±30度):模拟磁瓦摆放角度的变化,但有崩边的样本不建议做超过15度的强旋转,否则边缘形态会失真。
  • 随机缩放(0.8~1.2倍):模拟相机工作距离的微小波动。
  • 平移与裁剪:注意裁剪时不要裁掉磁瓦的主要轮廓,否则崩边缺陷会被误判为正常边界。
  • 轻微亮度扰动:模拟不同工位光照差异,控制在±10%的灰度偏移以内。
  • Mosaic增强可以开,但建议比例不要太高,否则小目标的分割边界会被拼贴边界干扰。

我在前一个项目里试过把Mosaic开到1.0,训练出来的模型在独立测试集上的边界准确率反而下降了2~3个百分点。原因就是拼接图的边界处,块与块的灰度差异会生成虚假的“伪边缘”,模型很容易把这些伪边缘误学成缺陷特征。

3. 模型训练实操:从预训练权重到产出可用模型

3.1 预训练权重的作用到底有多大

磁瓦数据集通常规模有限,哪怕是工厂攒了一年,有效标注样本能有两三千张就算不错。而分割模型参数量大,从头训练极易过拟合。

这时候最重要的操作是:加载检测或分割任务的预训练权重作为初始化,把前几层卷积的纹理特征直接迁移过来。磁瓦表面虽然和自然图像差异大,但底层的边缘、角点、纹理基元特征是通用的,这部分不需要重新学。

加载预训练权重后,有一个关键操作很多人不知道:冻结前几个Backbone阶段的参数,只训练后半部分的特征融合层和分割头。我一般会先完全冻结Backbone的前5层,训练大约20个epoch之后,再解冻全部层参与训练。这样做的好处是,前期模型不会因为大学习率把预训练阶段学到的通用特征冲掉,后期再微调时又能逐步适配磁瓦表面纹理。

3.2 损失函数与样本不均衡处理

磁瓦缺陷检测中,不同缺陷类别的样本数量通常极不均衡,气孔、划痕可能几百个样本,而分层、霉斑可能只有五十个不到。如果直接训,模型会严重偏向高频类别。

YOLO11-seg本身的分割分支一般使用基于BCE的掩码损失,但这解决不了类别不均衡问题。我采取的做法是两路并行:

  • 加权采样:在构建DataLoader时,给少样本类别设置更高的采样权重,让每个epoch里少样本类出现次数不低于一个下限。
  • 复合成像:对少样本类别,我更建议用真实缺陷样本做ROI裁剪,然后以粘贴方式叠加到正常磁瓦图像上。这个操作虽然简单粗暴,但在工业缺陷检测里出奇地有效,比生成式模型合成靠谱得多——因为粘贴的缺陷边缘过渡,恰好可以模仿真实崩边在灰度上的突变效果。

当然,粘贴增强也有讲究,不能太假。缺陷粘上去之后,要对局部区域做边缘羽化和亮度匹配,让缺陷和背景的灰度分布融合得更自然。这一步我通常用OpenCV的羽化蒙版来实现:

import cv2 import numpy as np def paste_defect(bg_img, defect_roi, mask, x_offset, y_offset, feather_radius=3): h, w = mask.shape[:2] roi = bg_img[y_offset:y_offset+h, x_offset:x_offset+w] # 对掩码做高斯模糊,模拟边缘过渡 feather_mask = cv2.GaussianBlur(mask.astype(np.float32), (feather_radius*2+1, feather_radius*2+1), 0) feather_mask = feather_mask[..., np.newaxis] blended = roi * (1 - feather_mask) + defect_roi * feather_mask bg_img[y_offset:y_offset+h, x_offset:x_offset+w] = blended return bg_img

3.3 关键训练参数参考表

这个项目我训练的硬件配置很普通,一块消费级显卡(16GB显存),单卡训练即可完成。关键参数如下,可以直接参考:

参数项设置值备注
输入分辨率1024×1024磁瓦表面缺陷小,1024比640在分割边界上明显更细腻
Batch Size8如果显存不够,优先减小batch,不要强行降分辨率
Epochs300用早停法,验证集指标连续20轮不涨就停
初始学习率0.005(配合Warmup)大学习率+冻结训练前20轮
优化器SGD或AdamW均可分割任务我用AdamW收敛更稳
掩码损失权重0.4~0.6太高会让分类头被忽略
类别权重按样本数倒数归一化少样本类别权重不小于0.3
早停patience20 epochs实测最稳的配置组合

3.4 分割掩码的验证与可视化

训练过程中,我每10个epoch就保存一次验证集的推理结果,把预测掩码叠加在原始图上保存成图片,肉眼看边界质量。只看指标不看可视化,在大缺陷数据上经常会被“假高分”骗过——模型可能在分类指标上不错,但分割掩码边缘抖得像锯齿,这在工业检测里是不可接受的。

我用的验证指标组合是:

  • mIoU:主要看掩码和真实缺陷的重合度;
  • 边界F1(Boundary F1):如果只关注mIoU,长条形裂纹容易在边缘处被过度收缩,边界F1能反映这个问题;
  • 误检率:用完全正常的产品图去跑推理,统计有多少张被误判成有缺陷。工业现场最怕的就是这个指标失控。

4. 部署落地中的真实问题与排查记录

4.1 导出与推理的坑

训练好模型之后,下一步就是导出部署。YOLO11-seg导出ONNX或者TensorRT引擎时,有几个容易忽略的坑:

  • 动态尺寸必须显式指定:导出的动态轴要设置为固定输入尺寸(比如1024×1024),动态尺寸虽然灵活,但在一些推理框架里会触发额外的内存分配和预处理,速度反而更慢。
  • 输出维度别搞混:分割模型的输出通常包含检测头输出和掩码系数输出,推理时要正确拆分。我见过有同事把掩码系数当成了分类概率,导致输出的掩码全是乱码,排查了半天。
  • 半精度要注意溢出:磁瓦表面图像在近红外波段下灰度动态范围很大,如果转FP16推理时出现边界条带噪声,建议回退到FP32推理,或者做输入量化校准,而不是直接砍精度。

部署端的推理代码,我建议把预处理放到独立的线程里,不要和推理线程混在一起,否则CPU预处理耗时会把GPU推理的节省全吃掉。在工控机上实测,1024×1024输入下,CPU预处理大约占8~12ms,GPU推理只占15~18ms,如果串行跑,总耗时直接翻倍。

4.2 现场缺陷形态漂移

项目上线后遇到的最典型问题:模型在实验室测试集上mIoU接近85%,一上产线,误检率立刻飙升到每天几十条。

排查下来,根因是:现场相机白平衡、光源亮度、光圈快门参数和实验室完全不一致。磁瓦的灰度直方图在实验室里是集中在120~160的窄峰,现场则分布在60~220的宽区间。模型学习到的灰度特征瞬间失效。

解决办法有三个,按优先级排列:

  1. 采集现场真实图像加入训练集微调,这是最有效的,也是必须做的。上线前最好能现场跑一个小时的图像采集,把不同时段的光照变化都拍下来。
  2. 图像预处理端统一标准化:在推理前,把图像灰度直方图映射到一个标准区间。这个操作简单,但能显著降低不同工位间的灰度漂移。
  3. 光源控制器固化亮度参数:不要让产线工人随意调节光源亮度,这会把灰度基线彻底打乱。

4.3 分割边界不稳的处理技巧

模型训练得不错,但推理出来的掩码边缘在某些缺陷上有轻微波动,这种“活着但难受”的状态在落地时最磨人。我的处理方案是加一道轻量级后处理:

  • 对分割掩码做一次形态学闭运算(小内核,比如3×3),填平边界上的细小空洞;
  • 用多边形简化算法(Douglas-Peucker)提取掩码轮廓,去掉零碎的锯齿点;
  • 对崩边类缺陷,额外检测掩码与磁瓦整体边缘的重合关系,如果重合率超过80%,判定为崩边;否则可能是内部划痕或气孔。

这一套后处理全程不超过2ms,但能明显提高客户对“检测稳定感”的认可。工业现场很多时候要的不是算法多巧妙,而是输出结果让人一看就信服。

4.4 几条实战避坑清单

最后把整个项目里总结的几条避坑经验列出来,都是真金白银换来的教训:

  • 不要过度相信预训练模型在磁瓦上的直接表现:第一次跑测试集准确率不理想是正常的,关键看加数据微调后的收敛曲线是否平滑。
  • 标注质量永远比标注数量重要:一百张高质量标注图,效果可以好过一千张粗糙标注图。尤其是分割任务,边界不准确的标注会直接污染损失函数。
  • 分割结果一定要和工艺关联:崩边的掩码面积如果超过某个阈值,直接触发“废品”信号,这个阈值要和客户工艺人员一起定,不能自己拍脑袋。
  • 别忽略正常样本的占比:我最终训练集里,正常产品图占了接近40%。没有这些负样本,误检率压不住。
  • 推理速度测试要用现场真实尺寸的图,不要用小图蒙混过关:1024×1024和640×640的推理时间差了不止一倍,前期评估速度时就要按最终输入分辨率来。

5. 从检测到量测:分割模型带来的“额外”价值

这个项目做完之后,我发现自己对磁瓦这类产品的检测思路发生了转变。过去做缺陷检测,交付的是一堆“有/无缺陷”的判定;现在用了分割模型,交付的是一整套“缺陷几何档案”——每个缺陷都有边界坐标、面积、长宽、主轴方向、离心率、缺陷间距。这些数据放到产线信息系统里,能做的不只是判废,还能反哺工艺改进:比如统计连续一周的崩边缺陷主要集中在磁瓦的哪个弧段,就能反推是模具磨损了还是上料机构的定位偏移了。

这一点,在我看来是分割模型相对检测模型最大的优势——检测是终点,分割是起点。数据沉淀下来之后,工厂可以做缺陷趋势分析、工序能力评估、甚至预测性维护。客户可能一开始只要求一个“缺陷判定”,但当你把分割掩码附带的结构化数据放到他面前时,他自然而然会提出更深层的质量分析需求,项目价值也就完全不一样了。

按我个人经验,如果只是做“缺陷有没有”级别的检测,用轻量检测模型确实省事;但要往工业智能化走一步,分割模型的能力边界远大于检测框,尤其是在磁瓦这种缺陷形态复杂、量测需求强烈的应用场景里,这个方向值得坚定投入。

RELATED READING

延伸阅读

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