Automatic fabric defect detection using a deep convolutional neural network
Intro
本文提出用于纺织品的瑕疵检测方法,将原始图片看成由若干patch组成的图片,利用对patch间距离的定义,求取二阶微分的最大值,进而得到最佳patch size。然后,由于正负样本极度不均衡,作者对负样本的patch进行增广,使得正负样本满足3:2的比例,最后,将patch作为输入丢进神经网络训练。判别时,网络逐patch预测类别,因此时间开销比较大(一张图片运行patch的数量次神经网络)。
Automatically calculating the patch size
首先定义patch之间的距离,称之为DMF(Distance Matching Function).
对于一维信号,周期为(delta)的DMF定义为:
[lambda(delta) = sum_{i=1}^{N-delta} [f(i) - f(i+delta)]^2
]
上式N是信号长度,很好理解,就是每隔(delta)求欧式距离然后求和。
对于二维信号,也就是图像信号,只需要定义水平和竖直方向的DMF即可:
[lambda_r(delta) = sum_{i=1}^{N-delta}[f(r,i) - f(r,i+delta)]^2 \
lambda_c(delta) = sum_{i=1}^{M-delta}[f(i,c) - f(i+delta,c)]^2
]
定义DMF的一阶差分:
[Delta lambda_r(delta) = lambda_r(delta +1) - lambda_r(delta) \
Delta lambda_r(delta-1) = lambda_r(delta ) - lambda_r(delta-1)
]
定义DMF二阶差分:
[Delta^2 lambda_r(delta) = Delta lambda_r(delta) - Delta lambda_r(delta-1)
]
作者认为,使得DMF的二阶差分最大的(delta)信号长度为最佳的patch size。由二阶差分的定义我们知道,二阶差分的最大值对应的就是一阶差分变化率最大的地方,在最佳patch时,DMF理应是较小的,而DMF的前向差分理应很大,后向差分理应很小(负值),二阶差分最大的地方一阶差分变化的最为剧烈。
上图为DMF计算可视化结果。
Manual labeling category
原始图片被分为不同patch之后,显然defective-free 的样本要远超过defetective的样本,样本远远不平衡,为了平衡样本,对defective的样本做了旋转等增广,使得两者比例为3:2,训练集和测试机的样本量比例为7:3.
再之后就是一个简单的多分类神经网络,训练。
Coding
import cv2 as cv
import numpy as np
class DMF(object):
def __init__(self):
pass
def __call__(self,img):
H,W = img.shape
ds_r = np.zeros((H-1,1))
ds_c = np.zeros((1,W-1))
for delta_r in range(1,H):
for delta_c in range(1,W):
d_r,d_c = self.distance(img,delta_r,delta_c)
ds_r[delta_r-1,0] = d_r
ds_c[0,delta_c-1] = d_c
dif_r = np.diff(ds_r,axis = 0)
dif_c = np.diff(ds_c,axis = 1)
dif_2_r = np.diff(dif_r,axis = 0)
dif_2_c = np.diff(dif_c,axis = 1)
return np.argmax(dif_2_r,axis = 0),np.argmax(dif_2_c,axis = 1)
@staticmethod
def distance(img,delta_r = 1,delta_c = 1):
H,W = img.shape
d_c,d_r = 0,0
for r in range(H): # number of row
for c in range(W): # number of col
# row_distance
for i in range(H - delta_r):
d_r += (img[i,c] - img[i+delta_r,c])**2
# col distance
for i in range(W - delta_c):
d_c += (img[r,i] + img[r,i + delta_c])**2
return d_r,d_c
if __name__ == "__main__":
img = np.random.rand(28,28)
dmf = DMF()
r,c = dmf(img)
print(r,c)
网络比较简单不实现。