• 正文
  • 相关推荐
申请入驻 产业图谱

用于图像缺陷检测的自编码器

09/18 11:25
925
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

检测有缺陷的产品是任何生产线的首要目标。如今,用于质量控制的计算机视觉已经很容易获得。然而,基本的计算机视觉方法要求对缺陷进行很好的量化。因此,有必要引入机器学习来帮助检测难以量化的缺陷。

话虽如此,在生产线上收集的图像可能会偏向于无缺陷产品,而缺陷产品的图像很少见。这使得简单的分类器难以训练。在这里,我将展示一种涉及自编码器的方法来解决这个问题。

这是我正在做的一些正在进行的工作的一部分。因此,未来的帖子可能会显示方法论的改进。

方 法

对于那些不熟悉自编码器的人来说,它是一种用于重建输入数据的机器学习模型。

这听起来有点微不足道。但是,对于这项任务,我们可以变得聪明。如果我们只在无缺陷的部件上训练自编码器,它应该能够可靠地再现这些部件。当馈入有缺陷部件的图像时,复制中应该有一些错误。

据推测,如果自编码器学会了很好地再现好的零件图像,那么在有缺陷的零件和良好的零件之间,这个误差应该足够大,可以形成决策边界。

数据集:制动卡钳缺陷图像

为了公开演示这些方法,我将使用公开可用的数据集。该数据集包含制动卡钳上良好和有缺陷铸件的图像,可以在 Kaggle 上免费找到。

https://www.kaggle.com/datasets/ravirajsinh45/real-life-industrial-dataset-of-casting-product

Keras 中的简单自编码器

对于初步测试,我使用了一个由完全连接的密集层制成的简单自编码器。实现可以在这里看到:

stacked_encoder = Sequential([    layers.Input(img.shape), # img.shape is 300 x 300 pixels    layers.Flatten(),    layers.Dense(100, activation="relu"),    layers.Dense(30, activation="relu"),])stacked_decoder = Sequential([    layers.Dense(100, activation="relu"),    layers.Dense(img.shape[0] * img.shape[1] * img.shape[2], activation="sigmoid"),    layers.Reshape([img.shape[0], img.shape[1],img.shape[2]]),])stacked_ae = Sequential([stacked_encoder, stacked_decoder])stacked_ae.compile(loss="mse", optimizer="nadam")stacked_ae.summary()

在这里,我们将自编码器分为两部分:编码器和解码器。对于这种特定情况,我们不会使用这种分离。在类似的情况下,编码器单独用于执行我们在此处执行的相同任务,这被认为是一种异常检测方法。

对于训练,我使用了这行代码:

history = stacked_ae.fit(X_good,X_good,epochs=200)

在这里,您会注意到 X_good用于输入标签和训练标签。此变量来自数据集的一组无缺陷部分。我肯定会事先将它们拆分为训练和验证拆分,但这超出了本文的范围。

绘制一些无缺陷(良好)和有缺陷部分的重建图,我们可以看到存在明显的差异。尽管如此,对于一些好的部分还有改进的余地。

为了在结果中获得更明显的变化,我们将采用重建图像和原始图像之间的差异。这只需减去两者即可完成。我们还将使用np.clip()将它们限制为 0-1 之间的值。

结果显示,好零件和缺陷零件之间的差异更加夸张。现在几乎就像缺陷被突出了一样。这应该足以运行基本分类器。

我用来绘制上图的函数如下所示。该函数允许通过更改plot_diff布尔值来绘制图像重建以及两者之间的误差 。

def plot_reconstructions(model, images=X_good, n_images=5,plot_diff=False):    reconstructions = np.clip(model.predict(images[:n_images]), 0, 1)
    if plot_diff:        reconstructions = reconstructions - images        reconstructions = np.clip(reconstructions,0,1)
    fig = plt.figure(figsize=(n_images * 1.5, 3))    for image_index in range(n_images):        plt.subplot(2, n_images, 1 + image_index)        plt.imshow(images[image_index], cmap="binary")        plt.axis("off")        plt.subplot(2, n_images, 1 + n_images + image_index)        plt.imshow(reconstructions[image_index], cmap="binary")        plt.axis("off")

为分类器奠定基础

要使用分类器来确定零件是好的还是有缺陷的,需要确保结果以某种方式是可分离的。对我来说,我希望每张图像都归结为一个数字。为此,可以使用多种方法。例如:

对所有图像求和

取图像的平均值

取图像的标准差

经过一些测试,这些都在某种程度上有效。然而,图像的标准差被证明是最有效的。我还发现,采取np.abs()每一种方法以确保结果是积极的,这很有用。这是我用来执行此作的函数:

def get_diff_sums(imgs,autoenc):    Y = autoenc.predict(imgs) # create reconstructions    D = Y-imgs # take differences between reconstructions and images    sums = []    for diff in D:        sums.append(np.abs(np.std(diff))) # take std and abs of each image    sums = np.array(sums)    return sums
good = get_diff_sums(X_good,stacked_ae)bad = get_diff_sums(X_bad,stacked_ae)

绘制结果,我们可以看到好的部分和坏的部分是可以分离的。这意味着将来可以应用分类器。

请注意,重建误差是重建图像与原始图像之间的差异。重建误差与原始图像的形状相同。为了将其制成一个数字以供将来分类,采用了标准差。然后取绝对值,使值为正。

自编码器可以成为检测图像缺陷的有用工具,特别是当数据集主要包含无缺陷部件的图像时。在这里,我们训练了一个自编码器来再现一个好的零件的图像。通过自编码器发送的有缺陷部件的图像产生了重建错误。从原始图像中减去重建图像以产生重建错误。将重建误差汇总为一个数字提供了一种区分好部分和坏部分的方法,从而允许将来进行分类。

相关推荐