製造工場のラインなどにおいて、製品に生じた「キズ」や「欠け」を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 decoded2. ヒートマップによる「異常箇所の可視化」
学習が完了したモデルにテスト画像を入力し、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を素早く導入するための最強の武器となります。


コメント