草庐IT

基于双孪生网络的表面缺陷无监督异常检测

E1 Dia61o 2023-04-08 原文

Unsupervised Anomaly Detection for Surface Defects with Dual-Siamese Network(基于双孪生网络的表面缺陷无监督异常检测)

1. 主流的工业异常定位(检测)方法

目前,基于深度学习的视觉检测在监督学习方法的帮助下取得了很大的成功。然而,在实际工业场景中,缺陷样本的稀缺性、标注成本的高昂以及缺陷先验知识的缺乏可能会导致基于监督的方法失效。近5年来,无监督异常定位算法在工业检测任务中得到了更广泛的应用。

中科院自动化所北京工商大学印度理工学院等单位联合发表最新的工业异常定位(检测)综述。20页综述,共计126篇参考文献。综述将工业异常定位方法根据不同的模型/方法进行分类和介绍,最新方法截止至2022年2月。同时,综述还包括了在完整MVTec AD数据集上的性能对比,并给出了多个工业异常定位的未来研究方向。

论文地址Deep Learning for Unsupervised Anomaly Localization in Industrial Images: A Survey

相关博客最新的工业异常定位(检测)综述 - 知乎 (zhihu.com)

1.1 基于图像重构的方法

基于图像重构的异常检测方法通常会用到三种模型结构:自编码器(AE)变分自编码器(VAE)生成对抗模型(GAN),其中应用AE的方法较多。基于图像重构的方法根据被检测图像与其重构后图像的差值来判断缺陷的位置和类型。

AE中的编码器先将数据压缩到一个隐空间中的中间表示(Bottleneck层),解码器再将其重构为输入图像。AE的Bottleneck层蕴含着输入图像隐空间中的特征信息,用Bottleneck层重构输入图像的方式使得对其泛化能力的控制十分困难。当AE泛化能力极强时,异常特征和正常特征混合在一起,导致网络输出直接复制输入,产生复制效应

如上图中(b)所示,基于AE的方法RIAD直接将缺陷区域也重建输出了出来,导致无法有效地检测异常。为了减小泛化能力的影响以避免复制效应,相关研究提出的方法有:(1)限制AE中隐空间的表达能力。包括Memory Bank、隐空间中的选择和加权、隐空间特征的聚类等方法。(2)将VAE或GAN集成到网络中。

然而,弱的泛化能力又会导致对一些细节的重构效果不佳而产生过检测问题。这些正常区域的异常得分可能会超过异常区域,如上图(b)的右上角所示。最新的基于VAE的模型FAVAE也一定程度上忽略了图像的细节,导致了如下图所示的过检测问题。

这种现象也表明基于图像重构的方法仅仅是倾向于用Bottleneck层压缩图像的内容而非学习其中有用的语义表示。虽然基于图像重建方法简单明了,但这种图像层面的方法在一些复杂的场景下(如复杂纹理,复杂背景,功能异常等)更容易失效。当面对一些缺陷样本时,重构过程中可能会产生复制效应,或者无法很好的重构输入图像而产生过检测问题

1.2 基于特征嵌入的方法

基于特征嵌入的异常检测和定位方法,大体被分为两个步骤:特征提取和异常估计。通过比较目标图像和正常图像的深度嵌入特征,生成最终的像素级别的图片。

用缺陷图像对应的特征嵌入向量和训练集中正常样本对应的特征嵌入向量的差来计算异常分数并定位异常区域。一些基于特征嵌入的方法如:PaDiMMKDS-TDFR等模型都在缺陷检测定位问题中表现出了优异的性能。

与基于图像重构的方法相比,基于特征嵌入的方法更注重于提取图像中的语义信息,因此在一些复杂场景下对不同缺陷类型和位置的把握更佳。

2. 双孪生(Dual-Siamese)网络

论文地址Unsupervised Anomaly Detection for Surface Defects with Dual-Siamese Network

不同于上述从图像级(图像重构)或仅从正常样本的特征(判别性嵌入)学习表示的方法,该算法充分考虑了正常和异常信息,并理解了正常和异常区域在特征层面上的位置关系。其将异常检测问题描述为双孪生网络框架下特征重构和修复的联合问题。该模型在MVTec AD数据集下多个类别的异常定位中获得了SOTA的结果。

2.1 模型结构

2.1.1 缺陷随机生成(DRG)模块

给定一个无缺陷的正常图像 I s I_s Is,可以使用DRG模块生成一个与其对应的有缺陷的图像 I g I_g Ig。其本质上就是生成一块缺陷部分 I s I_s Is并将其覆盖在正常图像上的某个区域上。首先,DRG生成任意形状的椭圆作为初始缺陷轮廓。然后,通过在椭圆轮廓上选取点并随机调整其位置,形成形状不规则的缺陷区域。利用新的缺陷轮廓,对随机亮度值进行填充,并进行进一步的高斯滤波操作,生成 I m a s k I_{\mathrm{mask}} Imask。 最终的缺陷图像 I g I_g Ig是将原始图像 I s I_s Is I m a s k I_{\mathrm{mask}} Imask共同叠加的结果。合成的缺陷图像中的缺陷有不同的位置,形状,大小和亮度。DRG的实现细节如下。

DRG模块的缺陷生成效果:

2.1.2 密集特征融合(DFF)模块

现有的一些基于判别性嵌入的方法中,只有最后的特征层才被用来判断是否有异常。文中的方法利用了多个层的特征,即在神经网络的不同深度产生特征,以提高异常检测性能。由于不同层的特征具有不同的感受野大小和尺寸,特征融合模块首先通过Resize实现所有特征的对齐。DFF模块实现不同层特征融合的操作包括:提取patch块,reshape和求均值。

首先,对齐后的特征进行提取patch块操作,从图像中获取块并将其放入depth的输出维度。然后对所获得的张量进行reshape,以确保最后一维中的特征通道数保持不变。通过对特定维度执行平均运算来生成新的特征图。最后,对每一层特征图进行拼接,形成最终的特征集 F D F_D FD。以两个Block结构特征图做特征融合为例示意图如下。 P P P表示每行/列划分patch块的个数,实验中设为4。 T T T表示特征提取网络每个Block结构中的卷积层数。

2.1.3 双孪生网络结构

该模型首先使用一个孪生结构的网络来提取无缺陷样本及其对应的由缺陷随机生成(DRG)模块生成的缺陷样本的判别性特征。然后使用密集特征融合(DFF)模块来获得两样本的密集特征表示。用第二个孪生结构的网络来感知缺陷并重建和修复前一阶段提取出来的的密集特征。该框架通过特征级而非图像级的重建和修补帮助正确理解缺陷区域和非缺陷区域的位置关系。同时针对性地处理正常和异常信息,文中提出的框架减少了因对正常区域判断差所带来的影响。

第一个嵌入特征提取的孪生网络为预训练的VGG19。其包含5个Block结构,前两个Block结构中含有2个卷积层,后三个Block结构中含有4个卷积层。因此第一个孪生网络的输出有16个特征图。孪生网络的第i层记作 φ i \varphi_i φi,将相应特征图的输出记作 f φ i f \varphi_i fφi,则第一个网络的全部输出可以表示为 F = { f φ 1 , … , f φ i } F=\left\{f \varphi_1, \ldots, f \varphi_{\mathrm{i}}\right\} F={fφ1,,fφi}。原始无缺陷的图像和DRG生成的相应的缺陷图像经过第一个孪生网络后的输出分别记为 F s F_s Fs F g F_g Fg

第二个用来感知缺陷的孪生网络的主要结构是自编码器AE。不同于现有的使用单一图像或特征图作为输入的方法,文中方法使用DFF模块的输出作为AE的输入。因此第二个孪生网络的两个输入分别为:正常样本的融合特征集 F D S F_{D_S} FDS和缺陷样本的融合特征集 F G S F_{G_S} FGS。并且,实验中用1×1卷积代替传统的AE中的3×3卷积,确保了特征信息的大小没有损失。AE中每个卷积层后连着BN层和ReLU激活函数层。为了进一步提高网络的重建和修复效果,实验中还在AE网络里加入跳跃连接。经过第一个VGG19孪生网络提取出的特征通道数达到了5504,实验中将AE中的隐空间维度设置为200。AE的具体结构如下表。

本文提出的双孪生网络结构实际上和深度特征重建网络DFR的思想比较接近。不同的是,作者采用了双孪生网络的框架,并且在其基础上创新性地设计了DRG和DFF模块。同时输入正常样本和缺陷样本,将之前的修复问题转化为重建和修复的联合问题。

2.1.3 训练和推理

  • 训练过程中的损失函数

目前主流的损失函数只是强迫自编码器重构输入,导致其在推理过程中无法很好地分辨缺陷和噪声。为了解决此问题,文中定义了新的损失函数,引导孪生网络通过重建和修复的联合行为来感知缺陷。定义 L r e c o n s t r u c t i o n L_{\mathrm{reconstruction}} Lreconstruction L i n p a i n t i n g L_{\mathrm{inpainting}} Linpainting两项分别代表重构过程和修复过程中的损失。定义 L r e c o n s t r u c t i o n L_{\mathrm{reconstruction}} Lreconstruction的目的在于使正常样本重构后的特征集 F A E s F_{A E s} FAEs和原正常样本的特征集合 F D S F_{D_S} FDS尽可能相近;定义 L i n p a i n t i n g L_{\mathrm{inpainting}} Linpainting的目的在于使缺陷样本修复后的特征集 F A E g F_{A E g} FAEg F D S F_{D_S} FDS尽可能相近。为了提高分割准确率和计算速度,两项损失均选择了一个像素级别的L2损失度量方式来定义,损失函数具体形式如下。
L total  = L reconstruction  + λ L inpainting  = ∑ j = 0 h − 1 ∑ i = 0 w − 1 ( F A E s − F D s ) 2 + λ ∑ j = 0 h − 1 ∑ i = 0 w − 1 ( F A E g − F D s ) 2 \begin{aligned} L_{\text {total }} &=L_{\text {reconstruction }}+\lambda L_{\text {inpainting }} \\ &=\sum_{j=0}^{\mathrm{h}-1} \sum_{i=0}^{w-1}\left(F_{A E s}-F_{D s}\right)^2+\lambda \sum_{j=0}^{\mathrm{h}-1} \sum_{i=0}^{w-1}\left(F_{A E g}-F_{D s}\right)^2 \end{aligned} Ltotal =Lreconstruction +λLinpainting =j=0h1i=0w1(FAEsFDs)2+λj=0h1i=0w1(FAEgFDs)2
式中, λ \lambda λ设为1以保持两损失项的相同范围,密集特征集合的尺寸为 h × w h\times w h×w

  • 推理过程

在推理阶段,仅用待检测图像验证双孪生网络的重建和修复性能,因此不需要通过DRG模块生成相应的缺陷图像,因此第一个孪生网络的两个图像输入均为 I s I_s Is。第二个孪生网络的两个分支分享权重,所以 F A E s F_{A E s} FAEs F A E g F_{A E g} FAEg在推理阶段相同。结果图像首先由第一个孪生网络输出的特征集 F D S F_{D_S} FDS和第二个孪生网络输出的 F A E s F_{A E s} FAEs的差生成,然后被resize成与输入图像相同的大小。

2.2 实验结果

2.2.1 MVTec AD数据集上的实验

实验以AUROC作为主要的评估指标,由下表可以看出文中提出的双孪生网络与其他方法相比在MVTec AD数据集的缺陷定位任务中得到了最优结果。

实验结果表明,文中的方法对于检测对象、形状和纹理的变化具有很强的适应性。下图中第二行为标签,第三行为文中提出方法的缺陷定位结果,可以看出其对缺陷的定位效果比较精细。

与其他主流方法的对比也说明了双孪生网络框架不易收到噪声的影响,定位准确度高,有一定的的优越性。

有关基于双孪生网络的表面缺陷无监督异常检测的更多相关文章

  1. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  2. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  3. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  4. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  5. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  6. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  7. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  8. 网络编程套接字 - 2

    网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

  9. SPI接收数据异常问题总结 - 2

    SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手

  10. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

随机推荐