本記事では、PaDiMとタイルアンサンブルを組み合わせて実践する際の、ポイントを解説します。
背景
既存手法の問題点
PaDiMやPatchCoreなどに代表される異常検知AIは、小さな欠陥を検出することが苦手です。PaDiMは小さな欠陥に強いと言われていますが、それでも限界があります。なぜなら、画像がAIに入力されると、複数のレイヤを通る度に徐々に画像の解像度が低くなっていき、小さな欠陥は消えてしまうからです。これは、既存のAIモデルのメカニズム上、仕方のないことです。
この問題の対処するためには、基本的には画像の解像度を上げるしかありません。AIモデルの中で解像度が下がったとしても、元々の解像度が高ければ、小さな欠陥が見えなくなることはなくなるだろう、という考え方です。
しかし、画像の解像度を上げれば上げるほど、メモリ使用量が大幅に上昇するため、高価なマシンが必要になってしまいます。異常検知AIのメモリ使用量はかなり多く、費用面を考慮すると現実的ではないことが多いです。
タイルアンサンブルというアイディア
そういった問題を対処するために、タイルアンサンブルという手法が以下の論文で提案されました。
Divide and Conquer: High-Resolution Industrial Anomaly Detection via Memory Efficient Tiled Ensemble

上記画像は論文からの引用です。この画像を見れば、なんとなくイメージできると思いますが、画像を分割して、それぞれの画像に対してAIを実行し、その結果を最後にマージする。というアイディアです。
高解像度画像であっても分割することで、1つ1つのAIモデルのメモリ使用量は小さいままなので、性能の低いマシンでも高解像度画像を利用でき、小さな欠陥を検出することができるようになります。
当然、分割した数だけAIモデルを実行することになるので、その分実行時間はかかりますが、時間よりも検出性能を優先したいケースには有力な選択肢となるでしょう。
本記事の目的
タイルアンサンブルは考え方はシンプルですし、実践するのは簡単と思うかもしれません。しかし、実際はそううまくはいきません。私がタイルアンサンブルを実践するにあたり、2つの問題に直面しました。
- 異常度マップのマージ
- マージ後の不自然さの除去
本記事では、この2点の問題点と対処方法を、タイルアンサンブル実践のポイントとしてお伝えすることです。
なお、タイルアンサンブルでは、使用する異常検知AIは限定していませんが、本記事では「PaDiM」を使用することを前提にお話しいたします。
先ほどの2つの問題点は、PaDiMとタイルアンサンブルを組み合わせた際に直面した問題です。他の異常検知AIを用いた場合は、状況が異なるかもしれませんが、ご了承ください。
異常度マップのマージ方法
問題点
タイルアンサンブルのアイディアにあるように、AIモデルが出力した異常度マップを1つのファイルにマージする必要がありますが、その具体的な方法は論文に書かれていません。何も書かれていないので、単純に異常度マップをマージすれば良いのかと思い、実践してみると、以下のような結果となってしまいました。

エリアごとに異常度の分布が異なっており、例えば、左下のエリアは全体的に異常度が高くなっているのがわかると思います。正常品・異常品にかかわらず、全てこの傾向にありました。判定基準にもよりますが、左下のエリアに必ず欠陥があると誤判定してしまうこともあるでしょう。
原因
問題の原因は、異常度マップの正規化のタイミングです。
PaDiMでは、異常度を計算した後に正規化を行なっています。異常度はマハラノビス距離を使っているため、その値の取り得る範囲は学習データによってまちまちです。50〜200だったり、1000〜30000といった具合にバラバラです。このままだと使い辛いので、正規化して値を0.0〜1.0の範囲に収めているのです。

エリアごとに異常度が高かったり低かったりするのは、この正規化をした後にマージを行なっていたからです。画像を上下に分割した場合の、マージのイメージ図を見てください。

左側の上下のグラフを見比べてください。これは異常度の分布ですが、上のグラフの方がMaxが大きい値です。次に真ん中の上下のグラフを見比べてください。異常度を正規化したグラフですが、上側のグラフは全体的に低い値、下側のグラフは全体的に高い値になっていることがわかると思います。正規化前の分布によって、正規化後の値の傾向が変わってしまうのです。これは当たり前のことではありますが、PaDiM内部の処理のため、気付きにくい点かもしれません。この結果、マージするとエリアごとに異常度が高かったり低かったりしてしまうのです。
2025年8月3日追記:タイルアンサンブルのプロジェクトサイトで、正規化のタイミングについて、”マージ前にやっても良いし、マージ後にやっても良い”と記載がありました。どちらでも構わないと受け取れますが、本記事に記載した通り、正規化はマージ後を選択するのが良いと思います。
対策
原因がわかってしまえば対策は簡単です。正規化→マージとしていたのがよくないので、順番を逆にしてマージ→正規化とすればよいのです。そのように修正した結果が以下の画像です。

どのエリアも同じ色合いになっているのがわかると思います。つまり、どのエリアも異常度が同程度ということです。画像の境界線に不自然さが残っていますが、これはもう1つの問題点ですので、後ほど詳しく説明します。
マージ後の不自然さの除去
問題点
異常度マップをマージすると、境界線上に不自然さが残ります。その不自然さがわかりやすい画像を用意したので、まずはご覧になってください。

左上のエリアに欠陥があり、その周辺の異常度が高くなっていますが、左下のエリアとの境界線上で途切れているのがわかると思います。これは、左下のエリアには欠陥が存在していないため、左下のAIモデルは欠陥に反応することができないためです。このように、境界線付近に欠陥がある場合に不自然さが発生してしまうことがあります。
この対処方法として、論文では境界線付近でスムージング処理を行うことを提案しています。(ここで言うスムージング処理はおそらく平滑化だと思われるため、以降は平滑化と表記します。)

私はこの対処方法に疑問を持っています。平滑化処理を入れることで、その範囲がぼやけすぎてしまうからです。実際に平滑化を入れてみた画像をご覧になってください。いかがでしょうか?

私の提案
ここで平滑化処理を使わない方法を提案します。
そもそもPaDiMにはスムージングのためのガウシアンフィルターが入っています。なぜガウシアンフィルターが必要かというと、異常度は画像を小さな四角いパッチ状に分割して計算しているため、ガウシアンフィルターがないとモザイク柄になってしまうからです。あえてガウシアンフィルターを除いた異常度マップは、以下のような見た目になります。

これを避けるためにPaDiMにはガウシアンフィルターが入っています。そのため、マージした後にさらに平滑化処理を入れるのは、過剰なスムージングだと思います。
そこで、スムージング処理としてはガウシアンフィルターだけを使うこととし、そのフィルターの適用タイミングはマージ後に行う方法を提案します。こうすれば、過剰なスムージングにはならないですし、より自然な結果が得られるはずです。実際に試した画像をご覧になってください。

かなり自然な仕上がりになっていますね。なお、スムージング処理を複数回やる必要もなくなるので、処理性能の面でもこちらの方が有利です。
おわりに
本記事では、PaDiMとタイルアンサンブルを組み合わせた際の、問題点とその対策を紹介しました。
なお、この記事の内容は論文だけを読んで執筆しています。論文のコードも公開されているので、そちらを解析すれば、もっと適切な方法が実装されているかもしれません。私もコードを解析しようと思ったのですが、コード量が多く、解析に時間がかかりそうだったので断念しました。もし、気になる方がいればこちらも参照してみてください。
Add ensembling methods for tiling to Anomalib #1131
参考URL
タイルアンサンブルの論文
Divide and Conquer: High-Resolution Industrial Anomaly Detection via Memory Efficient Tiled Ensemble