人間生きていると誰しも異常検知をしたいときが突然来るものである。とある製品に光を当てて一定数以上エアポケットが出てしまった場合に異常を検知したいときが誰しも来る。
今回はいろいろ諸事情があって、その製品に関する画像データが手元に全くないので、まずはネジに対して異常を検知できるかどうかpythonで実装してみるか…
よし、、、
Convolutional Auto Encoder を実装する
今回はConvolutional AutoEncoderを使用する。Convolutional AutoEncoderとは、中間層にCNNを使用したAutoEncoderで画像の特徴を捉える能力が高いことでおなじみ
めちゃくちゃ分かりやすく言うとエンコーダー部分で入力された画像を圧縮して、それをデコーダー部分で逆のことをして復元する。
そして、訓練時にはとにかく正常の画像のみを学習させる。そして入力と出力の誤差を小さくなるようにする。
つまり正常な画像は圧縮し復元できるようにする。逆に訓練していない異常な画像は復元できないため誤差が大きくなる。
この仕組みにより、訓練時に異常な画像は必要ない。正常な画像だけを訓練に当てればいい。(テスト用には異常画像が必要)
学習用画像の用意
まずはネジの画像を用意する(参考書籍付属のもの)。ネジの反射による色も様々なものを128×128pxのサイズで

ネジがつぶれているのは異常
それを学習させて、学習に使っていない方の画像セットを誤差を比較すると
上図の右二つのグラフを見てほしい。
右から二番目の正常の画像の平均誤差と異常画像の平均誤差は確かに差があり異常検知はなんとなくできている気がするけど
誤差の差が甘い。
学習において、正常か異常か判断するうえで不必要な情報を極力排除することは非常に重要と言われている
画像セットを白黒に変換してから学習、検証してみる
OpenCVには画像をグレースケール変換してくれる関数が用意されている。それを使用して再度学習を行い検証すると、、、
………えぇ、、
マジか正直こんなに差があるとは思わなかった。
異常検知精度としては正直7割から8割(ネジに対して)
現段階でもこの精度で良しとするならばそのまま使えるし、まだ画像の整形などやれることはありそうではある。
実務として一番問題なのは異常なものを正常と判断してしまう場合の処理で、それをどうするのか、損失関数を定義するなどやり方があるかもしれないが具体的な実務に落とし込めるよう考えていきたい。
実際に実務で使ってみる
実際に判定したい製品はネジのように平面だけで判断できるものではなく、立体なのでカメラを複数用意する必要があった。
なんだかよく分からんけど認識できるカメラの台数に限界があり(USBの分配器を使用したのが原因かも)
しかも起動するたびに割り当てたカメラ番号が変わる(これはしらん)
でも一つのプログラムで全てのカメラを動作させるのではなく並列処理で動かしてやり、それぞれで誤差を導出
その誤差の総和を異常検知する最終的な数値とすることで複数台数でも動作可能ということ
そしてこの異常検知したいものは製品にエアポケット(空気の泡)が入って白くなってしまっている部分があった場合に異常と検知したいわけだが、それこそ先ほどのグレースケールにするやつがぴったりハマる。
どのようなシステムで次々と指定の場所をカメラが納められるようにするかは課題だがプログラム自体はできた
参考文献