YOLOv3のKeras版実装（keras-yolo3）をonnxに変換する

# TL;DR

- [YOLOv3のKeras版実装を利用したオリジナルデータ学習手順（2020年6月24日時点）](https://qiita.com/tfukumori/items/d1f79078803d8a7fe103)で作成したHDF5形式（*.h5）をONNX形式に変換する方法

# 参考とするサイト

[axinc-ai/yolov3-face](https://github.com/axinc-ai/yolov3-face)
[onnx/keras-onnx](https://github.com/onnx/keras-onnx)

# 注意点

~~変換したonnxファイルで推論できないことがありました。元々用意されていたonnxファイルでは推論できています。詳細な条件はまだ特定できていません。~~

別の方に指摘いただいたのですが、Netronで確認すると元々のリポジトリでは作成されるONNXファイルのファイルバージョンが`ONNX v6`です。しかし、`pip install keras2onnx==1.5.1`を行うと`onnx=1.7.0`がインストールされる影響で作成されるONNXファイルのバージョンが`ONNX v7`となるため、正常動作しないと思われます。

onnx, onnxconverter-commonを`1.7.0`から`1.6.0`に下げることで元々用意されている重み付けファイルを利用したONNXファイル作成と推論の動作確認は行えています。

# 1. 環境の作成

## 1.1. ソースの準備

[axinc-ai/yolov3-face](https://github.com/axinc-ai/yolov3-face)からgitでクローンする

```posh
git clone https://github.com/axinc-ai/yolov3-face.git
```

続けて、yolov3-face内でリンクしているkeras-yolo3をクローンする

```posh
cd .\yolov3-face
git clone https://github.com/qqwweee/keras-yolo3.git
```

## 1.2. 変換用python環境作成

condaで仮想環境「yolov3-face」を作成する

```posh
conda create -n yolov3-face python=3.6 -y
```

必要なモジュールをインストールする。
[axinc-ai/yolov3-face](https://github.com/axinc-ai/yolov3-face)で細かいバージョンが指定されており、condaのリポジトリに用意されていないため、pipでインストールする

```posh
conda activate yolov3-face
pip install tensorflow==1.13.2
pip install keras==2.2.4
pip install keras2onnx==1.5.1
pip install opencv-python
pip install pillow
pip install matplotlib
```

### 1.2.1. onnxconverter-commonとonnxのバージョンを下げる

#### 1.2.1.1. [axinc-ai/yolov3-face](https://github.com/axinc-ai/yolov3-face)はONNX 1.7.0（ONNX v7）では動作しない

```posh
pip install onnxconverter-common==1.6.0
pip install onnx==1.6.0
```
[axinc-ai/yolov3-face](https://github.com/axinc-ai/yolov3-face)の推論は、ONNXのバージョンが`ONNX v6`が前提となっているため正常に動作しない。

onnx==1.6.0、onnxconverter-common==1.6.0に下げる。

#### 1.2.1.2. [TensorRTとONNXの対応バージョンは厳密に決まっている](https://qiita.com/tfukumori/items/3f438294e722bc29fe16#13-tensorrt%E3%81%A8onnx%E3%81%AE%E5%AF%BE%E5%BF%9C%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3)

|TensorRT|ONNX|URL|
|---|---|---|
|7.x|1.6.0|https://docs.nvidia.com/deeplearning/tensorrt/release-notes/tensorrt-7.html|
|6.x|1.5.0|https://docs.nvidia.com/deeplearning/tensorrt/release-notes/tensorrt-6.html|
|5.x|1.4.1|https://docs.nvidia.com/deeplearning/tensorrt/release-notes/tensorrt-5.html|
|4.x|1.0|https://docs.nvidia.com/deeplearning/tensorrt/release-notes/tensorrt-4.html|

**TensorRT 5.xに対応する場合**

```posh
pip install onnxconverter-common==1.6.0
pip install onnx==1.4.1
```

**参考：依存関係ツリー**

```posh:pipdeptreeの結果
keras2onnx==1.5.1
  - numpy [required: Any, installed: 1.19.0]
  - onnx [required: Any, installed: 1.4.1]
    - numpy [required: Any, installed: 1.19.0]
    - protobuf [required: Any, installed: 3.12.2]
      - setuptools [required: Any, installed: 47.3.1.post20200622]
      - six [required: >=1.9, installed: 1.15.0]
    - six [required: Any, installed: 1.15.0]
    - typing [required: >=3.6.4, installed: 3.7.4.3]
    - typing-extensions [required: >=3.6.2.1, installed: 3.7.4.2]
  - onnxconverter-common [required: >=1.5.1, installed: 1.6.0]
    - numpy [required: Any, installed: 1.19.0]
    - onnx [required: Any, installed: 1.4.1]
      - numpy [required: Any, installed: 1.19.0]
      - protobuf [required: Any, installed: 3.12.2]
        - setuptools [required: Any, installed: 47.3.1.post20200622]
        - six [required: >=1.9, installed: 1.15.0]
      - six [required: Any, installed: 1.15.0]
      - typing [required: >=3.6.4, installed: 3.7.4.3]
      - typing-extensions [required: >=3.6.2.1, installed: 3.7.4.2]
    - protobuf [required: Any, installed: 3.12.2]
      - setuptools [required: Any, installed: 47.3.1.post20200622]
      - six [required: >=1.9, installed: 1.15.0]
    - six [required: Any, installed: 1.15.0]
  - protobuf [required: Any, installed: 3.12.2]
    - setuptools [required: Any, installed: 47.3.1.post20200622]
    - six [required: >=1.9, installed: 1.15.0]
  - requests [required: Any, installed: 2.24.0]
    - certifi [required: >=2017.4.17, installed: 2020.6.20]
    - chardet [required: >=3.0.2,<4, installed: 3.0.4]
    - idna [required: >=2.5,<3, installed: 2.10]
    - urllib3 [required: >=1.21.1,<1.26,!=1.25.1,!=1.25.0, installed: 1.25.9]
```

### 1.2.2. conda list（onnx==1.6.0）

```posh
(yolov3-face) PS > conda list
# packages in environment at C:\Users\user\Anaconda3\envs\yolov3-face:
#
# Name                    Version                   Build  Channel
absl-py                   0.9.0                    pypi_0    pypi
astor                     0.8.1                    pypi_0    pypi
certifi                   2020.6.20                py36_0
chardet                   3.0.4                    pypi_0    pypi
cycler                    0.10.0                   pypi_0    pypi
gast                      0.3.3                    pypi_0    pypi
grpcio                    1.30.0                   pypi_0    pypi
h5py                      2.10.0                   pypi_0    pypi
idna                      2.10                     pypi_0    pypi
importlib-metadata        1.7.0                    pypi_0    pypi
keras                     2.2.4                    pypi_0    pypi
keras-applications        1.0.8                    pypi_0    pypi
keras-preprocessing       1.1.2                    pypi_0    pypi
keras2onnx                1.5.1                    pypi_0    pypi
kiwisolver                1.2.0                    pypi_0    pypi
markdown                  3.2.2                    pypi_0    pypi
matplotlib                3.2.2                    pypi_0    pypi
mock                      4.0.2                    pypi_0    pypi
numpy                     1.19.0                   pypi_0    pypi
onnx                      1.6.0                    pypi_0    pypi
onnxconverter-common      1.6.0                    pypi_0    pypi
opencv-python             4.2.0.34                 pypi_0    pypi
pillow                    7.2.0                    pypi_0    pypi
pip                       20.1.1                   py36_1
protobuf                  3.12.2                   pypi_0    pypi
pyparsing                 2.4.7                    pypi_0    pypi
python                    3.6.10               h9f7ef89_2
python-dateutil           2.8.1                    pypi_0    pypi
pyyaml                    5.3.1                    pypi_0    pypi
requests                  2.24.0                   pypi_0    pypi
scipy                     1.5.0                    pypi_0    pypi
setuptools                47.3.1                   py36_0
six                       1.15.0                   pypi_0    pypi
sqlite                    3.32.3               h2a8f88b_0
tensorboard               1.13.1                   pypi_0    pypi
tensorflow                1.13.2                   pypi_0    pypi
tensorflow-estimator      1.13.0                   pypi_0    pypi
termcolor                 1.1.0                    pypi_0    pypi
typing-extensions         3.7.4.2                  pypi_0    pypi
urllib3                   1.25.9                   pypi_0    pypi
vc                        14.1                 h0510ff6_4
vs2015_runtime            14.16.27012          hf0eaf9b_3
werkzeug                  1.0.1                    pypi_0    pypi
wheel                     0.34.2                   py36_0
wincertstore              0.2              py36h7fe50ca_0
zipp                      3.1.0                    pypi_0    pypi
zlib                      1.2.11               h62dcd97_4
```

## 1.3. 推論用python環境作成

condaで仮想環境「yolov3-face-inference」を作成する

```posh
conda create -n yolov3-face-inference python=3.6 -y
```

必要なモジュールをインストールする。
[axinc-ai/yolov3-face](https://github.com/axinc-ai/yolov3-face)で細かいバージョンが指定されており、condaのリポジトリに用意されていないため、pipでインストールする

```posh
conda activate yolov3-face-inference
pip install tensorflow==1.13.2
pip install onnxruntime
pip install keras==2.2.4
pip install pillow
```

### 1.3.1. conda list

```posh
(yolov3-face-inference) PS > conda list
# packages in environment at C:\Users\user\Anaconda3\envs\yolov3-face-inference:
#
# Name                    Version                   Build  Channel
absl-py                   0.9.0                    pypi_0    pypi
astor                     0.8.1                    pypi_0    pypi
certifi                   2020.6.20                py36_0
gast                      0.3.3                    pypi_0    pypi
grpcio                    1.30.0                   pypi_0    pypi
h5py                      2.10.0                   pypi_0    pypi
importlib-metadata        1.7.0                    pypi_0    pypi
keras                     2.2.4                    pypi_0    pypi
keras-applications        1.0.8                    pypi_0    pypi
keras-preprocessing       1.1.2                    pypi_0    pypi
markdown                  3.2.2                    pypi_0    pypi
mock                      4.0.2                    pypi_0    pypi
numpy                     1.19.0                   pypi_0    pypi
onnx                      1.7.0                    pypi_0    pypi
onnxruntime               1.3.0                    pypi_0    pypi
pillow                    7.2.0                    pypi_0    pypi
pip                       20.1.1                   py36_1
protobuf                  3.12.2                   pypi_0    pypi
python                    3.6.10               h9f7ef89_2
pyyaml                    5.3.1                    pypi_0    pypi
scipy                     1.5.0                    pypi_0    pypi
setuptools                47.3.1                   py36_0
six                       1.15.0                   pypi_0    pypi
sqlite                    3.32.3               h2a8f88b_0
tensorboard               1.13.1                   pypi_0    pypi
tensorflow                1.13.2                   pypi_0    pypi
tensorflow-estimator      1.13.0                   pypi_0    pypi
termcolor                 1.1.0                    pypi_0    pypi
typing-extensions         3.7.4.2                  pypi_0    pypi
vc                        14.1                 h0510ff6_4
vs2015_runtime            14.16.27012          hf0eaf9b_3
werkzeug                  1.0.1                    pypi_0    pypi
wheel                     0.34.2                   py36_0
wincertstore              0.2              py36h7fe50ca_0
zipp                      3.1.0                    pypi_0    pypi
zlib                      1.2.11               h62dcd97_4
```

# 2. 変換および判定（用意されている例で検証）

まずは用意されているサンプルで検証する

## 2.1. 変換

**書式**

```posh
python keras-yolo3-to-onnx.py <h5-model-filepath> <classes-filepath> <anchors-filepath> <onnx-filepath>
```

|パラメータ|指定する内容|
|---|---|
|h5-model-filepath|kerasで作成したモデルファイル|
|classes-filepath|モデル作成時に使用したクラス名を記載したファイル|
|anchors-filepath|モデル作成時に使用したアンカーファイル|
|onnx-filepath|変換後ONNXファイル|

**実行**

```posh
cd .\keras-onnx

conda activate yolov3-face
python keras-yolo3-to-onnx.py ../model_data/logs/trained_weights_final.h5 ../model_data/face_classes.txt ../model_data/tiny_yolo_anchors.txt ../model_data/ax_face.onnx
```

## 2.2. 推論

**書式**

```posh
python inference.py <onnx-filepath> <classes-filepath> <targetimage-filepath> <outputimage-filepath>
```

|パラメータ|指定する内容|
|---|---|
|onnx-filepath|変換後ONNXファイル|
|classes-filepath|モデル作成時に使用したクラス名を記載したファイル|
|inputimage-filepath|推論する画像ファイル|
|outputimage-filepath|推論結果を描画したファイル|

**実行**

```posh
cd .\keras-onnx

conda activate yolov3-face-inference
python inference.py ../model_data/ax_face.onnx ../model_data/face_classes.txt ../images/couple.jpg output.jpg
```

# 3. [YOLOv3のKeras版実装を利用したオリジナルデータ学習手順（2020年6月24日時点）](https://qiita.com/tfukumori/items/d1f79078803d8a7fe103)で処理したファイルの場合

※ファイルは記載の場所にコピーしておく

|ファイル|値|
|---|---|
|kerasで作成したモデルファイル|../model_data/yolo_logs/models/Step2_yolo_weight_mAP_best.h5 |
|クラスファイル|../model_data/voc_classes.txt|
|アンカーファイル|../model_data/yolo_anchors.txt |
|変換後ONNXファイル|../model_data/ax_yolov3.onnx|

## 3.1. 変換

```posh
cd .\keras-onnx

conda activate yolov3-face
python keras-yolo3-to-onnx.py ../model_data/yolo_logs/models/Step2_yolo_weight_mAP_best.h5 ../model_data/voc_classes.txt ../model_data/yolo_anchors.txt ../model_data/ax_yolov3.onnx
```

## 3.2. 推論

```posh
python inference.py ../model_data/ax_yolov3.onnx ../model_data/voc_classes.txt ../images/couple.jpg output.jpg
```

---

# 参考

## keras-yolo3 + JetsonNano

https://qiita.com/rhene/items/b2a8ebe1f003e1107f63
http://mirai-tec.hatenablog.com/entry/2019/08/24/102129
http://mirai-tec.hatenablog.com/entry/2019/09/03/235156

## YOLOv3(Darknet) + JetsonNano

https://soralab.space-ichikawa.com/2019/06/jetson-tx2-tensorrt-yolov3/
https://www.nakasha.co.jp/future/ai/vol2_yolov3nvidia_jetson_nano.html

## TensorRT + Jetson Nano
https://qiita.com/tsutof/items/f81d3900fa77d954ef39

## kerassからONNXに変換する

https://medium.com/axinc/yolov3-66c9b998c096

## その他

https://qiita.com/agumon/items/114da6921c5dc4f7d7f9
https://github.com/zzh8829/yolov3-tf2
https://qiita.com/plseal/items/f493c67b2e810f2f876e
http://mirai-tec.hatenablog.com/entry/2020/01/12/115546
https://rightcode.co.jp/blog/information-technology/tensorflow2-yolov3-run