根据读者反映,咱们的这个PCB素材设置的不对,应该是没有漆,铜线等等,应该是黑白的。额,具体我也知道,但没去过工厂,实在很难获得这些素材。。。
所以就当是一次瑕疵识别的实践,具体的数据集你可以自己定义。代码在Github:
Source code : https://github.com/Ixiaohuihuihui/Tiny-Defect-Detection-for-PCB

一点心路历程,供需要做瑕疵识别的同学参考。
PCB瑕疵识别是毕业设计的题目,要求能够定位印刷电路板上面的瑕疵位置和瑕疵类别。为了完成毕业设计,我们实验室同一级的6个小伙伴对这个印刷电路板瑕疵识别进行了一系列探索。

PCB数据集
现在几乎没有开源的PCB数据集,可以用于深度学习训练的PCB瑕疵数据集,所以我们实验室的wepon同学重点是制作了一个简单的PCB瑕疵数据集,包括拍摄PCB图像,瑕疵是PS的(因为工厂生产出来的很少有缺陷样本),标注数据集。需要注意的是:我们处理的PCB是裸板,也不是多层的。

你可以从这里下载数据集:http://robotics.pkusz.edu.cn/resources/dataset/

瑕疵包括六种:missing hole, mouse bite, open circuit, short, spur, spurious copper. 整个数据集有693张图片,一张图片上有3-5个瑕疵,并提供了相应的annotation_file。

数据集示例:

数据集里的图片是上图这样的,分辨率比较高。而且数据集比较小,所以我进行了一系列的data augmentation操作,包括裁剪,改变亮度等。

我实际跑实验的数据集如上图所示,600*600大小的图片,而且亮度也比原来的图片更高。

Source code : https://github.com/Ixiaohuihuihui/Tiny-Defect-Detection-for-PCB
My paper: https://digital-library.theiet.org/content/journals/10.1049/trit.2019.0019

一点经验
刚开始做印刷电路板的瑕疵识别是在2018年的3月,那时候经过调研,知道了有传统方法,最简单的是拿标准图片和待测图片进行pixel to pixel的XOR操作,这样可以得到瑕疵的位置。至于瑕疵的分类,可以设计一系列的规则,如欧拉数,连通数等。
我当时毕业设计走的不是这条路,而是转化为了分类问题。因为当时采集的数据库,没有标注瑕疵。比如说一张有瑕疵的图,和标准图片对比,知道可能有瑕疵的位置,然后把这个瑕疵位置抠出来,然后分类问题就比较简单了,我用过SVM+BoW, 还用了一个简单的CNN网络去分类,效果还不错。但这不是一个end-to-end的,即得到瑕疵位置和瑕疵类别是分开进行的。真心塞。。。但起码还是顺利毕业了,并且没有打算再研究瑕疵检测问题。
至此为止,我能想到的创新点有:(1)在提取瑕疵位置阶段,你可以设计robust feature,或similarity metric 去判断标准图像和待测图像哪里不同,这个位置就是疑似瑕疵位置;(2)在瑕疵分类阶段:可以做的工作多了,在当时,将深度学习运用到工业瑕疵检测也算一个创新点,不过现在不行了。在这个阶段,你可以设计合适的网络将深度学习运用到瑕疵检测上,也可以设计更合理的feature提取规则。
为什么要用deep learning? 弱语义信息不代表没有语义信息;PCB多种多样,传统方法不能适应所有的规则。
天有不测风云,研究生入学一个月以后,boss又要求我们做PCB的瑕疵检测。
这个阶段我就开始思考,瑕疵检测是一个目标检测问题,即给定一张待检测PCB图片,要回归出瑕疵的位置和得到瑕疵的类别。这就是大火的目标检测问题呀。
于是我直接用Faster R-CNN去训练了一个模型,https://github.com/smallcorgi/Faster-RCNN_TF, 效果不好,就没一个能检测出来的;总结原因有:图片太大了,瑕疵又非常的小,Faster R-CNN又不适合检测小物体;原来拍数据集的时候,亮度太暗了等等;
深度学习从低层到高层不断去提炼高层语义信息,特征的深入,层数的增大,细节的信息丢失得越来越多,对于缺陷检测,细节是很重要的东西。 
从这张特征可视化图片看到,随着提取特征层数的增加,电路板的特征越来越模糊 。(还能利用这种特征检测什么?
这是一个底层视觉任务,轻语义信息,重纹理信息。
接下来查资料,发现FPN适用于多尺度检测问题,最后我也是采用这个解决方案。说一下我的流程吧:
(1) 扩充数据集,最终的数据集有10668张,可训练的瑕疵有21664个。
(2)设计合理的anchor;
(3)不同尺度的特征融合,参考FPN;重点就是这个multi-scale feature fusion,提升小目标检测的关键;
(4)一些策略吧:roi align,ohem, soft nms
总结:设计合适的网络是关键,各种tricks都可以试一下,当然,数据集的质量也特别重要。
放一些我检测PCB瑕疵的效果图:

这是检测短路,是的,这是毕设时候P的瑕疵,好假。

这是检测的断路。这是入学以后P的瑕疵了,同学P的瑕疵还可以。

这是检测鼠咬,其中把P的那个圈圈也检测成missing_hole了,不过这种工业检测更担心的是漏检率,也就是recall。
总结
这个项目还是让我打下了一点目标检测的基础,好好学习。
————————————————
版权声明:本文为CSDN博主「keep_early」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dlh_sycamore/article/details/87886198

一、介绍
缺陷检测被广泛使用于布匹瑕疵检测、工件表面质量检测、航空航天领域等。传统的算法对规则缺陷以及场景比较简单的场合,能够很好工作,但是对特征不明显的、形状多样、场景比较混乱的场合,则不再适用。近年来,基于深度学习的识别算法越来越成熟,许多公司开始尝试把深度学习算法应用到工业场合中。

二、缺陷数据
如下图所示,这里以布匹数据作为案例,常见的有以下三种缺陷,磨损、白点、多线。

如何制作训练数据呢?这里是在原图像上进行截取,截取到小图像,比如上述图像是512x512,这里我裁剪成64x64的小图像。这里以第一类缺陷为例,下面是制作数据的方法。

注意:在制作缺陷数据的时候,缺陷面积至少占截取图像的2/3,否则舍弃掉,不做为缺陷图像。

一般来说,缺陷数据都要比背景数据少很多,没办法,这里请参考我的另外一篇博文,图像的数据增强https://blog.csdn.net/qq_29462849/article/details/83241797
最后通过增强后的数据,缺陷:背景=1:1,每类在1000幅左右~~~

三、网络结构
具体使用的网络结构如下所示,输入大小就是64x64x3,采用的是截取的小图像的大小。每个Conv卷积层后都接BN层,具体层参数如下所示。
Conv1:64x3x3
Conv2:128x3x3
ResNetBlock和DenseNetBlock各两个,具体细节请参考残差网络和DenseNet。
Add:把残差模块输出的结果和DenseNetBlock输出的结果在对应feature map上进行相加,相加方式和残差模块相同。注意,其实这里是为了更好的提取特征,方式不一定就是残差模块+DenseNetBlock,也可以是inception,或者其它。
Conv3:128x3x3
Maxpool:stride=2,size=2x2
FC1:4096
Dropout1:0.5
FC2:1024
Dropout1:0.5
Softmax:对应的就是要分的类别,在这里我是二分类。

关于最后的损失函数,建议选择Focal Loss,这是何凯明大神的杰作,源码如下所示:

def focal_loss(y_true, y_pred):
    pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred))
    return -K.sum(K.pow(1. - pt_1, 2) * K.log(pt_1))
1
2
3
数据做好,就可以开始训练了~~~

四、整幅场景图像的缺陷检测
上述训练的网络,输入是64x64x3的,但是整幅场景图像却是512x512的,这个输入和模型的输入对不上号,这怎么办呢?其实,可以把训练好的模型参数提取出来,然后赋值到另外一个新的模型中,然后把新的模型的输入改成512x512就好,只是最后在conv3+maxpool层提取的feature map比较大,这个时候把feature map映射到原图,比如原模型在最后一个maxpool层后,输出的feature map尺寸是8x8x128,其中128是通道数。如果输入改成512x512,那输出的feature map就成了64x64x128,这里的每个8x8就对应原图上的64x64,这样就可以使用一个8x8的滑动窗口在64x64x128的feature map上进行滑动裁剪特征。然后把裁剪的特征进行fatten,送入到全连接层。具体如下图所示。

全连接层也需要重新建立一个模型,输入是flatten之后的输入,输出是softmax层的输出。这是一个简单的小模型。

在这里提供一个把训练好的模型参数,读取到另外一个模型中的代码

#提取特征的大模型
def read_big_model(inputs):
    # 第一个卷积和最大池化层
    X = Conv2D(16, (3, 3), name="conv2d_1")(inputs)
    X = BatchNormalization(name="batch_normalization_1")(X)
    X = Activation('relu', name="activation_1")(X)
    X = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), name="max_pooling2d_1")(X)
    # google_inception模块
    conv_1 = Conv2D(32, (1, 1), padding='same', name='conv2d_2')(X)
    conv_1 = BatchNormalization(name='batch_normalization_2')(conv_1)
    conv_1 = Activation('relu', name='activation_2')(conv_1)
    conv_2 = Conv2D(32, (3, 3), padding='same', name='conv2d_3')(X)
    conv_2 = BatchNormalization(name='batch_normalization_3')(conv_2)
    conv_2 = Activation('relu', name='activation_3')(conv_2)
    conv_3 = Conv2D(32, (5, 5), padding='same', name='conv2d_4')(X)
    conv_3 = BatchNormalization(name='batch_normalization_4')(conv_3)
    conv_3 = Activation('relu', name='activation_4')(conv_3)
    pooling_1 = MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding='same', name='max_pooling2d_2')(X)
    X = merge([conv_1, conv_2, conv_3, pooling_1], mode='concat', name='merge_1')
    X = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), name='max_pooling2d_3')(X)  # 这里的尺寸变成16x16x112
    X = Conv2D(64, (3, 3), kernel_regularizer=regularizers.l2(0.01), padding='same', name='conv2d_5')(X)
    X = BatchNormalization(name='batch_normalization_5')(X)
    X = Activation('relu', name='activation_5')(X)
    X = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), name='max_pooling2d_4')(X)  # 这里尺寸变成8x8x64
    X = Conv2D(128, (3, 3), padding='same', name='conv2d_6')(X)
    X = BatchNormalization(name='batch_normalization_6')(X)
    X = Activation('relu', name='activation_6')(X)
    X = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same', name='max_pooling2d_5')(X)  # 这里尺寸变成4x4x128

return X

def read_big_model_classify(inputs_sec):
    X_ = Flatten(name='flatten_1')(inputs_sec)
    X_ = Dense(256, activation='relu', name="dense_1")(X_)
    X_ = Dropout(0.5, name="dropout_1")(X_)
    predictions = Dense(2, activation='softmax', name="dense_2")(X_)
    return predictions
#建立的小模型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
inputs=Input(shape=(512,512,3))
X=read_big_model(inputs)#读取训练好模型的网络参数
#建立第一个model
model=Model(inputs=inputs, outputs=X)
model.load_weights('model_halcon.h5', by_name=True)
1
2
3
4
5
五、识别定位结果
上述的滑窗方式可以定位到原图像,8x8的滑窗定位到原图就是64x64,同样,在原图中根据滑窗方式不同(在这里选择的是左右和上下的步长为16个像素)识别定位到的缺陷位置也不止一个,这样就涉及到定位精度了。在这里选择投票的方式,其实就是对原图像上每个被标记的像素位置进行计数,当数字大于指定的阈值,就被判断为缺陷像素。

识别结果如下图所示:

六、一些Trick
对上述案例来说,其实64x64大小的定位框不够准确,可以考虑训练一个32x32大小的模型,然后应用方式和64x64的模型相同,最后基于32x32的定位位置和64x64的定位位置进行投票,但是这会涉及到一个问题,就是时间上会增加很多,要慎用。

对背景和前景相差不大的时候,网络尽量不要太深,因为太深的网络到后面基本学到的东西都是相同的,没有很好的区分能力,这也是我在这里为什么不用object detection的原因,这些检测模型网络,深度动辄都是50+,效果反而不好,虽然有残差模块作为backbone。

但是对背景和前景相差很大的时候,可以选择较深的网络,这个时候,object detection方式就派上用场了。

七、关于源代码
这里的代码不再开源,因为设计到技术保密,感兴趣的话可以自己动手实现下,难度不大~
————————————————
版权声明:本文为CSDN博主「Tom Hardy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_29462849/article/details/84763421

基于深度学习识别模型的缺陷检测相关推荐

  1. 基于深度学习的高精度家禽猪检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度家禽猪检测识别系统可用于日常生活中或野外来检测与定位家禽猪目标,利用深度学习算法可实现图片.视频.摄像头等方式的家禽猪目标检测识别,另外支持结果可视化与图片或视频检测结果的导 ...

  2. 基于深度学习的高精度牙齿健康检测识别系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于深度学习的高精度牙齿健康检测识别系统可用于日常生活中检测牙齿健康状况,利用深度学习算法可实现图片.视频.摄像头等方式的牙齿目标检测识别,另外支持结果可视化与图片或视频检测结果的导出.本系统采 ...

  3. 基于深度学习的日志数据异常检测

    基于深度学习的日志数据异常检测 数据对象 智能运维(AIOps)是通过机器学习等算法分析来自于多种运维工具和设备的大规模数据.智能运维的分析数据对象多源运维数据包括系统运行时数据和历史记录数据,历史记 ...

  4. 基于深度学习的安卓恶意应用检测----------android manfest.xml + run time opcode, use 深度置信网络(DBN)...

    基于深度学习的安卓恶意应用检测 from:http://www.xml-data.org/JSJYY/2017-6-1650.htm 苏志达, 祝跃飞, 刘龙     摘要: 针对传统安卓恶意程序检测 ...

  5. 姿态检测 树莓派_基于深度学习的树莓派老人摔倒检测系统的制作方法

    本发明属于电子器件技术领域,涉及基于深度学习的树莓派老人摔倒检测系统. 背景技术: 日益庞大的老年群体已成为人们关注的焦点.由于老年人身体活动不便等特点,摔倒已成为我国人员伤亡的第四位原因,而意外摔倒 ...

  6. 第四篇:基于深度学习的人脸特征点检测 - 数据预处理

    在上一篇博文中,我们整理了300-W.LFPW.HELEN.AFW.IBUG和300-VW这6个数据集,使用Python将特征点绘制在对应的图片上,人工验证了数据集的正确性,最终获得了223034个人 ...

  7. 目标检测YOLO实战应用案例100讲-基于深度学习的自动驾驶目标检测算法研究

    目录 基于深度学习的自动驾驶目标检测算法研究 相关理论基础 2.1  卷积神经网络基本原理

  8. 基于深度学习的2D图像目标检测

    参见第一部分网址1,第二部分网址2 目前学术和工业界出现的目标检测算法分成3类:(参见一文读懂目标检测:R-CNN.Fast R-CNN.Faster R-CNN.YOLO.SSD) 1. 传统的目标 ...

  9. 基于深度学习特征的植物病虫害检测

     ABSTRACT 及时.准确地诊断植物病害,对于防止农业生产的损失和农产品的损失或减少具有重要作用.为了解决这类问题,可以使用基于机器学习的方法.近年来,在图像处理中应用尤其广泛的深度学习为精准农业 ...

最新文章

  1. Windows与Linux区别3
  2. python meshgrid()理解
  3. java url 授权_Java:如何使用UrlConnection发布请求与授权?
  4. 牛客网 【每日一题】5月9日 过河
  5. JSONObject与GSON的一些常用的方法的使用
  6. CSS background-position用法
  7. 2012服务器在IIS部署的SLL(https)网址谷歌浏览器无法访问的问题解决
  8. 某微型计算机字长为8位,单片机课后习题答案 - 图文
  9. Arduino智能小车直线控制-模糊PID控制
  10. Android Auto (AA)手机软件安装总结
  11. ios订阅的升级和降级
  12. springmvc防xss脚本注入攻击,springmvc过滤html和js标签,html和js标签转义
  13. 2021年9面试总结
  14. 用金字塔原则思考与表达
  15. 分享本周所学——人工智能语音识别模型CTC、RNN-T、LAS详解
  16. paa抗衰机器人的功效_PAA抗衰机器人,告诉你年轻不老的秘密
  17. 合肥火车站为乌鲁木齐疼痛男孩开辟绿色通道
  18. 内网穿透远程控制Windows主机
  19. Echarts配置项-2
  20. 面向对象有限元框架设计(OOFEM)

热门文章

  1. python中int表示的数据类型是_python中的基本数据类型之 int bool str
  2. 总线制和多线制示意图_知识||RS485简介及与其他总线网络的区别
  3. matlab生成ai图片,MATLAB绘图:导出矢量图
  4. textread函数_matlab基础textread函数实例
  5. 7-31 字符串循环左移 (C语言)
  6. mysql5.6.37驱动_mysql 5.6.37(zip)下载安装配置图文教程
  7. vue-ueditor 后端配置项没有正常加载_nginx配置websocket
  8. IOS 从系统图库中获取 图片 并设置为头像
  9. 批处理修改远程桌面端口,并修改相应的防火墙配置
  10. 《深入理解Hadoop(原书第2版)》——1.3大数据的编程模型