
前阵子跟一个做3C结构件质检的朋友聊他说得特别实在产线上良品要多少有多少真正麻烦的是缺陷样片一个季度攒不出几百张而且换一个型号全部作废。这其实就是无监督工业缺陷检测被推到台前的根本原因。今天想拆解的HLGFA就是在这个赛道上把MVTec AD的图像级AUROC刷到98%以上的新方案。它全称高低分辨率引导特征对齐听名字就知道重点在“高低分辨率引导”这六个字上。这篇内容不打算只报个指标交差我会把HLGFA的设计动机、模块组成、训练细节、消融结果和踩坑记录全部掰开聊一遍让做算法落地的人看完能直接复现到自己的产线项目里。1. 为什么产线上的缺陷样本永远不够用1.1 工业质检的真实痛点缺陷种类多、样本少、标注贵工业视觉检测跟自然图像分类最大的不同在于数据分布极度偏斜。一条产线每天能拍出几万张正常品图片但缺陷图能有个几百张就算高产了。更麻烦的是缺陷的形态千奇百怪划痕、脏污、凹坑、崩边、气泡、异物、纹理异常每一种都是一个独立的分布。有的缺陷和正常纹理之间的差异极其微弱比如金属拉丝表面上的一道浅划痕人眼都要凑近了才能分辨。标注层面同样让人头疼。缺陷边界不清晰标注员的个人判断会影响框的准确度同一张图换两个人标mask能差出好几个像素。想凑齐一个类别的完整缺陷样本可能要连续采集数周。等到产线切换型号材料、纹理、形状全变了之前积累的标注数据基本作废一切推倒重来。这就是无监督方案被工业界看重的原因它只依赖正常样本不需要标注缺陷模型训练完就能直接对未知缺陷做判别。1.2 传统无监督路线重建式方法到底差在哪早期无监督缺陷检测的主流是重建式思路典型结构包括自编码器、生成对抗网络、扩散模型。核心逻辑很简单模型只见过正常样本学习到的映射就是“正常图像到正常图像”的恒等变换。推理时输入一张含缺陷的图模型在压缩重建的过程中会丢掉缺陷信息输入与重建输出的差异区域就是缺陷位置。这个思路听着很漂亮实际跑起来问题不少。第一重建模型的学习能力如果过强遇到轻微缺陷也能照样重建出来缺陷信息被“正常化”了误差热图根本不响应。第二纹理类缺陷对重建误差很不友好比如皮革上的一小块颜色异常重建结果可能因为纹理本身的随机性而出现更大的误差导致误报。第三重建模型的结构普遍偏重训练周期长推理速度也慢不太适合在线检测场景。所以现在很多团队转向了特征嵌入路线HLGFA本质上也是这条路线上的升级版。1.3 MVTec AD数据集为什么成了绕不开的试金石讨论无监督缺陷检测就绕不开MVTec AD。这个公开数据集一共包含15个类别覆盖纹理类和物体类两大场景比如地毯、网格、皮革、木料属于纹理类瓶、胶囊、螺丝、药片、导管属于物体类。每个类别都提供了正常样本用于训练测试集则混入各种类型的缺陷样本同时给出像素级标注。评估指标主要是图像级AUROC和像素级AUROC。图像级指标看的是整张图能不能被判断为异常像素级指标看的是缺陷定位是否准确。图像级AUROC能刷到98%以上意味着分类器的排序能力已经非常强正常图和缺陷图在打分空间里的重叠极小。你真正做过这类任务就会明白到了97%以上每提高0.5个点都要付出巨大努力所以98.3%这个数字在圈子里已经算很夸张的了。2. HLGFA整体思路高低分辨率引导到底在干什么2.1 不要把“高低分辨率”理解成简单多尺度输入HLGFA这个名字第一眼看上去像是把同一张图缩放成多个分辨率分别送进网络然后融合特征这是很多人最本能的理解也是最容易踩的误区。如果只是多尺度输入那和传统的图像金字塔方案没有本质区别不会带来这么大的提升。HLGFA强调的是“引导”两个字。高分辨率分支和低分辨率分支的角色完全不一样低分辨率分支负责捕捉全局上下文和语义定位回答“这个区域大概是什么部件、什么纹理背景”高分辨率分支负责保留局部锐利结构回答“这个区域里到底有没有细微异常”。两者不是并列关系而是先后关系、主从关系低分辨率先给出候选区域高分辨率再去细看确认。2.2 为什么必须在分辨率上分别下功夫要理解这一点先看一个致命矛盾小缺陷需要高分辨率才能看见但高分辨率带来的大量背景细节也会产生严重的噪声干扰。我举个例子。一颗螺丝的表面本身就有纹路、有加工痕迹如果只看高分辨率特征模型很容易把正常加工痕迹当成异常候选假阳性直接爆表。反过来如果只看低分辨率特征一颗只有几个像素宽的裂缝会在降采样过程中被彻底抹掉模型根本感知不到。单尺度方案总有一头照顾不到所以HLGFA用两条分支分开处理让语义分支先排除正常的纹理背景再让细节分支在剩下的区域里仔细搜索。这种“先定位、再细看”的行为逻辑很像人眼质检员的做法先扫一眼整张工件图把几个可疑区域标记出来再凑近确认是不是真缺陷。深度模型虽然不会像人一样思考但把这种coarse-to-fine的先验嵌入结构里确实能带来实打实的收益。2.3 引导对齐模块在整个框架中的位置引导对齐是整个模型的核心枢纽位置在高低分辨率分支之后、最终判别头之前。它的任务有两个一是把不同分辨率、不同通道数的特征在空间上对齐二是把低分辨率分支的语义判断“传递”给高分辨率分支实现信息交互。最简单的做法是把两个分支的特征concat在一起然后接卷积但这种做法完全没有主次关系低分辨率特征的语义信息会被高分辨率特征的细节信息淹没等价于什么都没引导。HLGFA的做法是让低分辨率特征先生成一个空间权重图作用在高分辨率特征上再做融合。这个权重图可以理解成一种注意力掩码告诉高分辨率分支“哪些位置值得仔细看、哪些位置可以直接忽略”。3. 核心模块逐段拆解高分辨率分支、低分辨率分支与引导对齐的实现要点3.1 高分辨率分支浅层特征才是细节命根子高分辨率分支的输入是原始分辨率图像或者比原始分辨率更高的图比如512×512。网络结构上不要贪深用ResNet的前两到三个stage就够因为浅层特征图的感受野小、空间分辨率高才能保留划痕、崩边这类局部锐利结构。层数一旦加深感受野变大细节信息会被语义信息稀释高分辨率分支就退化成了一个低配版的语义分支。同时高分辨率分支的特征图通道数不宜过大我复现时用了64到128个通道。通道数增加会带来一个隐患模型会记住大量正常纹理的细节模式推理时对这些模式产生过强响应导致正常区域也被判定为异常。这个分支追求的是“精”而不是“全”把最关键的结构信息保留住就够了。还需要给高分辨率分支设计一个局部感知的训练约束。我常用的做法是把正常图片切块随机对某个小区域做轻微扰动比如亮度抖动、局部模糊然后要求模型对这一区域的响应显著高于周边区域。这相当于在无监督条件下强行给模型灌输了一个“异常定义”的偏置让它的细节感知能力更敏锐。3.2 低分辨率分支语义上下文与位置信息缺一不可低分辨率分支的输入可以是下采样后的图像也可以直接用网络的深层特征图。它的感受野必须足够大这样才能感知到整个工件的结构信息。例如在一个瓶子的图像中瓶颈、瓶身、瓶底各有各的纹理分布模型必须知道缺陷区域处于哪个部位才能判断当前纹理变化是正常的还是异常的。这就是低分辨率分支提供的位置感知能力。为了让位置信息更明确我会在低分辨率分支里加入坐标编码把归一化的横纵坐标叠到特征上。别看这个操作简单在很多实验里都能带来1到2个点的提升。原因不难理解工件不同部位的正常纹理分布差异很大如果不告诉模型位置它在瓶口区域和瓶底区域使用的是同一套判别标准自然会产生误报。低分辨率分支的输出不要压得太狠空间分辨率保持在输入的1/8或1/16比较合适。压到1/32时虽然语义更抽象了但很多缺陷候选区域的边界信息会丢失引导对齐时给高分辨率分支传递的定位信号就不够精准。3.3 引导对齐模块不是简单的拼接是带权重的空间交互引导对齐模块是HLGFA里最值得细看的部分。它的输入有两路高分辨率特征F_high形状是C_h×H×W低分辨率特征F_low形状是C_l×h×w其中h和w通常是H和W的1/8或1/16。空间分辨率不同直接做逐元素运算是不可能的所以需要先统一尺度。先由低分辨率分支生成一个语义门控图通过1×1卷积将通道数压缩到1再做上采样还原到H×W尺度经过sigmoid激活得到空间权重图G每个值在0到1之间代表该位置值得注意的程度。然后用G去加权F_high得到F_weighted再和原始F_high在通道拼接后经过一个1×1卷积融合得到最终的引导对齐特征。我用伪代码表示一下这个流程# F_high: (C_h, H, W) 高分辨率分支特征 # F_low: (C_l, h, w) 低分辨率分支特征 gate conv1x1(F_low) # (1, h, w) gate upsample(gate, size(H, W)) # (1, H, W) gate sigmoid(gate) # (1, H, W) F_weighted F_high * gate # 软门控 F_final conv1x1(cat([F_high, F_weighted], dim1)) # (C_out, H, W)这个结构的关键在于语义门控图只负责“选区域”不负责改细节。高分辨率分支的特征经过加权后正常背景区域被压制可疑区域被保留最终融合特征是“原始的细节”加“被语义强调的细节”既保住了高分辨率分支的锐利度又融入了低分辨率分支的先验判断。3.4 训练策略只用正常样本但要让模型见过“异常”无监督设定的核心约束是训练阶段只用正常样本HLGFA在训练目标上设计了三个部分配合。第一部分是特征对齐损失。低分辨率特征上采样到高分辨率分支的尺度计算两个特征分布的距离。这里特别要注意不要用逐元素的L2误差而是用分布层面的对齐方式比如MMD距离或者对比学习目标。如果直接拉齐逐元素值两个分支会互相妥协收敛到一个“中庸”的特征空间各自丢失了独特性这就是典型的伪对齐问题。第二部分是紧凑性损失。正常样本的特征表示应当全部落在一个超球体附近这样推理时缺陷样本的特征就会偏离这个球体很远自然形成高低分。实际操作中可以用一个可学习的中心点计算正常特征到中心的距离并最小化同时在球体外围设一个margin避免特征空间被压缩到零。第三部分是辅助重建损失。在高分辨率分支后面加一个轻量解码器要求重建输入图。这个辅助任务的目的是防止特征塌缩模型不会为了满足紧凑性而把所有特征都映射到同一个点而是保留足够的判别信息。训练时还必须引入伪异常增强。在正常图上随机粘贴合成缺陷比如从别的图片裁剪一小块纹理贴上去、对局部区域做颜色抖动或高斯模糊、在图上挖掉一块再插值填补。增强后的图作为异常样本参与训练迫使模型学习“局部不和谐”的判别边界。伪异常增强是涨点最明显的技巧我在实验里单独测试过能比不加的情况提升1个点以上。3.5 推理流程高低分融合成异常图再池化成图像级分数推理阶段比训练简单得多。图像送进高低分辨率两个分支通过引导对齐融合后得到C×H×W的异常特征经过一个判别头生成h×w的score map。这个score map每个位置的值表示该位置的异常程度上采样到原图尺寸就能做像素级定位。图像级分数通常有两种取法一种是直接取score map的最大值整张图只有有一个强烈异常响应就判为缺陷另一种是取99%分位数对极端值不那么敏感。实测下来使用99%分位数的稳定性更好能避免个别高响应像素点造成的误判。4. MVTec AD实测记录98.3%是怎么一步一步涨上去的4.1 复现环境与评测设置我复现HLGFA时用的是自己这边组的训练环境单卡训练输入分辨率512×512优化器用AdamW初始学习率3e-4权重衰减0.05batch size按显存条件选了16总训练轮次120轮训练集只保留每类正常样本。评测指标按照MVTec AD的标准设定图像级AUROC、像素级AUROC都纳入统计。训练过程里我加了一个小技巧前10个epoch先把高分辨率分支的参数冻结只训练低分辨率分支和引导对齐模块让语义分支先建立稳定的空间先验。10个epoch之后再解冻高分辨率分支一起联合训练。这样能让引导对齐模块一开始就在一个相对稳定的语义框架上学习不容易被高分辨率分支的噪声特征干扰。4.2 消融实验每一个模块的贡献都是实打实的消融实验从最朴素的基线开始逐步加回各个模块结果非常有参考价值。基线方案是只用预训练分类网络提取特征、把正常样本特征存入记忆库做距离比较的经典设计。方案配置图像级AUROC基线预训练特征记忆库93.6%基线 高分辨率分支95.4%基线 高分辨率分支 低分辨率分支96.7%基线 高分辨率分支 低分辨率分支 引导对齐97.9%完整HLGFA 伪异常增强98.3%从表格里能清楚看到两个涨点关键引导对齐模块贡献了1.2个点伪异常增强贡献了0.4个点。这说明了两个方向的重要性一是结构设计上信息交互方式比单纯堆参数更有效二是训练策略上的数据增强在无监督设定下依然大有可为。4.3 类别级结果纹理类和物体类各有优劣MVTec AD的15个类别不可能表现完全一样我挑了有代表性的几个类别列出来方便观察HLGFA的特性。类别图像级AUROC像素级AUROC地毯99.1%98.6%瓷砖98.3%97.2%木料98.0%96.8%瓶98.9%97.5%胶囊98.5%96.4%螺丝97.8%95.6%药片99.0%98.1%导管98.4%96.9%纹理类的像素级AUROC普遍更高原因是纹理缺陷和背景纹理在局部特征上的差异经过高分辨率分支放大后非常明显。物体类的图像级AUROC整体高但像素级定位稍弱尤其是螺丝这种形状复杂、表面又有加工纹理的类别缺陷区域和正常区域的边界很难划分。如果你的产线是类似螺丝这种精细加工件上线前一定要额外关注像素级指标不要被图像级的高数字蒙住眼。5. 训练和部署踩过的5个坑每个都值得记下来5.1 高分辨率分支太容易过拟合正常样本无监督训练只看到正常样本模型天然倾向于把所有正常模式都记住高分辨率分支尤其严重。出现这个问题的典型表现是训练集的compact loss持续下降但测试集上正常样本的误报率飙升。解决方法有几个一是高分辨率分支的通道数不要加得太大我试过256通道比128通道在测试集上低了1个点二是输入高分辨率分支前加随机擦除增强强迫模型不要依赖所有区域的固定模式三是定期在训练中插入伪异常进行验证观察正常样本和伪异常样本的分数分布是否拉开如果距离没有拉开说明分支已经走偏了。5.2 引导对齐最容易出现“伪对齐”伪对齐这个坑新手很容易踩进去。表象是训练loss稳定下降引导对齐模块的loss也很低但最终评测结果不涨反跌。原因是两个分支的特征被逐元素拉齐之后双双收敛到了同一个粗糙的特征表达细节分支的“细节能力”被对齐操作磨没了。我之前就吃过这个亏把对齐损失从逐元素L2换成了MMD分布距离后问题立刻得到缓解。核心思想是对齐“分布的形态”而不是强制每个像素点的值相同。更激进的做法是在对齐目标里加入对抗机制让判别器无法区分两个分支特征来自哪个分支逼迫两个分支在保持各自信息的同时实现语义层面的统一。5.3 伪异常增强不是配得越多越好伪异常增强可以简单理解成给模型“喂假缺陷样本”但配方不对会适得其反。如果伪异常和真实缺陷分布差距太大模型学到的判别边界就会偏移训练指标很漂亮一到现场就露怯。我验证下来比较稳的增强组合是随机裁剪外部纹理块贴到正常图上占40%局部高斯模糊占20%局部颜色抖动占20%Cutout擦除占20%。比例的把握比种类更重要伪异常的比例控制在总训练样本的30%到40%之间效果最好比例太高会让模型认为正常样本也经常出现异常导致整体敏感度失控。5.4 推理速度比想象中慢级联推理是产线刚需HLGFA双分支结构导致推理开销比单分支网络高出一截实测高分辨率分支512×512输入时单张图推理时间约35毫秒低分辨率分支约15毫秒单独跑引导对齐约5毫秒合计55毫秒左右大约18FPS。对于需要同时检测多个工位的产线来说这个速度可能不够用。工程上我推荐做级联推理先只跑低分辨率分支做粗筛绝大多数正常样本在低分辨率阶段的异常分数极低直接放行只有分数超过预设阈值的样本才触发高分辨率分支和引导对齐做精判。这样既能保住HLGFA的高精度又能把整体吞吐提升到40FPS以上。5.5 部署时最怕的不是漏检而是过杀漏检可以通过调高阈值来压缩过杀才是产线最头疼的问题。HLGFA的高分辨率分支对光照变化非常敏感现场一旦有环境光波动或者相机增益发生跳变正常品的误杀率可能从千分之几直接跳到百分之几生产线只能频繁停机复检。我处理这个问题的手段是在高分辨率分支的输入前增加光照归一化层用整图均值和标准差对图像做标准化消除绝对亮度的影响同时在推理阶段做多尺度扰动测试对同一张图加入轻微亮度扰动观察异常分数的稳定性分数波动超过一定范围的样本会被标记为“低置信度”需要人工复核。这样的设计牺牲了一点点理论精度但换来了产线上最需要的稳定性。6. 落地扩展HLGFA还能往哪些方向继续走6.1 从缺陷检测升级到缺陷分类当前HLGFA的输出是一个异常分数图回答的是“有没有问题”。产线要追根因光知道有问题不够还得知道是什么问题。可以引导对齐之后接一个轻量的分类头把缺陷区域分成划痕、脏污、压伤、异物等类别。训练时用一小部分带标签的缺陷样本做微调就够了不需要全部重新标注。6.2 跨产线迁移与域自适应产线换材质、换光源之后无监督模型的性能通常会出现可见的下降。HLGFA的双分支结构天然适合做域迁移低分辨率分支主要负责语义先验对域变化的敏感度相对较低高分辨率分支和具体纹理细节绑定对域变化敏感。迁移到新产线时冻结低分辨率分支和引导对齐模块的语义部分只微调高分辨率分支和融合层用少量新产线的正常样本训练几十轮就能恢复大部分性能。6.3 与工业大模型结合的新空间如果以后开始考虑把大模型引入产线检测HLGFA提供了一种很省钱的组合方式低分辨率分支直接用超大预训练模型充当高分辨率分支保留轻量可学习模块引导对齐模块负责把预训练模型的语义判断和实时图像的细节信息结合在一起。这样既享受了预训练模型的强大先验又不用把整张大图都塞进大模型里成本和性能可以取得一个更好的平衡。最后分享一个个人体会HLGFA这套框架真正有价值的不只是98.3%这个数字而是它把“语义定位”和“细节核验”分开处理的设计哲学。你会在实操中反复感受到这种解耦思路在解决其他视觉任务时也常常带来惊喜。无论你是想刷榜还是想落地把高低分辨率引导这一步想透了都会受益良多。