もう目視検査をやめたいあなたへ。「Anomalib」で、 AIによる画像検査を試しませんか?

コンベアを流れる製品から、目視で不良品を見つける作業、かなり大変ですよね。人件費の高騰もあり、単純作業を自動化したいと言う現場のニーズは、常にあるかと思います。

しかし、画像検査の設計は非常に難しく、導入に二の足を踏んでしまう方は多いです。

たとえば、下のネジ画像、左は良品、右は不良品です。こんなのどうやって自動で判別したらいいのよ、となります。

良品と不良品のネジの画像
左が良品、右が不良品

この記事では、オープンソースの異常検知ライブラリ「Anomalib」を使って、AI画像検査を、ちょっと試してみたいという方に、簡単な環境構築の手順、短いサンプルコード、そして実際の結果を紹介します。

この記事で得られる事
・Anomalibの導入方法が分かる
・pythonでのサンプルコードが分かる
・AI画像検査で、どんな処理結果が得られるのかが分かる


1. Anomalib って?

Anomalib は、Intel が開発を主導している、オープンソースのディープラーニングアルゴリズムのうち、異常検知を目的としたものを集めたライブラリです。Apatch 2.0ライセンスなので、商用利用が可能なのも良いところです。

ライブラリには、異常検知を行うモデルが色々と収録されています。今回は、「PaDiM」というモデルを試します。


2. インストール

pythonは、3.11.9を使用しています。最新だと動かない場合があります。

pipを使って、必要なパッケージをインストールします。トータルで1.2GBあるので、HDDの空き容量には気を付けてください。

pip install anomalib==2.2.0
pip install requests tqdm matplotlib omegaconf
pip install pandas==2.3.3

3. データを用意

学習用に使用する画像を用意します。
train/good 配下に、良品の画像を置きます。

評価用の画像を用意します。
test/good配下に、良品の画像を置きます。
test/bad 配下に、不良品の画像を置きます。

test.py               <-- テストプログラム
dataset/
├── train/
│   └── good/         <-- 正常画像
└── test/
    ├── good/         <-- テスト用正常画像
    └── bad/          <-- テスト用異常画像

今回は、画像検査ソフトウェアメーカーのMVTec社が公開している良品・不良品の画像集を使ってテストします。

Screwというタイトルのデータセットを使用しました。記事の冒頭で、紹介した画像です。

写っている物は、向きなどがそろってなくても学習が可能です。もちろん、向きをそろえたり、背景をきれいにしたり、照明をいい感じに当てると、判定の精度は良くなります。


4. サンプルコード

下記が、サンプルコードです。

from pathlib import Path
import numpy as np
import cv2
import matplotlib.pyplot as plt
from pathlib import Path
from anomalib.data import Folder
from anomalib.models import Padim
from anomalib.engine import Engine

def main():

    current_dir = Path(__file__).parent
    dataset_path = current_dir / 'dataset'
    result_path = current_dir / 'results'

    # データセットの設定
    datasets = Folder(
        name='sample',
        root=Path(dataset_path),       # データセットフォルダ
        normal_dir='train/good',      # 学習用のデータ
        test_split_mode='from_dir',   # フォルダからデータを読み込む
        normal_test_dir='test/good',  # テスト用(通常)
        abnormal_dir='test/bad',      # テスト用(異常時)
        val_split_mode='same_as_test', # テスト用のgoodをそのままモデル検証にも使う
        train_batch_size=1, # 学習時のバッチ数(一度に何枚処理するか)
        eval_batch_size=1,  # 評価・推論時のバッチ数
        num_workers=0, # エラー回避用の設定
    )

    # モデルの初期化
    model = Padim(backbone='resnet18')

    # エンジンの設定
    engine = Engine(
        max_epochs=1, # 学習の繰り返し数
        default_root_dir=result_path, # 結果の出力先
    )

    # モデルの学習を実行
    engine.fit(model=model, datamodule=datasets)

    # 推論を実行
    predictions = engine.predict(model=model, datamodule=datasets)
    
    # 結果を取り出して表示
    for prediction in predictions:
        # 元画像を読み出し
        image_bgr = cv2.imread(str(prediction.image_path[0]))
        image_rgb = cv2.cvtColor(image_bgr,cv2.COLOR_BGR2RGB)
        image_gray = cv2.cvtColor(image_bgr,cv2.COLOR_BGR2GRAY)
        image_gray_rgb = cv2.cvtColor(image_gray,cv2.COLOR_GRAY2RGB)

        # ヒートマップを読み出し
        heatmap_org = prediction.anomaly_map.permute(1,2,0).cpu().numpy()
        heatmap_resize = cv2.resize(heatmap_org, (image_gray_rgb.shape[1], image_gray_rgb.shape[0]))
        heatmap_8bit = (heatmap_resize * 255).astype(np.uint8)
        heatmap_color = cv2.applyColorMap(heatmap_8bit, cv2.COLORMAP_JET)            
        overlay_img = cv2.addWeighted(image_gray_rgb, 0.3, heatmap_color, 0.7, 0)

        # スコア値を読み出し
        #score = float(prediction.pred_score[0])
        score = raw_val = prediction.anomaly_map.max().item()

        # 判定
        if(score >= 0.5):
            judge = 'NG'
        else:
            judge = 'OK'

        # 表示
        fig, axes = plt.subplots(1, 2, figsize=(10, 5))
        axes[0].imshow(image_rgb)
        axes[0].set_title(f'Original/ Judge: {judge} (Score: {score:.2f})')
        axes[1].imshow(overlay_img)
        axes[1].set_title('Anomaly Heatmap')
        plt.show()  

if __name__ == '__main__':
    main()

かなり短いと思いませんか?

でも、これだけで学習、推論実行、結果の取り出しまでやっています。サンプルコードは、datasetがある階層と同じ場所に置いて実行してください。

5.実行結果

サンプルを実行すると、下記のような画像が表示されます。右は元画像、左は異常と判定した箇所を強調した画像(ヒートマップ画像)です。元画像のタイトルのところに、NG度合いを示すスコア値を表示しています。

スコア値が0.5以上で、不良品として判定できます。

良品の判定結果
不良品の判定結果

まとめ

Anomalibは、良品画像を学習させるだけでよいので、検査の設計が非常に簡単です。

ただし、長さ〇〇mm以内かどうか、などの検査には不向きです。その場合は、ルールベースという古典手法で対応する必要があります。

今回試した PaDiM は、私の PC(10年前のおんぼろ)でも、推論が1秒程度でおわります。最新の PC であれば、もっと早いと思いますので、検査時間は、実用的な範囲になるかと思います。

これを機会に、めくるめく AI画像検査の世界に、足を踏み入れてみませんか?

最後まで読んでいただき、ありがとうございます。

コメントはお気軽にどうぞ。フォロー、スキいただきますと、嬉しいです。フォローバックします。

いいなと思ったら応援しよう!

あすくろ もし、記事が気に入っていただけましたら、応援いただけますと幸いです。いただいたチップは、記事作成に絶対必要なおやつ代になったり、部材を買ったりなどに使用させていただきます。