1. 工业质检的“火眼金睛”为何需要升级在工厂的生产线上质检环节就像是产品的“火眼金睛”任何微小的瑕疵——无论是芯片上比头发丝还细的裂纹还是金属外壳上一个不起眼的凹坑——都逃不过它的法眼。传统的自动化视觉检测系统大多依赖于预先设定好的规则和模板比如对比标准图像看看颜色、形状有没有偏差。这种方法对付一些简单、固定的缺陷还行但一旦遇到复杂多变的情况比如缺陷的尺寸大小不一、形态千奇百怪或者背景纹理本身就比较复杂这套“老办法”就很容易“看走眼”要么漏检要么误报。这几年随着人工智能特别是深度学习技术的发展基于AI的无监督异常检测方法成了工业质检领域的新宠。简单来说就是让AI模型只看大量的“好产品”正常样本图片学习“好产品”应该长什么样。当一个新的产品图片进来模型会尝试把它“脑补”成一个“好产品”的样子这个过程叫重建然后拿重建后的图片和原始图片一对比哪里对不上哪里很可能就是缺陷。这就像一位经验丰富的老师傅脑子里有“标准件”的样子看一眼就能发现哪里不对劲。在众多AI模型中扩散模型Diffusion Model最近风头正劲。它原本是图像生成领域的明星能画出以假乱真的图片。它的工作原理很有趣可以想象成两个过程一个是“破坏”过程给一张清晰的图片一步步添加噪声直到变成完全随机的噪点图另一个是“修复”过程模型学习如何从这堆噪点中一步步还原出最初的清晰图片。在缺陷检测任务里我们正好可以利用这个“修复”能力给一张有缺陷的测试图片加一点噪声然后让训练好的扩散模型去“修复”它。模型因为只学过正常图片所以它会倾向于把有缺陷的地方“修复”成正常的样子。最后对比修复前后的图片差异大的地方就是缺陷。听起来很完美对吧但我在实际项目里尝试应用这些方法时发现了一个很头疼的问题“一刀切”的重建策略。现有的方法通常给所有测试图片添加固定量的噪声然后用固定的步骤去修复。这就好比不管病人得的是感冒还是骨折医生都开同样剂量、同样疗程的药效果可想而知。具体来说问题出在两方面全局差异被忽视一张图片里可能只有一个微小的划痕另一张图片可能缺失了一大块结构。显然把缺失一大块“脑补”回来比抹掉一个小划痕要困难得多需要模型“思考”更久更多修复步骤。但现有方法不管三七二十一都用同样的“思考时间”导致对大缺陷重建不足对小缺陷又可能“过度修复”损失了正常区域的细节。局部差异被抹平即使在同一张图片内部缺陷区域和正常区域的重建难度也不同。模型在修复时理论上每一步预测的噪声都应该符合一个标准的分布。但缺陷区域和它应有的正常状态差异很大导致模型在这些区域预测的噪声会“跑偏”。如果整个修复过程都用一个标准正常区域的重建质量就会受到牵连。这就像用同一把力度和角度的刷子去修复一幅古画既要补上破洞又不能伤及完好的颜料实在太难了。ECCV 2024上提出的GLAD方法正是为了解决这个核心痛点而来。它不再“一刀切”而是像一位聪明的修复师懂得“看菜下饭”针对不同的缺陷类型和位置动态调整修复策略从而实现更精准、更保真的异常重建与检测。接下来我就带你深入看看GLAD这套“组合拳”是怎么打的。2. GLAD的核心秘籍动态调整与精准融合GLAD的全称是“Global and Local Adaptive Diffusion Model”翻译过来就是“全局与局部自适应的扩散模型”。这个名字就点明了它的两大法宝一是从全局图片层面自适应二是从局部像素层面自适应。它主要引入了三个关键创新自适应降噪步骤ADS、空间自适应特征融合SAFF和面向异常的训练范式ATP。我们一个一个来拆解。2.1 自适应降噪步骤ADS给每张图“量体裁衣”传统的扩散模型做重建可以简单理解为把测试图片x_test有缺陷加噪声加到某个固定程度得到x_t然后从这个x_t开始用训练好的模型一步步降噪去噪最终得到重建图x_recon理想中无缺陷。这个固定的加噪程度对应降噪的起始步骤T是人为设定的。GLAD认为这不对。它提出起始的噪声程度应该由图片自身的“异常程度”来决定。缺陷大的图需要加更多噪声从更“糊”的状态开始修复让模型有更大的“发挥空间”去想象正常的样子缺陷小的图只需加一点点噪声从比较清晰的状态开始修复避免不必要的细节损失。但问题来了我们怎么知道一张图该加多少噪声呢我们又没有它的“正常版本”作对比。GLAD想了一个很巧妙的办法让模型自己跟自己比。具体操作流程是这样的我们有一个预训练好的扩散模型它擅长从噪声中生成正常图片。对于一张测试图x_test我们先给它加一个很大的噪声得到x_T这是传统方法的起点。然后我们开始从x_T一步步降噪。每降一步我们就得到一张中间图x_t。关键来了在每一步我们不仅得到降噪后的x_t还会直接把原始的测试图x_test加上对应步骤的噪声得到z_t。注意x_t是模型“猜”的正常图加噪又降噪回来的而z_t是原始缺陷图直接加噪的。由于噪声的干扰直接比较x_t和z_t不公平。GLAD会把它们都转换回“无噪声”的估计版本利用扩散模型的数学性质然后计算这两个估计版本之间的差异作为“异常得分”。我们设定一个阈值。从T步开始降噪每一步都计算这个差异。当某一步t的差异小于阈值时说明模型降噪到这一步产生的图像x_t已经和直接给缺陷图加噪的z_t“看起来很像”了。这意味着从这一步t开始模型已经“认为”当前的图像状态足以代表一个“正常”的起点。于是我们不再从最初的x_T开始而是选择从这个t步开始再往后进行少量比如n步的降噪得到最终的重建图。这样做的好处极其明显对于只有小缺陷的图片可能很早比如第100步差异就小于阈值了那么我们就从第100步开始精细修复完美保留了正常区域的细节。对于有大缺陷的图片可能需要到第500步差异才足够小那我们就从第500步这个更“模糊”的状态开始给模型足够的“想象力”去补全缺失。这就实现了全局层面的自适应。2.2 空间自适应特征融合SAFF像素级的“精修”手术ADS解决了全局步骤问题但一张图片内部缺陷区域和正常区域的需求还是不同。缺陷区域需要“大刀阔斧”地修改正常区域则需要“小心翼翼”地保护。SAFF就是为了解决这个局部自适应问题。在通过ADS确定了合适的起始降噪步骤t后我们手头实际上已经有了两套“素材”素材A从第t步开始降噪n步后得到的重建特征图。这套特征图是模型“努力修复”后的结果缺陷区域被修正了但可能因为修复过程正常区域的细节也受到了一些“牵连”或模糊。素材B从最初的T步降噪到第t步时产生的中间特征图。这套特征图在降噪早期生成更多地保留了原始测试图包括缺陷的信息但对于正常区域其清晰度可能不如最终修复版。SAFF的核心思想是取长补短按需混合。它通过ADS过程中计算出的异常图生成一个软掩码m。这个掩码的值在0到1之间直接指示了每个像素位置是异常的可能性值越高越可能是缺陷。有了这个掩码融合就很简单了对于很可能为缺陷的区域掩码m值高我们更信任“素材A”修复后的特征因为这里的缺陷需要被修正。对于很可能为正常的区域掩码m值低我们更信任“素材B”早期保留细节的特征因为这里我们只想保留原貌不想被修复过程干扰。最终的融合特征 m * 素材A的特征 (1 - m) * 素材B的特征这个操作就像在Photoshop里做精细的图层混合用蒙版控制不同区域的透明度。它确保了在最终的重建结果中异常区域被有效重建而正常区域的纹理、边缘等细节得到了最大程度的保留。这一步是局部自适应的精髓。2.3 面向异常的训练范式ATP让模型“见过世面”前面两个模块ADS和SAFF主要是在推理即实际检测时的优化。但俗话说“巧妇难为无米之炊”如果模型本身的重建能力不强再好的策略也是白搭。传统的扩散模型只用正常图片训练它的“世界观”里只有“正常”是什么样。当面对一个从未见过的缺陷时它可能会不知所措预测的噪声会出现偏差导致公式上的不匹配影响重建效果。GLAD的ATP就是为了拓宽模型的“见识”。它在训练阶段就主动给正常的训练图片“制造”一些合成异常比如随机贴上一块纹理或模拟一个划痕然后让模型去学习如何把这些“人造缺陷”也给重建回正常样子。这样训练出来的模型其预测的噪声分布就不再局限于完美的标准高斯分布而是学会了如何处理“异常→正常”这种偏移。用论文里的话说这使模型“突破了标准高斯分布的限制”。当它在推理时遇到真实的未知缺陷就能更好地将缺陷区域映射到正常的特征空间从而生成更干净、更准确的重建结果。ATP可以看作是给模型做了一次“抗干扰”训练让它面对异常时更加从容。3. 实战效果GLAD真的更强吗理论说得再好不如实际跑分看看。GLAD论文在四个主流的工业异常检测数据集上进行了全面测试包括大家熟知的MVTec AD以及更具挑战性的MPDD、VisA和PCB-Bank数据集。结果可以说是相当能打。我整理了一下论文中的核心数据可以直观地感受它的优势。下表是GLAD与其他最先进SOTA方法在MVTec AD数据集上的平均性能对比重点关注图像级的异常检测I-AUROC越高越好和像素级的异常定位P-AUROC越高越好。方法类别方法名称I-AUROC (%)P-AUROC (%)备注基于重建的方法GLAD (Ours)99.398.9本文方法DiffAD98.798.2基于扩散模型UniAD98.597.8基于Transformer基于嵌入的方法PatchCore99.198.1特征记忆库SimpleNet99.098.1简单高效网络从表格可以看出GLAD在基于重建的方法中一骑绝尘无论是检测还是定位都达到了新的SOTA水平。即使与目前非常流行的基于嵌入的方法如PatchCore相比在定位精度P-AUROC上也具有明显优势。这意味着GLAD不仅能判断一张图有没有问题还能更精确地指出问题出在哪个像素点这对于工业质检中的维修和工艺改进至关重要。为什么GLAD的定位能力尤其突出这就要回到它的设计理念了。传统的重建方法对于大缺陷经常“补不回来”或者“补得不对”导致重建图和原图在缺陷区域的差异反而不明显因为都没重建好定位就会失败。而GLAD通过ADS确保了大缺陷也能被有效重建为正常区域通过SAFF确保了正常区域细节不丢失这样一增一减重建图与原始缺陷图之间的差异就精准地聚焦在了真实的缺陷区域得到的异常定位图自然就更准、更干净。论文中也给出了很多可视化对比。比如对于一块有巨大缺失的金属零件其他方法重建出来的图缺失处要么是模糊一片要么还是能看到空洞的痕迹。而GLAD重建的结果缺失部分被合理地“想象”并填补上了纹理连贯几乎看不出原缺陷。在定位图上其他方法可能只检测到了缺失区域的边缘而GLAD则能完整地勾勒出整个缺失区域。在MPDD这种光照、背景复杂的金属部件数据集上以及VisA这种包含多种物体类型的数据集上GLAD同样保持了领先优势。这证明了其自适应机制对于不同场景、不同缺陷尺度都具有良好的泛化能力。4. 自己动手GLAD代码实现与调参心得看完了惊艳的效果是不是手痒想试试虽然GLAD的官方代码尚未完全开源但基于其论文思路我们可以尝试用现有的扩散模型框架如PyTorch Diffusers库来搭建一个简化版的Pipeline理解其核心流程。这里我分享一些关键步骤和我在复现类似思想时踩过的坑。环境准备与依赖首先你需要一个支持CUDA的Python环境。核心库包括PyTorch, torchvision, 以及Hugging Face的Diffusers库它封装了Stable Diffusion等潜在扩散模型。为了特征提取和计算相似度我们还需要用到包含DINO或CLIP等视觉Transformer模型的库如timm或直接使用OpenAI的CLIP。# 基础环境 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 扩散模型库 pip install diffusers accelerate transformers # 图像处理与特征提取 pip install opencv-python pillow timm # 用于合成异常的数据增强库可选 pip install albumentations核心流程代码框架以下是一个高度简化的伪代码流程展示了GLAD推理过程的主干。import torch from diffusers import StableDiffusionPipeline, DDIMScheduler from PIL import Image import torchvision.transforms as T class SimplifiedGLAD: def __init__(self, model_pathrunwayml/stable-diffusion-v1-5): # 加载预训练的潜在扩散模型 (LDM) 和调度器 self.pipe StableDiffusionPipeline.from_pretrained(model_path, torch_dtypetorch.float16).to(cuda) self.pipe.scheduler DDIMScheduler.from_config(self.pipe.scheduler.config) self.pipe.unet.eval() # 我们通常只微调UNet # 加载特征提取器这里以DINO为例 self.feature_extractor load_dino_model() self.transform T.Compose([...]) # 定义图像预处理 def ads_find_start_step(self, test_image, max_T1000, threshold0.1): 自适应降噪步骤ADS寻找起始步数t # 1. 将测试图像编码到潜在空间 latent_test latent_test self.encode_image(test_image) # 2. 从max_T步开始逐步降噪并比较 for t in range(max_T, 0, -1): # 生成噪声 noise torch.randn_like(latent_test) # 获取当前步的加噪版本 z_t (公式1) z_t self.scheduler.add_noise(latent_test, noise, t) # 从z_t开始降噪一步得到预测的起始点 x_t_recon x_t_recon self.denoise_one_step(z_t, t) # 将 x_t_recon 和 z_t 转换到“无噪声”估计版本 (公式2) est_clean_x_t self.estimate_clean(x_t_recon, t) est_clean_z_t self.estimate_clean(z_t, t) # 计算两个估计版本之间的特征差异异常得分 diff_score self.calculate_feature_diff(est_clean_x_t, est_clean_z_t) # 如果差异小于阈值返回当前步数t作为起始步 if diff_score threshold: return t return 50 # 返回一个默认最小步数 def saff_fusion(self, latent_test, start_step_t, n50): 空间自适应特征融合SAFF # 1. 路径A: 从start_step_t开始降噪n步得到重建特征 feat_recon latent_recon, feat_recon self.denoise_steps(latent_test, start_step_t, n, return_featuresTrue) # 2. 路径B: 从max_T降噪到start_step_t得到中间特征 feat_intermediate _, feat_intermediate self.denoise_steps(latent_test, max_T, start_step_t, return_featuresTrue) # 3. 利用ADS过程中计算的差异图生成掩码m (值0~1) anomaly_mask self.generate_anomaly_mask(latent_test, start_step_t) # 简化表示 # 4. 特征融合 fused_feat anomaly_mask * feat_recon (1 - anomaly_mask) * feat_intermediate # 5. 将融合特征解码回图像 final_image self.decode_latent(fused_feat) return final_image def detect(self, test_image_path): 主检测函数 test_img Image.open(test_image_path).convert(RGB) test_img self.transform(test_img).unsqueeze(0).cuda() # 步骤1: 寻找自适应起始步数 start_t self.ads_find_start_step(test_img) print(fADS确定的起始降噪步数: {start_t}) # 步骤2: 执行SAFF融合重建 reconstructed_img self.saff_fusion(test_img, start_t) # 步骤3: 计算异常图 (对比原图与重建图) anomaly_map self.compute_anomaly_map(test_img, reconstructed_img) return reconstructed_img, anomaly_map # 使用示例 detector SimplifiedGLAD() recon_img, anomaly_map detector.detect(your_defective_product.jpg)关键参数调优与避坑指南ADS阈值threshold这是决定何时停止搜索起始步t的关键。设得太高模型会过早停止可能无法完全重建大缺陷设得太低则会过度降噪增加计算量并可能损失正常细节。建议在验证集上观察不同缺陷尺度下的重建效果选择一个能平衡召回率与重建保真度的值。可以从0.05到0.2之间尝试。特征提取器的选择计算diff_score和生成异常图时需要提取图像特征。论文使用了DINO-ViT。在实践中CLIP的ViT也是一个极佳的选择因为它对语义信息捕捉能力强。关键是保持训练和推理时使用同一套特征提取器。合成异常的策略ATP训练如果你要自己训练模型合成异常的质量至关重要。不要只用简单的随机噪声或颜色块。建议使用更逼真的数据增强如CutPaste裁剪粘贴、模拟划痕、污渍等或使用Perlin噪声生成更自然的纹理缺陷。这能极大提升模型对真实异常的泛化能力。计算效率ADS需要迭代尝试多个t这会增加推理时间。一个实用的优化技巧是采用二分搜索策略而不是从max_T线性递减可以大幅减少比较次数。内存管理扩散模型尤其是高分辨率下非常吃显存。在实现SAFF时同时保存多步的特征图可能会爆内存。可以考虑只缓存关键层的特征或者使用梯度检查点技术。5. 展望与思考GLAD带来的启发与未来方向GLAD的工作给我最大的启发是将生成式模型应用于判别式任务时精细化的过程控制比单一的端到端映射更重要。它没有去发明一个全新的网络结构而是在扩散模型这个强大的“发动机”上加装了智能的“变速箱”ADS和“差速器”SAFF让它能适应不同的“路况”缺陷类型。从工业落地的角度看这种自适应机制非常符合实际需求。产线上的缺陷千奇百怪GLAD提供了一种“弹性”的解决方案。不过正如论文最后提到的推理速度是目前的一个瓶颈。因为ADS需要多次前向传播来寻找最佳起始步这比固定步数的方法慢。在实际部署中这可能是一个需要权衡的问题。未来的一个有趣方向或许是训练一个轻量级的网络直接预测输入图片所需的降噪步骤t从而绕过迭代搜索的过程。另一个值得探索的方向是与轻量级检测框架的结合。GLAD的重建质量很高但整套流程计算量不小。也许可以将其作为一个小型“专家模块”与一个快速的、基于嵌入的初筛模型结合。让快模型先找出可疑区域再让GLAD只对这些区域进行高精度重建和确认这样既能保证精度又能提升整体吞吐量。在我自己的一些实验里我还发现对正常样本的建模纯度非常关键。如果训练数据中混入了未被标注的微小异常模型会将其学习为“正常”导致后续检测失灵。因此在使用GLAD或任何无监督方法前花大力气清洗和确保训练集的“纯净”是事半功倍的基础。总的来说GLAD为基于扩散模型的异常检测打开了一扇新的大门它告诉我们生成模型的能力不仅在于“生成”更在于对生成过程的“精准调控”。这种思想或许也能启发其他视觉任务如图像修复、超分辨率等让AI的“创作”过程更加智能和可控。对于从事工业AI落地的工程师来说理解并尝试这类方法无疑是提升系统鲁棒性和精度的有效途径。