SSD_KerasをWindowsで使って交通量調査できるか試してみた

![SSD512.png](https://qiita-image-store.s3.amazonaws.com/0/140663/bbbb72a4-a2a8-7890-a80c-b467779c248d.png)


#サマリー
この記事は「YOLO V3を使った交通量調査ソフトを作って苦労した」に関連します。要するにディープラーニングや人工知能の映像解析技術を使って、自動車のカウントができるか？という技術的チャレンジです。
最終的にはYOLO V3を採用したのですが、最初にSSDを使ってみてあきらめた話です。

・Windows10にSSD_Kerasをインストール
・SSD_Kerasの実行
・SSD_Kerasの実行詳細
・SSD512の実行結果
・SSD300の実行結果
・結論

#Windows10にSSD_Kerasをインストール

使ったのはこちら。https://github.com/pierluigiferrari/ssd_keras
最初から(YOLOやSSDを全く使ったことがない場合)環境をセットアップする場合は使用するGPUとCUDAとCUDNN、TensorFlow-GPUとKerasの組み合わせがとても大事。私の環境では以下で安定動作しています。

・NVIDIA GTX1080 8GBVRAM(Pascal世代) 
・cuda 9.0.176
・cudnn 7
・Tesorflow-gpu==1.6.0
・keras==2.1.6
・Python3.6 (Anacondaの仮想環境)

SSDのインストールはcudaやcudnnをインストール後に、パッケージをクローンして同封されている「requirements.txt」を使ってライブラリをインストールすればOK。
※「requirements.txt」の中身はご自分の環境に応じてあらかじめ書き直しましょう。特にtensorflow-gpu==1.6.0とかkeras==2.1.6ですね。
インストールは以下のようにコマンドを叩けばOK。用意したAnnacondaの仮想環境をあらかじめActivateするのをお忘れなく。

$> pip install -r requirements.txt

※ライブラリの依存関係で、足りないモジュールがあれば適宜入れましょう。

#SSD_Kerasの実行

SSD_Kerasのプログラムには下記の２種類があります。

・SSD_img.py　画像データから判別して結果を画像で出力する。
・SSD_video.py　動画データを判別しながらリアルタイムに表示する。

今回は動画データを試したかったので、SSD_video.pyを使ってみました。
もう少し細かく言いうとSSD_Videの中にも解析精度優先のSSD512と解析速度優先のSSD300があり、それぞれ試してみました。
残念ながら解析した動画の保存機能がないので、PCの画面を録画するソフトを使ってムービーに起こしました。
SSD512の解析結果はこちら：https://youtu.be/1n6rwgDTv2g
SSD300の解析結果はこちら：https://youtu.be/EzXTmlKMFKw

#SSD_Kerasの実行詳細

任意の静止画や動画を解析したい場合は、ソースをちょっといじる必要があります。
静止画の場合はSSD_img.pyの128行目の画像ファイルのパスを判別したい画像に変更する。
infile  = join("img", "test.jpg")

動画の場合はSSD_video.pyの190行目の動画ファイルのパスを判別したい動画に変更する。
vid_test.run("video/test.mp4")

また解析したいクラスは例えばSSD_video.pyの176行目で以下のように指定しています。

    class_names = ["background",
                   "aeroplane", "bicycle", "bird", "boat",
                   "bottle", "bus", "car", "cat",
                   "chair", "cow", "diningtable", "dog",
                   "horse", "motorbike", "person", "pottedplant",
                   "sheep", "sofa", "train", "tvmonitor"]

不要なクラスがあったら適宜抜いてください。ヘタに消すとエラーが出るので、詳しくない方は全クラスで解析しましょう。

#SSD512の実行結果

![SSD512.png](https://qiita-image-store.s3.amazonaws.com/0/140663/792cf136-d1e1-500c-dfea-f6f8273b2ca9.png)

SSD512を実行する場合は、コマンドプロンプトでSSD_video.pyなどのファイルがあるディレクトリまでCDして、以下のコマンドを叩きます。

$> python SSD_video.py 512

コマンドプロンプトには検出したクラスの名前とスコアが流れていきます。
15fpsくらいは出ている感じでしょうか。
静止画の場合、以下のコマンドで処理を行います。
$> python SSD_img.py 512

コマンドプロンプトに処理時間のログが出ます。
Model Input:  0:00:02.328740
Detected:  0:00:01.279902
Img Output:  0:00:00.843578

こんな感じ。

#SSD300の実行結果

![SSD300.png](https://qiita-image-store.s3.amazonaws.com/0/140663/bed650a0-9065-cc2b-3312-a4c1be964d47.png)

画面が小さいので、さすがに早いですね。21fpsくらいは出ています。
SSD512とだいたい同じフレームでスクリーンショットを取ったのですが、反対車線のトラックを認識しており、逆に重機は認識してません。興味深いですね。

静止画をSSD300を実行する場合は以下のコマンドを叩きます。事前にソースを編集して、解析対象の静止画を指定するようにしましょう。
$> python SSD_img.py 300

コマンドプロンプトに処理時間のログが出ます。確かにSSD512より速いけど…
Model Input:  0:00:02.213278
Detected:  0:00:01.115361
Img Output:  0:00:00.874819

#結論

処理のFPSについては画面の小ささが正義となるのであんまり信用しない。
SSDによる物体検出は画面下側、つまりカメラに近い部分（車両が大きく映るため）で実施されている。逆を言うとカメラから遠い部分では認識されていない。後で採用したYOLO V3ではもっと遠くまで認識されていたので(そのため誤検出も多いのだが)、違いが大きい。

もちろん交通量調査の手法には色んなものがあり、この場合だと画面の下の方にラインを引いて、そこを通過する車両の数をカウントすることも考えられる。でもそれだとOpenCVでやりつくされているので、新鮮さがない感じ。
また車間距離を測定するには、カメラから遠い状態でも対象を検出する必要があり、SSDだと厳しいものがある。よって他にも色々考えて結果、SSDの採用は見送ることになりました。

#関連記事
・[ディープラーニングで故障車両を発見するのに苦労した]
(https://qiita.com/ComputerVision/items/4f377bc3eb5e601676ac)
・[ディープラーニングで映像から速度を正確に算出するのに苦労した]
(https://qiita.com/ComputerVision/items/d5358632209c67dab325)
・[ディープラーニングによる映像解析で車両をトラッキングするのに苦労した]
(https://qiita.com/ComputerVision/items/d865f084c98a59349910)
・[ディープラーニングで交通量調査の映像解析精度を上げるのに苦労した]
(https://qiita.com/ComputerVision/items/2b5e8ed97610085a20c2)
・[YOLO V3を使った交通量調査ソフトを作って苦労した]
(https://qiita.com/ComputerVision/items/bdbf5c237004195a4fbc)