工业异常检测是一个比较火热的话题,从传统的图像处理到现在引入深度模型的深度视觉识别,在这短短十几年的时间取得了很大提升。这样的提升主要体现在几个方面:1、检测能力越来越强大,从单一的异常检测到现在的多种类检测;2、模型越来越强大,从少数文件图片到现在深度模型需要的万级图像。但异常图像始终是个比较难获取的。在边缘GPU的加持下,深度模型取得了检测速度和检测精度的双平衡,这篇文章将从:1、原理解读,2、动手实践两个部分进行展开。恪守知行合一,争取做一些实际的工作,为像我这样强迫症带来一份酣畅。

| 图1 在工业异常数据集MVTec AD上的实测效果图 |
|---|
我们可以看到该技术提供了以下功能:1、异常区域叠加在原图上;2、显示出异常区域的热力图,橙色表示得分高的异常区域;3、异常区域边界用红色划离。因此,我们可以将工业异常检测的任务可以归类到图像分割。如果,能够进一步检测出是哪种异常类型,而不是简单的0-1分类,那么可以划分到具体的实例分割任务。

| 图2 在检测速度与检测精度面板上的性能对比 |
|---|
通过图2,我们不难发现该方法在取得接近80FPS(帧每秒)的前提下,还取得了超过99.5的分割准确率(I-AUROC)。这种又快又好的检测器,是一把解决行业需求的利器吗?经得起实战吗?
但是,有一个待解决的问题:以上方法只给出了检测的异常位置,但是属于哪种异常,是钢件上异常还是丝绸的呢?这个方法并没有给出。如果在某种材料上的异常不确定时,还能检测出来吗?所以,至少两个问题还需要进一步研究:1、实例分割;2、迁移分割或者鲁棒性检测。
在工业场景下,异常检测与定位特别难,因为异常样本很少,而异常类型多,比如从细小的划痕到大结构缺失等。更多的样例可参考图1。这样让基于有监督的训练比较难执行。
当前的方法为了解决这个问题,主要采用无监督的方式,即只采用正常样本来训练,只在测试过程中加入异常样本。比较常见的无监督方法有三种趋势:
为了解决上述问题,作者提出一个SimpleNet,能够利用合成和嵌入方法的优点,获得以下提升:

| 图3 SimpleNet的框架 |
|---|
它是一个非常流行的数据集,在异常检测与定位方面。它包含5中纹理,和10个物体分类,总共包含5354张图片。这个数据集通常由正常样本的训练集,和异常正常兼有的测试集构成。并且,它还提供了像素级别的标注用于异常图片测试。在作者的文中,它将所有类别当成一个分类,也就是所谓的冷启动异常测试,即作者在对应的正常训练样本上为每一个分类训练一个单分类器。没有使用数据增强,每一张图片都被归一化到256x256,中心切割224x224。
下图展示了当前数据集上的领先方法对比性能:

| 图4 SimpleNet与当前领先方法的性能对比 |
|---|
作者在a Nvidia GeForce GTX 3080ti GPU and an Intel®和Xeon® CPU E5-2680 v3@2.5GHZ的CPU上跑出了比PatchCore几乎快8倍的性能。

| 图5 更多的分割效果 |
|---|
按照github指示,几乎不花代价,很快就可以运行,
(pytorch-cifar) wqt@ser2024:SimpleNet$ bash run.sh
INFO:__main__:Command line arguments: main.py --gpu 0 --seed 0 --log_group simplenet_mvtec --log_project MVTecAD_Results --results_path results --run_name run net -b wideresnet50 -le layer2 -le layer3 --pretrain_embed_dimension 1536 --target_embed_dimension 1536 --patchsize 3 --meta_epochs 40 --embedding_size 256 --gan_epochs 4 --noise_std 0.015 --dsc_hidden 1024 --dsc_layers 2 --dsc_margin .5 --pre_proj 1 dataset --batch_size 4 --resize 329 --imagesize 288 -d screw -d pill -d capsule -d carpet -d grid -d tile -d wood -d zipper -d cable -d toothbrush -d transistor -d metal_nut -d bottle -d hazelnut -d leather mvtec /home/wqt/Datasets/MVTecAD/
INFO:__main__:Dataset: train=320 test=160
INFO:__main__:Dataset: train=267 test=167
INFO:__main__:Dataset: train=219 test=132
INFO:__main__:Dataset: train=280 test=117
INFO:__main__:Dataset: train=264 test=78
INFO:__main__:Dataset: train=230 test=117
INFO:__main__:Dataset: train=247 test=79
INFO:__main__:Dataset: train=240 test=151
INFO:__main__:Dataset: train=224 test=150
INFO:__main__:Dataset: train=60 test=42
INFO:__main__:Dataset: train=213 test=100
INFO:__main__:Dataset: train=220 test=115
INFO:__main__:Dataset: train=209 test=83
INFO:__main__:Dataset: train=391 test=110
INFO:__main__:Dataset: train=245 test=124
INFO:__main__:Evaluating dataset [mvtec_screw] (1/15)...
INFO:__main__:Training models (1/1)
INFO:simplenet:Training discriminator...
epoch:3 loss:0.25116 lr:0.0002 p_true:0.645 p_fake:0.668: 100%|█████████████████████████████████████████████████| 4/4 [00:49<00:00, 12.31s/it]
----- 0 I-AUROC:0.7534(MAX:0.7534) P-AUROC0.9586(MAX:0.9586) ----- PRO-AUROC0.845(MAX:0.845) -----
INFO:simplenet:Training discriminator...
如果能提供预测代码或者推理速度更好,但应该从project来看,貌似提供了一些函数,鉴于时间关系就没有再深入挖掘。但从这个项目来看,实用性如何,鲁棒性如何,值得探索。
主要对SimpleNet进行了原理解读,和效果分析。通过解读,我们知道当前主流的数据集,和任务,这给我们后续做检测提供了一个方向。