RaspberryPiで物体検出してみる ~その1：検出速度比較~

#はじめに
RaspberryPiで物体検出を行うにあたり、主要な物体検出手法の一つであるYOLO(You only look once)の各ソースの検出速度と検出精度を比較してみたのでまとめます。

YOLOの仕組みについては[【物体検出手法の歴史 : YOLOの紹介】](https://qiita.com/mdo4nt6n/items/68dcda71e90321574a2b)が分かり易かったです。


## 私がRaspberryPi でやりたいこと
猫用のペットカメラとするついでに、4匹の猫を見分けたい！柄は4匹とも違う！
見分けて何をするかは、猫の様子を監視してエアコンのリモコン制御とか、活動量を見て健康管理に使えたらいいなぁ程度しか考えてないです。

-  MUST：識別するクラス数を変更して、オリジナルの学習モデルを作ることができる(今回の記事のスコープからは外れます)
-  MAY：できれば1秒に1回は判定したい

##環境
 ![RaspberryPi-RaspberryPi4 ModelB(4GB)](https://img.shields.io/badge/Raspberry Pi-RaspberryPi4 ModelB(4GB) - brightgreen)   ![OS-Raspbian 32bit(2020.5.27版) ](https://img.shields.io/badge/OS-Raspbian 32bit(2020.5.27版) - brightgreen)


#結果
評価対象はCOCOデータセット(クラス数は80)とし、[YOLOの作者のサイト：YOLO: Real-Time Object Detection](https://pjreddie.com/darknet/yolo/)と[AlexeyAB](https://github.com/AlexeyAB/darknet)で配布されている学習済みモデルの重みを用いています。各モデルには検出時間を優先した"Tiny"というものがあります。

以下、ソース×Modelの結果です。説明・結果の画像・所感は後程記載します。

| ソース     | Model     | 検出時間 | 検出精度 |
|:-----------|:----------|-------:|:-------:|
| pjreddie   | v2        | 477秒  | ○ |
| pjreddie   | v2-Tiny   | 42秒   | × |
| AlexeyAB   | v2        | 33秒   | ○ |
| AlexeyAB   | v2-Tiny   | 6.6秒  | △ |
| AlexeyAB   | v3        | 74秒   | ◎ |
| AlexeyAB   | v3-Tiny   | 6.7秒  | ○ |
| AlexeyAB   | v4        | 152秒  | ◎ |
| AlexeyAB   | v4-Tiny   | 7.8秒  | ○ |
| keras-yolo3 | v3       | 12秒   | ◎ |
| keras-yolo3 | v3-Tiny  | 0.75秒 | ○ |
| Tensorflow-YOLOv3 | v3 | 8.9秒  | ◎ |
| Tensorflow-YOLOv3| v3-Tiny | 3.4秒 | ○ |
| yolov3-tf2  | v3       | 5.6秒  | ◎ |
| yolov3-tf2  | v3-Tiny  | 0.67秒 | ○ |

検出精度は主観ですが、各画像の主の物体の認識率を目安にしています。◎(90%～100%)、〇(70%~90%)、△(50%~70%）、×(認識できない)。


#ソースごとの説明・結果画像・所感
## pjreddie/darknet
https://pjreddie.com/
https://github.com/pjreddie/darknet

-  本家
-  v2、v3の学習済みモデルの重みのダウンロードもこちらからできます。
-  C言語
-  物体検出中のCPUの使用率は25~35%で遷移しており、CPUの使用効率は悪い。
-  makeファイルのパラメータを変えることで、GPUで動作させることも可能だが、RaspberryPiでは難しい。
-  v3、yolov3-tinyは`Segmentation fault`で動きませんでした。(Google Colaboratoryでは検出できているので環境の問題)
-  v2-Tinyは物体検出できてなさそうでした。(こちらもGoogle Colaboratoryでは検出できているので環境の問題)

 ![gcc-8.3.0 (Raspbian 8.3.0-6+rpi1)](https://img.shields.io/badge/gcc - 8.3.0 (Raspbian 8.3.0_6+rpi1) - brightgreen)  

| Model| dog| person|
|:-----|------------|------------|
| v2 | ![predictions_v2_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/9296096e-12cb-f8e9-fec1-bdd355b18f04.jpeg)| ![predictions_v2_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/fe3687cf-f195-af86-f740-f7c77aba1dd0.jpeg)|
| v2-tiny|![predictions_v2t_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/ab0ef344-259d-1a94-bea7-5155eb4378f9.jpeg)|  ![predictions_v2t_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/6924db2e-e418-815e-ab5d-351483c54140.jpeg)|


## AlexeyAB/darknet
https://github.com/AlexeyAB/darknet

 - pjreddieの継承版。YOLO v4に対応。
 - YOLO v4の学習済みモデルの重みのダウンロードはこちらからできます。
 - C言語
 - makeファイルのパラメータを変えることで、GPUで動作させることも可能だが、RaspberryPiでは難しい。
 - 物体検出中のCPUの使用率は25~35%で遷移しており、CPUの使用効率は悪い。
 
 ![gcc-8.3.0 (Raspbian 8.3.0-6+rpi1)](https://img.shields.io/badge/gcc - 8.3.0 (Raspbian 8.3.0_6+rpi1) - brightgreen)  

| Model| dog| person|
|:-----------|------------|------------|
| v2 |![predictions_v2_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/716737f6-6e81-8cac-361b-d0c5499a9a55.jpeg) |![predictions_v2_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/a7de4f02-473d-b583-4a85-ddc46432cd11.jpeg) |
| v2-tiny| ![predictions_v2t_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/fbe0f92f-601c-d8cf-24a3-d2a1b0114842.jpeg)| ![predictions_v2t_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/ad48c811-df68-4d20-2eb8-f9b3a6d14b9a.jpeg) |
| v3 |![predictions_v3_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/a4a59237-a0d8-ba2f-13cb-d0a98f8b366d.jpeg) |![predictions_v3_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/fb98d1e8-413a-8b47-5275-fefde9f804bf.jpeg) |
| v3-tiny| ![predictions_v3t_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/be535ea5-a9c9-a57a-609a-95e4ce60d145.jpeg)| ![predictions_v3t_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/62913530-9c0e-6615-e5ef-99affd4c8908.jpeg) |
| v4 |![predictions_v4_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/aa50f909-b5ff-e237-9757-c3d6cd8ebb5a.jpeg) | ![predictions_v4_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/5a493691-e0aa-1a32-ed61-533f1074430f.jpeg)|
| v4-tiny| ![predictions_v4t_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/65733ae3-606d-9ef0-a6b9-e1b5d1c735e7.jpeg)|![predictions_v4t_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/8e786f72-352b-2c64-01a2-73f71a3071ee.jpeg) |


## qqwweee/keras-yolo3
https://github.com/qqwweee/keras-yolo3

- keras版
- pjreddie/darknetの重みをコンバートして使用することができる。
- デフォルトでは検出結果の画像を出力できないので、[KerasのYOLO-v3を動かしたった](https://qiita.com/yoyoyo_/items/10d550b03b4b9c175d9c)を参考に処理を追加しました。　
- 物体検出中のCPUの使用率は100%

 ![Keras-2.2.5](https://img.shields.io/badge/Keras-2.2.5 - brightgreen)  ![tensorflow-1.13.1](https://img.shields.io/badge/tensorflow-1.13.1 - brightgreen) ![Python-3.7.3](https://img.shields.io/badge/Python-3.7.3 - brightgreen) 

| Model| dog| person|
|:-----------|------------|------------|
| v3 |![out_v3_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/e75435bb-e599-d543-fd6e-1ba187301128.jpeg) |![out_v3_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/8ba0f347-60d6-9598-e796-018075ef13cb.jpeg) |
| v3-tiny|![out_v3t_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/4573ed17-6a02-190b-664c-0b5191b4d2e8.jpeg) | ![out_v3t_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/ad487db5-c1cc-ab2b-cf82-76ff2d6c916a.jpeg) |


## neuralassembly/Tensorflow-YOLOv3
https://github.com/neuralassembly/Tensorflow-YOLOv3
[Raspberry Pi で YOLO v3-Tiny / YOLO v3 による物体検出を試してみよう](https://mlbb1.blogspot.com/2019/12/raspberry-pi-yolo-v3-tiny-yolo-v3.html)

- Tensorflow1系
- pjreddie/darknetの重みをコンバートして使用することができる。
- 検出時間は出力されないので、sess.run()の前後で時間を計測。
- 物体検出中のCPUの使用率は100%

![tensorflow-1.13.1](https://img.shields.io/badge/tensorflow-1.13.1 - brightgreen) ![Python-3.7.3](https://img.shields.io/badge/Python-3.7.3 - brightgreen) 


| Model| dog| person|
|:-----------|------------|------------|
| v3 |![image_output_v3_dog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/822fd217-faff-3b9c-80b8-5a77f650b31c.png) |![image_output_v3_person.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/c8e8c792-8dd8-807b-7d46-44bb46c2c038.png) |
| v3-tiny| ![image_output_v3t_dog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/a135d305-9a75-f6cd-6bc7-429371fcd59b.png)|  ![image_output_v3t_person.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/76c54ebe-3562-558e-af95-70347333cf2f.png)|


## zzh8829/yolov3-tf2
https://github.com/zzh8829/yolov3-tf2
 
 - tensorflow2系 (tf.keras使用)
 - pjreddie/darknetの重みをコンバートして使用することができる。
 - RaspberryPiでは`pip install tensorflow`でtensorflow2は入らなかったので、https://github.com/PINTO0309/Tensorflow-bin から`tensorflow-2.2.0-cp37-cp37m-linux_armv7l.whl`をダウンロードしてinstall
 - 物体検出中のCPUの使用率は75~85%

![tensorflow-2.2.0](https://img.shields.io/badge/tensorflow-2.2.0 - brightgreen) ![Python-3.7.3](https://img.shields.io/badge/Python-3.7.3 - brightgreen) 


| Model| dog| person|
|:-----------|------------|------------|
| v3 |![output_v3_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/687b073f-6c29-9c34-12fc-f3902f6da8f0.jpeg)| ![output_v3_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/ecf9f7b2-fec2-7228-53b9-bd45c07f4421.jpeg)|
| v3-tiny|![output_v3t_dog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/867e2fdf-ed06-aa91-6a39-8e3ac9d8e9f8.jpeg)| ![output_v3t_person.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438288/bbff928f-8a3a-684c-ba6c-602c868d0dcc.jpeg)|


#まとめ
- 「1秒に1回は判定したい」を満たすには、多少検出精度は落ちるがPython系のv3-tinyでしか難しい。
- 私が使うときにはクラス数は少なくなるので、それにより精度は上がることを期待する。

##今後の方向性
- 学習はAlexeyABをGPU版でbuildし、Google Colaboratoryで実行する。Tinyなら1000エポック：7分程度。
- 物体検出はPython系の中から流用しやすさを見てどれを使うか決める。(今後のことも考えるとzzh8829/yolov3-tf2が無難か。。)
- 猫の写真撮らないと。。

次回：[RaspberryPiで物体検出してみる ~その2：ねこ画像の学習~](https://qiita.com/SwitchBlade/items/11253433bbf6c34772ac)

#参考
[Raspberry PiでDarknetを使う](https://qiita.com/Brutus/items/b898a4b0e28303f3edfa)
[YOLOv3 論文訳](https://qiita.com/mdo4nt6n/items/7cd5f106adc775e5d92b)

## qqwweee/keras-yolo3
- [YOLO(keras-yolo3)で物体検出をやってみた！](https://qiita.com/hiraku00/items/fe7d55b3ab556ff43786)
- [KerasのYOLO-v3を動かしたった](https://qiita.com/yoyoyo_/items/10d550b03b4b9c175d9c)
- [エンジニアの眠れない夜さん【物体検出】keras−yolo3の使い方](https://sleepless-se.net/2019/06/21/how-to-use-keras%E2%88%92yolo/)


## zzh8829/yolov3-tf2
- [yolov3-tf2を使って、リアルタイム物体検出を簡単に試してみる。／tensorflow v2・keras](https://arakan-pgm-ai.hatenablog.com/entry/2020/06/22/000000)