高性能な異常検知AIをノーコード的に開発する

## まえがき
* 異常検知データセットで知られる[MVTecADを配布](https://www.mvtec.com/company/research/datasets/mvtec-ad)しているMVTec社は、国内でも著名な産業用画像処理ライブラリHALCONのメーカである
* MVTecは無料で高性能のディープラーニングモデルを作成することができるDeep Lerning Tool(DLTool)を2019年から配布している
* DLToolで作成した深層学習モデルは、同社のHALCONやMERICに組み込んで使用することができる
* MERICは画像処理アプリをノーコードで作成できる、HALCONのサブセットとでもいうべきツールで、これ単独でGUIアプリまで作成できる
* MVTecADのscrewデータセットから異常検知モデルを作成したが、普通にDLToolを使うだけではいまいちな性能だった
* そこで、MERLICの体験版を使って画像の前処理工程を作成することで、十分に満足できる性能のモデルを作成できた
* DLToolやMERLICの製品情報は、国内の総代理店である[株式会社リンクスのWebサイト](https://linx.jp/product/mvtec/)に詳しいのでここでは詳細を説明しない
* DLToolの使い方については、Youtubeの再生リスト[【無料でAI外観検査】MVTec Deep Learning Toolで○○検査してみた](https://www.youtube.com/playlist?list=PL-ieHtkK_1NvDT4LFibzLmYFV1hi8g9Z7)や[この再生リストの作者のWebサイト](https://ovit.co.jp/deeplearning/)に詳しい

## MVTec Deep Learning Tool (DLTool)

### MVTec AD の screw データセット

異常検知学習用に用意された480枚の木ねじのグレー画像のセットで、木ねじの姿勢がバラバラで揃っていないという特徴がある。
例えば、、、

良品画像：
![スクリーンショット 2024-05-02 172252.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/1de9fd94-1f05-a603-515d-77efe180a9c6.png)

不良品画像：
ねじ先端が欠けている
![スクリーンショット 2024-05-02 172526.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/3308b2ae-8fea-986c-d704-77c053379775.png)

ねじ頭部にキズがある
![スクリーンショット 2024-05-02 172604.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/f6fb2a9f-fff7-2459-5967-0ff668afdf95.png)

ねじ首部にキズがある
![スクリーンショット 2024-05-02 172650.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/c9d641fc-51f8-356d-7293-f3650e996277.png)

ねじ山に欠けがある(1)－キズを横から見ている
![スクリーンショット 2024-05-02 172726.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/6d08b1cc-3416-4aba-bd34-91fcb0bef095.png)

ねじ山に欠けがある(2)－キズを正面から見ている
![スクリーンショット 2024-05-02 172754.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/d65e5e27-4810-8a2f-e8a6-b65c308195c7.png)

## DLToolで素の画像のまま学習させる

手元のPCは当時12万円で購入した2年落ちのエントリーレベルのゲーミングPCで、GPUとして NVIDIA Geforce GTX 3050 を積んでいる。このPCでグローバルアノマリー検出プロジェクトを作成し良品データのみを教師として学習を80分ほど回してモデルを作成した。
このモデルをテストすると、F1スコア=93% と次のようなヒストグラムが得られる。

![スクリーンショット 2024-05-02 115742.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/c90ae39e-dc98-61d1-bccb-ed81079197c0.png)

この結果を得られるまでに必要な時間は、初期設定に5分、学習に80分、評価に5分しか必要なく、しかも無料で使えるのでこの簡便さは十分にスゴイことだと感じたのだが、よく考えると、
* 「不良品をすべて不良品と判断させる」ためにしきい値を左にずらすと、良品画像の約6割が不良品と判断されてしまう
* 「良品をすべて良品と判断させる」ためにしきい値を右にずらすと、不良品の約3割が良品と判断されてしまう

この状態ではあまり役に立たないモデルでしかない。

ヒートマップを確認すると、、

偽陽性（不良品なのに良品と判断）の画像
![スクリーンショット 2024-05-02 180842.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/9e5256d1-3519-0746-9a21-10b816567f00.png)

偽陰性（良品なのに不良品と判断）の画像
![スクリーンショット 2024-05-02 181503.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/6dd97117-0681-e22e-136b-38d6186d7f3a.png)

学習モデルはどこを捉えているのかよく分からない。

## MERLIC を使って事前に画像編集を行う

木ねじの姿勢がバラバラであることが、モデルの性能に影響していそうだと仮説を立てた私は、木ねじの方向を揃えて余白をトリミングする方法を探した。ImageMagick を使ったバッチファイルを書いても良かったが、それはそれで手間がかかり面倒である。
どうせDLToolで作成した学習モデルはHALCONかMERLICにしか組み込めず、Pythonから呼び出すような使い方はできないので、腹を括ってMERLICを使うことを考えた。

MERLICの操作はチュートリアル動画を何本か見れば理解できるものであった。
組んだ処理は次のようなものである。

![スクリーンショット 2024-05-02 183758.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/0bcacf97-e071-e8d2-970a-da1c3ffa1819.png)

フォルダから画像を1枚読み込んで、ねじ頭の形状を探してそれを基準に画像を回転して、長方形に切り取ってから別名保存するという単純な処理である。初めて触るアプリと30分ぐらい格闘して完成させた。事前処理をかけた画像は次のようになる。

![スクリーンショット 2024-05-02 184421.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/bfd8a235-7db5-88d0-fe92-a9a7a8574717.png)
アフィン変換じゃないので台形補正とかはできないようだが、あっさりと方向を揃えることができた。

## 処理済み画像を使って学習モデルを組む

この結果は劇的なものになった。F1スコア=95.97% と3%も向上し、そのヒストグラムは次のようになった。

![スクリーンショット 2024-05-02 115644.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/f89c6513-f8b7-3a10-4d07-cc566f4a250e.png)

不良品はすべて不良品と正しく判断でき、その場合でも偽陰性は10％程度で済む。これなら異常検知として使えそうだ。

![スクリーンショット 2024-05-02 185751.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99561/c7ac2208-4106-2717-0415-65af176caee0.png)

誤って良品を不良品と判断した画像のヒートマップを見ると表面の汚れや変色を拾って不良と判断しているようだ。輪郭線を拾ってモデルを作るともっと性能が上がるかもしれない。
※MERLICだとエッジ強調処理はできても輪郭線を拾うことはできないが、、、

## あとがき
今回は仕事上の必要性もあって姿勢がバラバラな画像の異常検知を調べていた。当初はMVTecADのscrewデータセットをサンプルに、Collabでフルスクラッチしかけていたけれども、DLToolとMERLICに行き当たったので方針転換して出来合いのツールを使うことにしました。その成果の一部をブログにすることを思い立って、情報整理をしつつチュートリアル動画を見返して、異常検知モデルの作成を２回繰り返し、ブログのこの記事を書き上げるまでには延べ8時間しかかかりませんでした。思い立ってパッと使えるMVTec社のDLTとMERLICは本当に便利です。プログラマではないのでHALCONには手を出さないのですが、MERLICは購入したいぐらいです。いくらだろう？

※HALCONには学生用の無料のライセンスが2023/9に登場している

※MERICで足りない機能は、HALCONで組んでExtensionツールを使って組み込むことができる。