【異常検知】オートエンコーダ(Autoencoder)を使った工場ライン外観検査の自動化

プログラミング

製造工場のラインなどにおいて、製品に生じた「キズ」や「欠け」をAIで検出する外観検査の自動化は極めて費用対効果の高いAI導入事例です。しかし、致命的なハードルがあります。
それは「不良品データ(キズのある画像)が圧倒的に少なく、機械学習の定番である『画像分類(正しいデータと間違ったデータを両方教える手法)』が使えない」という現場の現実です。

そこで大活躍するのが、「正常なデータだけ」を学習させて異常を見つけ出すUnsupervised Learning(教師なし学習)の一種、「オートエンコーダ(Autoencoder)」を用いた異常検知です。

1. オートエンコーダによる「正常な状態の記憶」と復元誤差

オートエンコーダは、「入力された画像を一度あえて小さな次元に圧縮(エンコード)し、そこから元の画像を完璧に復元(デコード)するように自分自身を学習させるニューラルネットワーク」です。
ポイントは、「正常な製品の画像だけ」を数千枚学習させる点にあります。するとAIは、「正常な製品を圧縮して、元通りに復元する」能力だけを猛烈にマスターします。

このAIに、未知の「キズ付きの不良品」を入れるとどうなるでしょうか?
AIは「キズを復元する方法を知らない」ため、無理やりキズの無い『正常な画像』として復元して出力してしまいます。その結果、「入力画像(キズあり)」と「出力画像(綺麗に復元されたもの)」の間でピクセルごとの差分(復元誤差:Reconstruction Error)を取ると、キズの部分だけがクッキリと浮かび上がるのです!

import torch
import torch.nn as nn
class ConvAutoencoder(nn.Module):
    def __init__(self):
        super(ConvAutoencoder, self).__init__()
        # エンコーダ(次元圧縮): 3チャネルカラー画像を徐々に小さくする
        self.encoder = nn.Sequential(
            nn.Conv2d(3, 16, 3, stride=2, padding=1),
            nn.ReLU(),
            nn.Conv2d(16, 32, 3, stride=2, padding=1),
            nn.ReLU(),
            nn.Conv2d(32, 64, 7) # 小さな潜在変数(Latent space)へ圧縮
        )
        
        # デコーダ(復元): エンコーダと全く逆の操作で元の解像度に戻す
        self.decoder = nn.Sequential(
            nn.ConvTranspose2d(64, 32, 7),
            nn.ReLU(),
            nn.ConvTranspose2d(32, 16, 3, stride=2, padding=1, output_padding=1),
            nn.ReLU(),
            nn.ConvTranspose2d(16, 3, 3, stride=2, padding=1, output_padding=1),
            nn.Sigmoid() # 出力は0〜1のピクセル値
        )
    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return decoded

2. ヒートマップによる「異常箇所の可視化」

学習が完了したモデルにテスト画像を入力し、Mean Squared Error (MSE)を用いて差分を取り、ピクセルごとの異常スコアをヒートマップとして可視化する処理です。これにより、現場の作業員が直感的に「どこがおかしいのか」を即座に判断できるようになります。

import cv2
import numpy as np
def visualize_anomaly(model, test_image_tensor, original_img_cv2):
    model.eval()
    with torch.no_grad():
        # モデルに画像を入力し、復元画像を得る
        reconstructed = model(test_image_tensor)
        
    # TensorからNumPy配列に変換 (Batch, Channel, H, W -> H, W, Channel)
    input_np = test_image_tensor.squeeze(0).permute(1, 2, 0).cpu().numpy()
    recon_np = reconstructed.squeeze(0).permute(1, 2, 0).cpu().numpy()
    # 入力画像と復元画像の絶対誤差(Absolute Error)を計算
    diff = np.abs(input_np - recon_np)
    
    # チャンネル平均をとってグレースケールの異常スコアマップにする
    score_map = np.mean(diff, axis=2)
    score_map_normalized = np.uint8(255 * score_map / np.max(score_map))
    
    # OpenCVの色を適用してヒートマップ化 (JETカラーマップ)
    heatmap = cv2.applyColorMap(score_map_normalized, cv2.COLORMAP_JET)
    
    # 元画像にオーバーレイ (半透明合成)
    result = cv2.addWeighted(original_img_cv2, 0.6, heatmap, 0.4, 0)
    
    return result

まとめ:工場への真の価値とは?

画像分類であれば「キズ」「へこみ」「塗装のハゲ」など、すべてのパターンの不良品データを均等に何百枚も集めなければAIを作れませんが、オートエンコーダを使えば「良品だけを撮りためる」だけで明日からAI検査ラインをスタートできます。この「教師なし学習」のアプローチこそが、日本の製造業がAIを素早く導入するための最強の武器となります。

コメント

タイトルとURLをコピーしました