最新ディープラーニングアルゴリズムを使って物体検出のチュートリアルを動かしてみた

# はじめに

[前回](http://qiita.com/neriai/items/bd7bc36ec42c8ef65b2e)、顔分類器を畳み込みニューラルネットワーク (CNN)を使って作成しましたが、実はこれはまだ初歩の初歩に過ぎなく機械学習の世界はとてつもないスピードで進歩していることを知りました。
命がけで倒したボスが実は１万以上いる敵の中で最弱なのだと知りました。

毎年のように新しいアルゴリズムが論文発表されたり、認識精度を競い合う大会などが行われているようで、進歩している理由としては、認識精度と処理速度の向上が主な目的なようです。
その中で、今回一番最新のアルゴリズムであるSingle Shot MultiBox Detector（SSD）のチュートリアルとなるものを動かしてみました。

詳しい業界内の進歩を読みたい方は以下のページがとてもわかりやすいです。
[SSD: Single Shot MultiBox Detector (ECCV2016)](https://www.slideshare.net/takanoriogata1121/ssd-single-shot-multibox-detector-eccv2016)
要約すると
CNN → R-CNN → FAST R-CNN → FASTER R-CNN　→ SSD（今ここ）

# 今回投稿までに時間がかかった経緯

５日くらいハマりっぱなしで、結果解決の糸口が見いだせませない問題がありました。
というのも、実装自体はPythonを用いるのですが、実はそれを実装する上で必要なライブラリの選択肢が非常に多いということです。

当初は、Tesnorflowを用いた実装しているものをと思いましたが、あまりにも理解ができなさそうなコードなのもあり、ただ無心に動かす目的だと面白くないため、まだコードがミニマムなKerasで実装したものを動かすことにしました。

[参考コード](https://github.com/rykov8/ssd_keras)
Kurasは問題なかったのですが、こちらは動画を直接認識するような仕組みであり、OpenCV、FFmpeg、GTK2が必要なものでした。
結論から申しますと、Homebrewを使ってOpenCVとFFmpegまでは入れられたもの、GTK2がOpenCVにビルドされず、動画読み込みが行われない状態に陥ってしまいました。

brew editして色々書き換えたり、ビルドオプションやこれいれればいいよみたいなもの色々いれてためしましたが、結論HomebrewのOpenCVはGTKをビルドできない設定になっているようでした。
[諦めの結論に至った記事](https://vhquang.com/blogs/post/install-opencv-mac/)

ちなみに、ビルドから試みかけましたが、やはり前評判通りFFmpegのビルドがとても面倒くさかったので途中で諦めました。

# 試行錯誤の結果

上記の元、Chainerを使ったものを試してみることにしました。こちらは動画でなく、静止画を検出できます。
[chainer-SSD](https://github.com/ninhydrin/chainer-SSD)

# 環境

## Git
```zsh
brew install git
```

## Python3.6.1
```zsh
brew install python3
```

## PATHの設定
```zsh
if [ -d $(brew --prefix)/lib/python3.6/site-packages ];then
  export PYTHONPATH=$(brew --prefix)/lib/python3.6/site-packages:$PYTHONPAT
fi
```

## Cython
```zsh
pip3 install cython
```

## Numpy
```zsh
pip3 install numpy
```

## Chainer
```zsh
pip3 install chainer  
```

## Matplotlib
```zsh
pip3 install matplotlib  
```

## git clone
```zsh
cd {ワークスペース}
git clone https://github.com/ninhydrin/chainer-SSD.git  
```

# 準備

```zsh
cd {ワークスペース}/chainer-SSD/util
python3 setup.py build_ext -i
```
※ warningが出ますが、終了していれば問題なく動くはずです。

# 実行

実行用の画像が２枚入れてくれているので、まずはこちらを実行してみましょう。

```zsh
cd {ワークスペース}/chainer-SSD
python3 demo.py img/dog.jpg
/usr/local/lib/python3.6/site-packages/skimage/transform/_warps.py:84: UserWarning: The default mode, 'constant', will be changed to 'reflect' in skimage 0.15.
  warn("The default mode, 'constant', will be changed to 'reflect' in "
```
※ エラーが出ますが、終了していれば問題なく動くはずです。

# 結果

## 犬と車と自転車
<img width="752" alt="スクリーンショット 2017-06-21 16.53.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/90598/49e3b933-2d09-33d2-e59a-0d38512b45e4.png">

## 魚型の自転車と人
<img width="752" alt="スクリーンショット 2017-06-21 16.58.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/90598/1435318e-828b-5939-0e6d-5e53e89dc5ae.png">

# 色々試してみた

## 車と猫
<img width="752" alt="スクリーンショット 2017-06-21 16.56.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/90598/41c0f70f-72f3-d07b-d0e5-5c58655ff94b.png">

## 人と鳥
<img width="752" alt="スクリーンショット 2017-06-21 17.06.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/90598/2a471147-bac9-025f-0f9c-245da6053a4c.png">

## アライグマ
<img width="752" alt="スクリーンショット 2017-06-21 17.08.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/90598/bff4be27-830b-3a42-1e1b-937ec3fbecf3.png">
※ 見事（？）認識せず

## 車椅子の犬
<img width="752" alt="スクリーンショット 2017-06-21 17.09.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/90598/bba3c6db-7cb4-fc63-f764-7428bbd1000f.png">

## 大勢の人
<img width="752" alt="スクリーンショット 2017-06-21 17.10.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/90598/25b89e80-c2ef-ecc8-2e1b-6f7d38f391f6.png">

# 感想

- １画像に対して３物体くらいが検出精度としては限界な感じがあった。
- 画像に写っている物体が小さすぎると検出されない。（リサイズしているからかと思う）
- 背面や横向きやぶれているいるものの精度はまだあまり高くなさそう。（学習が足りないのかもしれない）
- 速度はもともと１画像に対してそこまで遅いと感じてはいなかったので変わらない。（体感で5秒程度）

# まとめ

- ソースコードを読んでオリジナルの画像データを学習させて再度試してみたいなと思います。
- 動画やカメラから直接認識をやってみたいです。（MacかCentOSで簡単な構築方法あれば）
- 日本人または日本語訳された情報が少なすぎる。先生かお互いに教えられるコミュニティがほしいところです。