地味な物体検出ですみません。　－組立検査機－

※こちらは[Pythonデータ分析勉強会#06](https://pythondata.connpass.com/event/118304/)の発表資料です。

本稿は、ラズパイ+物体検出を使って「将棋駒」を検出するプロジェクトの続きです。
もはや将棋駒ではなく、違うものを検出させていますが、気にせず進めます。

一応、過去の記事のリンクも貼っておきます。

+ [ラズパイで将棋駒の物体検出　ーMovidiusのインストール編ー](https://qiita.com/shinmura0/items/fa352f42bde5bff86948)
+ [地味な物体検出ですみません。　ープロジェクトの立て直しー](https://qiita.com/shinmura0/items/967e9eb02724639a7624)
+ [地味な物体検出ですみません。　ーOpenVINOのインストールー](https://qiita.com/shinmura0/items/318c775544fae64ae0db)

今回は、物体検出を使って組立検査機を作ってみました。

#まずは結果から

部品の組み立て工程では、ボルトの締め忘れや組付け**間違い**がしばしば発生します。
今回は、物体検出を使って組立工程をチェックする検査機を作りました。

###正常工程
![v1319-f7j70.gif](https://qiita-image-store.s3.amazonaws.com/0/264781/3d1a0656-caef-c1c4-d395-8ca6e9298142.gif)

###ヒートマップ（正常）
![normal.jpg](https://qiita-image-store.s3.amazonaws.com/0/264781/5b44e07b-d55e-c293-96f9-609164a2c5ce.jpeg)

###異常工程
![9xn5y-euros.gif](https://qiita-image-store.s3.amazonaws.com/0/264781/9358f8f7-f63e-3a27-d03d-35fb0b97658a.gif)

###ヒートマップ（異常）
![right.jpg](https://qiita-image-store.s3.amazonaws.com/0/264781/691cd37f-13b3-f574-0b61-1935cc53ca23.jpeg)

#組立検査の難しさ
組立検査は難しいものがあり、現状では決定版はないものと思われます。
その難しさの要因は、以下のようなものが挙げられます。

+ 完成後の外観検査ではチェックできない。（外から見えない部分で組立間違いがあるかもしれない）
+ 組立間違いがあっても、動作チェックで不具合が出ない。

特に2番目の方は、根が深く、短期間使っている分には問題ないが、長期間
使っているといきなり壊れるといったケースもあるので、重大クレームに
なってしまうこともあります。

IOTの普及によりカウンタ付きドライバーなどが開発され、記録できる工程も
出てきましたが、接着剤の塗布など記録できない工程もあります。

#物体検出×組立工程
今回の取り組みは、物体検出を使って組立中の手を認識して、正常な作業時間と
位置になっているかどうかをチェックするものです。

#使い方
まずは、使ってみたいという人は以下の方法で使ってみてください。

##環境
+ Raspberry Pi 3
+ NCS1(Movidius)かNCS2を装着
+ OpenVINOがインストール済（インストール手順は[前回の記事](https://qiita.com/shinmura0/items/318c775544fae64ae0db)を参照。）
+ USBカメラ

##ダウンロード
こちらの[リポジトリ](https://github.com/shinmura0/AssemblyCheck)から``` main.py```をダウンロード

@PINTO さんの[リポジトリ](https://github.com/PINTO0309/MobileNet-SSD-RealSense)から``` lrmodel```をダウンロード

二つのフォルダを同一のフォルダに入れ、以下のコマンドで実行します。

```
python3 main.py -wd 640 -ht 480
```

##手順

後は、以下の手順で動かしてください。

+ 画面が立ち上がったら、[m]ボタンを押して人の手の動きを認識させてください。
+ 認識が終わったら、[e]ボタンを押してください。
+ お手本ヒートマップ（「Reference」）が出てきますが、ここでは無視してください。

次に検査工程に入ります。

+ [s]ボタンを押して先ほどの手の動きを再現してください。
+ 認識が終わったら、[e]ボタンを押してください。
+ 検査ヒートマップ（「Result」）が出てきます。
+ 正常な手の動きをしたのであれば、ほとんど赤い部分はないはずです。
+ 異常な手の動きをしたのであれば、その部分が赤くなっているはずです。
+ 再度、[s]ボタンで検査、[e]ボタンで検査ヒートマップの出力ができます。
+ [q]ボタンで終了します。

#アルゴリズム
##謝辞

@PINTOさんが[こちら](https://github.com/PINTO0309/MobileNet-SSD-RealSense)のリポジトリで``` MultiStickSSDwithUSBCamera_OpenVINO_NCS2.py```を
作ってくれました。かなりシンプルなコードになっています。**感謝！！**

私は、RealSenseを持っていないため、上記のコードをベースにしました。

##変更点
オリジナルのコードに対し変更点は##を付けています。
気になる方は``` main.py```を追って見てください。

主な変更点は以下のとおりです。

+ Personを検知したときだけ、赤い表示が出る。
+ 文字を黒に変更（組み立て工程は白い背景が多いため）
+ 存在確率の閾値を変更（60％ →　30％）
+ 組立ヒートマップのアルゴリズムを組み込む
+ フォルダ内にヒートマップを保存する

##ヒートマップの仕組み

ヒートマップの生成は基本的にPersonと認識したときだけ、演算しています。

###お手本ヒートマップ

まずは、お手本ヒートマップを作ります。仕組みは簡単です。

下の図は5×5ピクセルの画像をイメージしたものです。

![t123.png](https://qiita-image-store.s3.amazonaws.com/0/264781/c952288c-ffa1-7f8a-a3ed-ba8d3209c90c.png)

t時間で右下にPerson（手）と認識したとします。このとき、そこの部分を1にしておきます。
そして、t+1時間でも右下にPerson（手）と認識したとして、1にしておきます。
t+2時間では左下でPerson（手）と認識したとします。

最後にそれらを足し合わせると下図のようになります。

![t_sum.png](https://qiita-image-store.s3.amazonaws.com/0/264781/32cccfd2-8e93-f706-9f4c-166f66cd3051.png)

最後に0～1になるように標準化します。

上の図全体を2で割ります。すると、下図のようなお手本ヒートマップの出来上がります。

![t_stand.png](https://qiita-image-store.s3.amazonaws.com/0/264781/02cdb268-27fa-a829-ec0f-1698732f823a.png)

###検査ヒートマップ

検査工程では、お手本ヒートマップと同じように、マップを作り、
お手本ヒートマップの差をとって絶対値化しています。

あとは、カメラの画像と合成して出力しています。

#結果
以下に動作の様子を示します。

本来であればラズパイ + NCS2は**20FPS**(NCS1は8FPS)で高速に動くのですが、
動画保存用にOpenCVを動かしているため、少し遅くなっています。

###お手本の動作
最初にお手本の動作です。
今回は組立工程を簡単にするため、付箋を貼る動作を題材にしています。

![om6c0-zn8en.gif](https://qiita-image-store.s3.amazonaws.com/0/264781/67fac0c8-a830-3962-e5e4-dfcfdbc786d2.gif)

1つの付箋を3秒くらいで貼っています。
お手本ヒートマップは以下のようになっています。

![Reference.jpg](https://qiita-image-store.s3.amazonaws.com/0/264781/245ca9f6-80c4-ca29-e11b-951818ae70ac.jpeg)

比較的、右手を検出した時間が長くなっているようです。

###正常な動作
これ以降、動画と検査ヒートマップをセットで示します。
まずは、正常な動作です。

![v1319-f7j70.gif](https://qiita-image-store.s3.amazonaws.com/0/264781/3d1a0656-caef-c1c4-d395-8ca6e9298142.gif)

![normal.jpg](https://qiita-image-store.s3.amazonaws.com/0/264781/5b44e07b-d55e-c293-96f9-609164a2c5ce.jpeg)

ご覧のとおり、ほとんど赤い部分はなく、正常な動作が可視化できています。

###右しかやっていない場合（異常）
右しか付箋を貼っていない場合です。
![9xn5y-euros.gif](https://qiita-image-store.s3.amazonaws.com/0/264781/9358f8f7-f63e-3a27-d03d-35fb0b97658a.gif)

![right.jpg](https://qiita-image-store.s3.amazonaws.com/0/264781/691cd37f-13b3-f574-0b61-1935cc53ca23.jpeg)

ご覧のように左側にオレンジ色の異常部分が出てきました。

###左しかやっていない場合（異常）

左しか付箋を貼っていない場合です。

![r8qap-1gynh.gif](https://qiita-image-store.s3.amazonaws.com/0/264781/a68b1ddb-5b75-9c56-dbd2-368dada63630.gif)

![left.jpg](https://qiita-image-store.s3.amazonaws.com/0/264781/558e8a5c-ad0d-970f-1106-794553ec0482.jpeg)

ご覧のように右側に赤色の異常部分が出てきました。

###長時間の動作（正常）
ベテランの人は早く作業できますが、慣れていない人は
長時間の作業時間になってしまうこともあります。

前述したとおり、検査工程のマップではお手本マップと同様に標準化しているため、
全体の作業時間が長くなっても同じ土俵で比較できます。

![ht9t2-vc2iq.gif](https://qiita-image-store.s3.amazonaws.com/0/264781/65a7da34-85ae-3b7d-ef7c-652f7ec0a231.gif)

![long.jpg](https://qiita-image-store.s3.amazonaws.com/0/264781/495842ff-4f1b-9b1c-24b1-e10d788b46f3.jpeg)

お手本の動作に対し、２倍時間がかかっていますが、大体正常な検査ヒートマップになっています。

検出枠に少しズレがあるのが気になります。
検出枠のズレへの対処方法は後述します。


###両手でやった場合（正常）
人によって組立手順は違います。

右からやる人もいれば、左からやる人もいるかもしれません。
もしくは、両手でやる人もいるかもしれません。

![9ng9r-p4qfv.gif](https://qiita-image-store.s3.amazonaws.com/0/264781/417a3dba-e90b-ade4-9f81-312d8dd3e0b4.gif)

![both.jpg](https://qiita-image-store.s3.amazonaws.com/0/264781/09518fda-4347-8bbc-c501-6ed65de2558e.jpeg)

ときどき、左右の手が一つの検出枠になってしまうこともありますが、
検査ヒートマップでは大体正常になっています。

#ガチでやる人のために
もっと本気でやる人のために、メモを残しておきます。

###手の検出精度を上げるには
MobileNET + SSDの「Person」は本来「手」ではなく、「人体」全体を学習させています。
従って、手の検出精度は悪いです。顔が入っていれば、ほぼ100％検出できるのですが・・・

ただ、色の濃い長袖（作業着など）を着ると手の検出精度が上がります。
白い生地のものはダメみたいです。

###位置ズレに弱い
現状は、記憶させたヒートマップと差をとっているだけなので、位置ずれに対し
脆弱です。ただ、ヒートマップを画像として認識させ、ディープラーニングで
異常判定させると非常に安定し、柔軟性がある検査ヒートマップが生成されると思います。

###複雑な工程に対応できない
工具を使った複雑な工程はうまく判定できない可能性があります。ここは、手ではなく
工具を認識させた方が安定した結果が得られると思われます。

###複数工程に対応できない
例えば、ある部品のA面でボルトを締め、裏返してB面で接着剤を塗るといった
複数工程がある場合、現状では対応できません。実は、ここでもアイディアがあり、
複数工程を自動検出できると考えています。

ただ、論文にできるかもしれないので、まだお話しはできません。

もし企業の方で一緒に開発したいという方がいらっしゃれば、共同研究など対応
できるかもしれません。その場合は、メールしていただけると幸いです。
メールアドレスはプロフィールに書いてあります。

#まとめ

+ 物体検出を使って組立工程の検査機を作りました。
+ 組立工程だけではなく、他の作業でも応用が利くかもしれません。
+ 工具など新たなものを学習させる場合、時間と労力がかかるので、ある程度覚悟して望まないと闇の世界に落ちます！お気をつけください。