製造業の外観検査では、不良品の画像が十分に集まらないまま検査を始めたい場面があります。そこで使われるのが、正常品だけから「正常らしさ」を学び、そこから外れた領域を見つける異常検知です。

この記事では、産業画像の定番ベンチマークMVTec ADとPatchCoreを使い、正常画像の学習から異常スコア・ヒートマップの確認までをローカルで一周します。なぜ外観検査でこの問題設定が有効なのかは、製造業にAIが根づいた理由で整理しています。

今回試すもの

MVTec ADは、工業製品とテクスチャを対象にした異常検知データセットです。15カテゴリ、5,354枚の高解像度画像があり、学習用は正常画像だけ、テスト用は正常画像と欠陥画像で構成されます。欠陥は70種類を超え、異常領域のピクセル単位マスクも付属します[1][2]

今回は物体カテゴリのbottleを使います。モデルはPatchCoreです。事前学習済みCNNから画像内のパッチ特徴を取り出し、正常画像の代表的な特徴をメモリバンクに保存します。推論時は、各パッチが正常メモリからどれだけ離れているかで異常度を計算する仕組みです[3]

要素今回の選択役割
データMVTec AD / bottle正常学習と欠陥テスト
モデルPatchCore正常パッチからの距離で異常を検出
実装anomalib 2.5.0データ取得・学習・評価・可視化
出力画像スコアと異常マップ製品単位の判定と欠陥位置の確認

MVTec ADはCC BY-NC-SA 4.0で配布され、商用利用は許可されていません[1]。教材・検証用データとして扱い、製品開発では自社データと利用条件を別途確認してください。

環境を作る

本稿はmacOS、Python 3.12、anomalib 2.5.0のCPU環境で、インストール、import、CLI設定の解決まで確認しました[4]。データ全量の学習は計算資源と実行時間に左右されるため、編集環境では未実行です。

uvが入っている前提で、隔離した環境を作ります。

mkdir mvtec-ad-handson
cd mvtec-ad-handson
uv venv --python 3.12 .venv
source .venv/bin/activate
uv pip install "anomalib[cpu]==2.5.0"

NVIDIA GPUを使う場合は、anomalib公式のインストール手順で環境に合うCUDA extraを選びます。PyTorchとGPUドライバの組み合わせがあるため、CPU用コマンドのcpuだけを機械的に置き換えないでください。

PatchCoreを学習・評価する

次の1コマンドで、データの取得、正常画像によるメモリバンク作成、テストデータでの評価まで進みます。初回はMVTec AD全体を取得するため、ディスク空き容量と通信時間を見込んでください。

anomalib train \
  --model Patchcore \
  --data anomalib.data.MVTecAD \
  --data.category bottle \
  --data.num_workers 0

PatchCoreは通常の分類モデルのように重みを何十エポックも更新するのではなく、正常画像から特徴を抽出してメモリバンクを構成します。anomalibの標準設定では、wide_resnet50_2layer2layer3を使い、代表特徴を残すcoreset sampling ratioは0.1です[5]

実行前に、CLIがどの設定へ解決したかだけ確認することもできます。

anomalib train \
  --model Patchcore \
  --data anomalib.data.MVTecAD \
  --data.category bottle \
  --data.num_workers 0 \
  --print_config

結果はresults/以下に保存されます。環境によってディレクトリ階層が変わる可能性があるため、まずファイルを一覧します。

find results -maxdepth 6 -type f | sort

結果をどう読むか

異常検知には、少なくとも2つの粒度があります。

  • 画像レベル: この製品全体が正常か異常か。ラインから排出するか、人の再検査へ送るかに使う
  • ピクセルレベル: 画像のどこが異常か。ヒートマップやマスクとして、検査員の確認や原因分析に使う

AUROCは、しきい値を動かしたときの正常と異常の順位づけ能力を要約します。ただし、AUROCが高いだけでは運用しきい値は決まりません。現場では「欠陥の見逃し」と「正常品の過検出」でコストが違うためです。

ヒートマップも、赤い場所をそのまま欠陥の説明だと受け取らないことが重要です。PatchCoreが示すのは正常メモリから離れた特徴の位置です。背景、治具、照明の反射、製品位置のずれにも反応します。まずテスト画像を次の3群に分けて観察すると、モデルの癖が見えます。

  1. 欠陥を正しく強調した画像
  2. 欠陥を見逃した画像
  3. 正常なのに高スコアになった画像

平均値だけでなく失敗画像を並べることが、次の改善を決めます。評価指標としきい値の設計は、モデル評価設計入門で詳しく扱っています。

別カテゴリで壊してみる

bottleで動いたら、cabletransistorへカテゴリを変えて同じ設定を試します。

anomalib train \
  --model Patchcore \
  --data anomalib.data.MVTecAD \
  --data.category cable \
  --data.num_workers 0

物体の位置が揃いやすいカテゴリと、部品構成や姿勢にばらつきがあるカテゴリでは難しさが違います。同じモデルの平均スコアだけを比較するより、どの正常変動を異常と誤認したかを見ます。ここで、撮像条件と位置合わせがモデル選定以上に効くことを体感できます。

自社データへ移る前のチェック

MVTec ADで高い性能が出ても、そのまま工場へ持ち込めるわけではありません。ベンチマークから実データへ移るときは、次の順で確認します。

  1. 撮像を固定する: カメラ、焦点、照明、背景、製品姿勢を固定し、正常変動を減らす
  2. 分割単位を決める: 同じ製品や同じ撮影連番が学習と評価にまたがらないようにする
  3. 欠陥別Recallを見る: 平均AUROCの裏で、小さなキズや特定材質だけを見逃していないか確認する
  4. 運用しきい値を決める: 見逃しコストと再検査能力から、過検出率を含めて決める
  5. 変化を監視する: 品種追加、照明交換、カメラ交換、季節変動でスコア分布が動く前提を置く

正常画像そのものが少ない場合の転移学習・データ拡張・合成データは、教師データが足りないときの戦い方も参考になります。

まとめ

  • MVTec ADは、正常画像で学習し、欠陥画像で検出と位置特定を評価できる産業異常検知の定番データセット
  • PatchCoreは、正常画像のパッチ特徴をメモリバンク化し、そこからの距離を異常度として使う
  • anomalibなら、データ取得から学習・評価・可視化までを1コマンドで通せる
  • AUROCだけで判断せず、見逃し画像・過検出画像・欠陥別Recallを確認する
  • 実データでは、撮像固定、リークしない分割、運用しきい値、分布変化の監視までがシステムの一部

次は、自社の正常画像を集める前に、カメラと照明を固定して「モデルに見せたい差」だけが写る撮像条件を作ってみてください。

参考文献・一次情報

  1. [1]
    OFFICIALMVTec AD — Industrial Anomaly Detection Dataset

    MVTec Software GmbH

    データセットの構成、配布条件、CC BY-NC-SA 4.0ライセンスの確認

  2. [2]
    PAPERMVTec AD — A Comprehensive Real-World Dataset for Unsupervised Anomaly Detection

    Paul Bergmann, Michael Fauser, 他CVPR 20192019DOI: 10.1109/CVPR.2019.00982

    5,354画像・15カテゴリ・70種類超の欠陥とピクセル単位アノテーションを示した原論文

  3. [3]
    PAPERTowards Total Recall in Industrial Anomaly Detection

    Karsten Roth, Latha Pemula, 他CVPR 20222022

    正常画像のパッチ特徴をメモリバンク化するPatchCoreの原論文

  4. [4]
    OFFICIALanomalib 2.5.0

    Anomalib Contributors2026

    本稿で動作確認したパッケージ版とPython対応範囲

  5. [5]
    OFFICIALPatchCore — Anomalib documentation

    Anomalib Contributors

    PatchCore実装の設定、バックボーン、学習・推論API