Coral DevBoardでPoseNetを動かしてエッジデバイスのパフォーマンスを比較する

## 【内容】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454012/42e58808-0428-0e03-436f-4ed47796de2a.png)

[前回の記事](https://qiita.com/rhene/items/4419ef08b85e697fe8c0)でDevBoard上でOpenCVを動かせるようになりました。
これにより過去に作ったEdgeTPU + PoseNetを使ったプログラムが動くようになりましたので、各エッジデバイスとのパフォーマンスを比較します。

## 【環境構築】

以前の記事の[「【PoseNet環境構築】」](https://qiita.com/rhene/items/b3bbbfb062dfb1872c9a#posenet%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89)と[「【EdgeTPU + OpenCV + PoseNet】」](https://qiita.com/rhene/items/b3bbbfb062dfb1872c9a#edgetpu--opencv--posenet)を参照して環境構築を行いました。

なお、DevBoardは初期状態では `git` コマンドが入っていないので `sudo apt install git` でインストールしてください。


## 【pose_opencvの実行】
リアルタイムのカメラ映像を使うときは `--videosrc` オプションに整数値を入れてください。
数値は `/dev/video*` に対応する数値になります。
DevBoardでは `/dev/video0` は専用カメラに割り合っているため、USBカメラを使う場合は `1` 以上の値になります。
なお、専用カメラは入手していないため、動作確認は出来ていません。

```bash:pose_opencvの実行(カメラ映像)
# USBカメラ映像による姿勢推定
python3 pose_opencv.py --res 480x360 --videosrc 1
python3 pose_opencv.py --res 640x480 --videosrc 1
python3 pose_opencv.py --res 1280x720 --videosrc 1
```

映像ファイルを使う場合は `--videosrc` オプションに映像ファイルのパスを入れてください。

```bash:pose_opencvの実行(映像ファイル)
# サンプルビデオの取得
wget https://github.com/opencv/opencv/raw/master/samples/data/vtest.avi

# サンプルビデオ映像による姿勢推定
python3 pose_opencv.py --res 480x360 --videosrc ./vtest.avi
python3 pose_opencv.py --res 640x480 --videosrc ./vtest.avi
```


## 【結果】
## 【実行結果 (カメラ映像)】
|解像度   | Platform               |推論時間 (ms) |FrameIO (ms) |FPS     |備考                |
|:------:|:-----------------------|------------:|-------------:|-------:|:-------------------|
|1280x720| RaspberryPi3 + EdgeTPU |       279.4 |        75.82 |   2.47 |                    |
|-       | DevBoard               |        44.9 |        42.89 |   7.46 |                    |
|-       | JetsonNano   + EdgeTPU |        49.2 |        23.82 |   7.44 |                    |
|640x480 | RaspberryPi3 + EdgeTPU |        94.4 |        27.48 |   7.16 |                    |
|-       | DevBoard               |        13.5 |        15.26 |  24.36 |                    |
|-       | JetsonNano   + EdgeTPU |        15.0 |         8.53 |  29.89 | カメラの性能限界    |
|480x360 | RaspberryPi3 + EdgeTPU |        53.5 |        12.34 |  12.57 |                    |
|-       | DevBoard               |         8.2 |        10.92 |  30.18 | カメラの性能限界    |
|-       | JetsonNano   + EdgeTPU |         9.7 |         4.21 |  30.06 | カメラの性能限界    |

## 【結果 (ビデオファイル)】
|解像度   | Platform               |推論時間 (ms) |FrameIO (ms) |FPS     |備考                |
|:------:|:-----------------------|------------:|-------------:|-------:|:-------------------|
|640x480 | RaspberryPi3 + EdgeTPU |        65.3 |        19.59 |   8.68 |                    |
|-       | DevBoard               |        13.6 |        14.97 |  20.94 |                    |
|-       | JetsonNano   + EdgeTPU |        15.0 |         6.87 |  30.08 |                    |
|480x360 | RaspberryPi3 + EdgeTPU |        33.9 |        10.27 |  14.64 |                    |
|-       | DevBoard               |         7.5 |         8.18 |  31.68 |                    |
|-       | JetsonNano   + EdgeTPU |         8.9 |         4.00 |  45.57 |                    |

FrameIOとFPSを見るとラズパイ3とJetsonNanoの中間の値になっています。
基本スペックからしてもだいたい予想通りの結果です。
TPUとCPU間の接続バスの違いなのか、推論時間に関してはDevBoardが一番早いです。



## 【参考：Multi TPUの場合】
参考までにMulti TPUでの処理を行ってみました。
2つのTPUに対してそれぞれPoseNetとMobileNet SSD v2のモデルをロードして推論しました。
今回はシリアルで処理を行い、それぞれの推論時間と1フレームあたりの処理時間を計測しました。

DevBoardはUSBポートが一つしかないので、USBポートにUSB Hubを繋いで、そこにUSBカメラとEdgeTPUをつなぎました。
その上で内蔵TPUにPoseNet、EdgeTPUにSSDを割り当てました。


### 【実行結果 (カメラ映像)】
|解像度   | Platform                 |推論時間 (ms) <br> PoseNet |推論時間 (ms) <br> SSD |FrameIO (ms) |FPS     |備考                |
|:------:|:-------------------------|------------:|-----------:|-------------:|-------:|:-------------------|
|480x360 | DevBoard   + EdgeTPU     |         7.6 |       23.2 |        67.36 |  11.79 |                    |
|-       | JetsonNano + EdgeTPU x 2 |         8.8 |       15.2 |        35.99 |  19.82 |                    |
|640x480 | DevBoard   + EdgeTPU     |        14.0 |       21.4 |        98.73 |   8.01 |                    |
|-       | JetsonNano + EdgeTPU x 2 |        15.4 |       15.2 |        49.17 |  14.26 |                    |
|1280x720| DevBoard   + EdgeTPU     |        42.1 |       20.7 |       207.71 |   3.60 |1秒程度遅延あり      |
|-       | JetsonNano + EdgeTPU x 2 |        47.2 |       16.1 |       118.82 |   5.55 |0.5秒程度遅延あり    |

推論時間はPoseNet、SSDそれぞれ大きく違いはありません。
ただ、DevBoardのほうがPoseNetは若干早く、SSDの方は遅いようです。
これはTPUの接続方式の違いによるものと思われます。
内蔵TPUはCPUとTPUとの通信が早く、USB Hub経由のUSB接続はJetsonNanoより若干遅いようです。

あと解像度が1280x720の場合、実際の動きに対して画面に描画されている映像には遅延が発生していました。
本体性能に依存しているようで、DevBoardの遅延がかなり目立ちました。


## 【最後に】
DevBoardをセットアップから実行まで一通り使ってみました。
率直な感想はコスパ悪いなと言う感想です。
1年前に発表されたときにすぐに手にできていたらまた印象は違っていたと思いますが、安価で高性能なJetsonNanoが出てしまったので…

DevBoardはMendel LinuxというDebianベースの独自のディストリビューションを使っているため、ビルド済みのバイナリモジュールも少なくセットアップには手間がかかります。
最近は結構充実してきましたが、以前のラズパイを思い出します。
そうやって手間ひまかけて環境を構築したのに、値段の割にはいまいちパフォーマンスが出ないのが少し残念なところです。
明確な目的があり、TPUで実装できることがわかっているのであればDevBoardを使うのもありかと思いますが、現時点では、わざわざこれを選択するメリットは無いかなという印象です。
とはいえ選択肢が増えたという点では良かったかなと思います。