YOLO(keras-yolo3)で物体検出をやってみた！

# やること
- [前回記事](https://qiita.com/hiraku00/items/6b89c3d54e278056df0a)では SSD で物体検出してみましたが、今回は YOLO v3 で物体検出をしてみました

# 手順概要
- 1. コードのダウンロード
- 2. 学習済モデルのダウンロード
- 3. モデルの変換
- 4. コードの修正
- 5. コードの実行
- 6. tiny モデルの使用

# 実行環境
- macOS Catalina 10.15 beta
- python 3.7.4
- tensorflow 1.14.0
- keras 2.2.4
- pillow 6.1.0


# 1. コードのダウンロード
- 以下から keras 版の yolov3 をダウンロードします

```terminal
$ git clone https://github.com/qqwweee/keras-yolo3
```

# 2. 学習済モデルのダウンロード
- 学習済モデルを下記コマンドで取得します

```terminal
$ wget https://pjreddie.com/media/files/yolov3.weights
```

# 3. モデルの変換
- 入手した学習済みデータを Keras 用に変換します。以下のコマンドを入力します
- これで Keras 用の学習済みデータが「model_data」フォルダに入ります(yolo.h5)

```terminal
$ python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5
```

# 4. コードの修正
- yolo_video.py を実行すると下記エラーが出力されるため(ファイル自体は出力可能？)、コードを修正します

```python:AttributeError
Traceback (most recent call last):
  File "yolo_video.py", line 75, in <module>
    detect_video(YOLO(**vars(FLAGS)), FLAGS.input, FLAGS.output)
  File "/Users/XXXXX/anaconda_project/keras-yolo3/yolo.py", line 191, in detect_video
    image = Image.fromarray(frame)
  File "/Users/XXXXX/anaconda3/envs/yolo_v3_keras/lib/python3.7/site-packages/PIL/Image.py", line 2642, in fromarray
    arr = obj.__array_interface__
AttributeError: 'NoneType' object has no attribute '__array_interface__'
```

- 下記の通り、191行目に例外処理(frame が NoneType になった場合)を追加します

```python:yolo.py
# before
    while True:
        return_value, frame = vid.read()
        image = Image.fromarray(frame)

# after
    while True:
        return_value, frame = vid.read()
        if type(frame) == type(None): break
        image = Image.fromarray(frame)
```

# 5. コードの実行
- 下記コマンドにて動画ファイルを指定し、物体検出を実施した結果を出力します  

```terminal:コードの実行
$ python yolo_video.py --input AAA.mp4 --output AAA_out.mp4
```

# 6. tiny モデルの使用
- [前回記事](https://qiita.com/hiraku00/items/6b89c3d54e278056df0a)で SSD を実行した時もそうでしたが、私の環境は CPU のみで実行しているため、実行速度が遅いです
- そこで重いフルモデルではなく、軽い tiny モデルを使います
- tiny モデルは yolo-v3 の計算が少ないモデルなので、CPU でも使いやすいとのことです
- tiny モデルは精度は落ちますが、速いことが特徴です
- #2、#3同様にモデルのダウンロード及び変換を行います

```terminal
$ wget https://pjreddie.com/media/files/yolov3-tiny.weights
$ python convert.py yolov3-tiny.cfg yolov3-tiny.weights model_data/yolo-tiny.h5
```

- また、yolo.py をコピーして、新たにyolo_tiny.py を作成します。
- そして23~24行目のパスを以下の通りに変更します。

```python:yolo_tiny.py
# before
        "model_path": 'model_data/yolo.h5',
        "anchors_path": 'model_data/yolo_anchors.txt',

# after
        "model_path": 'model_data/yolo-tiny.h5',
        "anchors_path": 'model_data/tiny_yolo_anchors.txt',
```

- 加えて、yolo_video.py をコピーして、yolo_video_tiny.py を新たに作成します
- そして3行目の import を以下の通り yolo.py から yolo_tiny.py へ変更します。

```python:yolo_video_tiny.py
# before
from yolo import YOLO, detect_video
# after
from yolo_tiny import YOLO, detect_video
```

- これで実行する準備が出来たので、#5のようにコードを実行します

```terminal:コードの実行
$ python yolo_video_tiny.py --input AAA.mp4 --output AAA_tiny_out.mp4
```

# 実行結果
- 私の環境では CPU のみ使用しているため、前回実行した ssd も今回実行した yolo の何れも処理が遅かったです
- tiny モデルを使用した処理は上記に比べて早くなりましたが、精度(bounding box)も悪くなった印象です

# ソースコード
https://github.com/hiraku00/yolo3_keras_test

# 参考文献
- [Macで物体検知アルゴリズムYOLO V3を動かす](http://starpentagon.net/analytics/yolo_v3_on_mac/)
- [YOLOv3で動画入力時最終フレームの処理後AttributeErrorが出る時の対処法](https://qiita.com/toten_s/items/04d0744598e8c3d9bc9b)
- [物体検出でパトライトの監視（YOLOv3）](https://qiita.com/shinmura0/items/dc0d02dc1e716b912932)
- [KerasのYOLO-v3を動かしたった](https://qiita.com/yoyoyo_/items/10d550b03b4b9c175d9c#github)