Raspberry Pi上で物体検出（YOLO v5）をやってみる

# 0. はじめに
こちらの記事の「Raspberry Piで遊ぶ」、まとまった時間が取れたので遊んでみた。
なんとかYOLOV5の実装（といってもコーディングはしてないです）して、実際に画像認識までお試しできた。
結果、**「ライブラリ環境の構築がとてもシンどい」**と身をもって経験した…。

なお、理論や実装（ラベリングや学習）は今回せずに、ツールとしてほぼブラックボックス的にDL(YOLO)を利用してる感じ。

https://qiita.com/hamanhuman/items/106be729f74405c422d4

# 1. 実機の準備
何も分からないけど、画像認識もしたかったので、カメラも併せて適当に購入。
![194DD57A-9750-46C9-A419-1ED4077BCC77.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384185/9799426a-f86f-ab6f-3cb9-9d46b25b81f9.jpeg)


https://www.amazon.co.jp/%E3%83%A9%E3%82%BA%E3%83%99%E3%83%AA%E3%83%BC%E3%83%91%E3%82%A44-%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%83%BC%E3%83%A2%E3%83%87%E3%83%ABB-Raspberry-Computer-Model/dp/B07WR5W2D6

[Raspberry Piモデル]
　・model name : ARMv7 Processor rev 3 (v7l)
　・Model : Raspberry Pi 4 Model B Rev 1.2

※画像認識やるなら、冷却装置も必要そう…めちゃ熱くなる。

(5/9 追記)
冷却ファン付きケースに変更してみた。
ちょうど良い湯加減レベルになってくれた。

```
pi@raspberrypi:~ $ vcgencmd measure_temp
temp=42.8'C
```
![raspi.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384185/a6ae6638-89f0-c07c-3c22-fe0ab5361123.jpeg)



# 2. Raspberry のセットアップ
初期セットアップで躓くと放り投げるので、ここがすんなり通って一安心。
1台目のモニターはうまくいかず、2台目で無事成功。
こちら↓を参考に。キャプチャが多くて、とても分かりやすい、感謝。

https://www.indoorcorgielec.com/resources/raspberry-pi/raspberry-pi-setup/

カメラのセッティングも初めてなので、接続の仕方から分からない。
破壊するのは嫌なので、こちら↓を参考にセッティング。こちらもキャプチャ多くて安心。

https://www.pc-koubou.jp/magazine/17276

# 3. いざ、YOLO v5のセットアップ
こちらの記事のまんま、セットアップしていった。
前段のOpenCVはうまくいったので、YOLOも楽ちんだと思ってたけど、、、ここからがライブラリとの闘いだった。。。

https://konchangakita.hatenablog.com/entry/2020/08/03/220000

## ① そこそこ忠実にやってみる
記事に記載してるとおり、pipでインストールすると躓くようなので、リンク先のtorchやtorchvisionのwheel（Pythonのパッケージの形式）を利用してインストール。


最新版は正義！という思考停止状態でYOLOv5のver5で実行してみる。（ver4でも同様だけど）
すると、こんなエラー。。。
軽くYOLO側を参照してみると、「SiLU」っていう関数がver4から実装された様子。。。うむ…

```
AttributeError: Can't get attribute 'SiLU' on <module 'torch.nn.modules.activation' from  '/usr/local/lib/python3.7/dist-packages/torch/nn/modules/activation.py'>
```
## ② torchを上げてみる
torch側がSiLUを利用できればいいのだな、ってことでYOLOv5のrequirements.txtを参照し、torchを別のwheel探してバージョンアップしてみる。
今考えるとココの判断が非常によろしくなかった…
再度実行すると、、、

```
from torch._C import *
ImportError: libopencv_highgui.so.4.5: cannot open shared object file: No such file or directory
```

もうここからはあまり覚えてないが、ゴチャゴチャやってみたけど、改善せず。
とりあえず、torchとtorchvisionをアンインストールして、落ち着いてみる。

## ③ YOLOのバージョンを下げる
記事どおりにやるために、YOLOのバージョンを下げてみる。
おそらく…YOLOv5 ver2かな？ってことで、ver2で実施してみたが、、、
※torchとtorchvisionはそれぞれ、1.5.0と0.6.0。

```
File "/home/pi/yolov5/models/yolo.py", line 25, in forward
self.training |= self.export
File "/usr/local/lib/python3.7/dist-packages/torch/nn/modules/module.py", line 772, in getattr
type(self).name, name))
torch.nn.modules.module.ModuleAttributeError: 'Detect' object has no attribute 'export'
```

はい、ダメ。[YOLO側のバージョンを上げると解消するらしい…](https://github.com/ultralytics/yolov5/issues/870)

## ④ YOLOv5 ver3.1へ
ということで、ver3.0(Ver3.1)へ。
requirements.txtに記載のものは、ちゃんとバージョンを守ろうとようやく思いつつも、、、
torchを1.6へあげてみつつも、torchvisionのarm用wheelがなく0.6.0のまま強硬突破！
出来ず…

```
return torch.ops.torchvision.nms(boxes, scores, iou_threshold)
File "/usr/local/lib/python3.7/dist-packages/torch/_ops.py", line 61, in getattr
op = torch._C._jit_get_operation(qualified_op_name)
RuntimeError: No such operator torchvision::nms
```

ですよね…。さてどうしよう。。。


# 4. ライブラリ探索
といっても、「torchvisionを0.7以上に上げる」が一番早そうなので、ネットで色々と探してみる。
arm向けのwheelファイルがなかなか見つからなかったのだが、ようやく発見！案外近場にあったという。。。

### TorchVision 0.7.0
非公式だけど有志で公開してくださるのありがたい。
https://github.com/Paratra/torch160_vision070_armv7


で、実行すると…動いた！！
![zidane.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384185/38e419d0-b94d-8036-03c5-317a8a65f644.jpeg)

デモと同様な感じで人とネクタイを検出できている。
が、地味に時間かかってるのが気になる。（約6秒ほど）カメラの場合、使い物になるのかしら…

# 5. カメラでのリアルタイム物体検出
YOLO5のReadmeどおりに--source 0と設定するとカメラからの画像に対して、物体検出を実施してくれる。
※デフォルトでは上記のジダンやバスの画像に対して検出を実施。

```
$ python3 detect.py --source 0 
```

B'zのお二方をちゃんと認識してくれました！
稲葉さんが辛うじて人と認識してるのはきっと神に近しい存在だからか。松本さんもそうだろうけど。

ちなみに、手前のペンは頑なに認識してくれなかった。
こういう既存の学習済データをビジネスで利用する際には、どう判断・評価していくんだろう？
気になるので誰かに聞くか調べてみよう。
なんとなく学習データを公開してそうな気もするし、、、そこがモデルとしての価値でもあるから非公開な気もする。。。
推測だけど、後者はどちらかというとGPT3とか超大規模言語モデルの場合で、画像認識系は前者なのかな？

![yolo-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384185/8d08cdc6-e42e-2760-967b-3ad8d38e39b2.png)

なお、めちゃくちゃカクつく。5秒に1回ほど判定してるので、そのままカメラ映像にも反映されてしまう様子。
その時のターミナルを見てみると、、

![result_comand.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384185/7c1c7bf0-cd2c-ac64-72d2-4f3858d7071d.png)

何度か松本さんがCATと判定されてる。
松本さんって可愛い時あるものね。猫よりも犬っぽいけど。


# 6. おわりに
エッジコンピューティングでの物体検出を体験できた。
やはり動くものが実際に見れると、楽しいですね。1日があっという間に溶けた。

ただ、あまりにもカクつくので、モデルを軽量化するのか、別のアルゴリズムでの実装を試してみよう。

# 7. 参考
YOLOv5 ver3.1で動作した際のライブラリ一覧を残しておく。
が、すいません、途中Tensorflowに浮気をしてしまい、不要なライブラリも入ってます。。

<details><summary>YOLOv5 ver3.1での動作環境</summary><div>

```
pi@raspberrypi:~ $ pip3 list
Package Version

absl-py 0.12.0
appdirs 1.4.3
asn1crypto 0.24.0
astor 0.8.1
astroid 2.1.0
asttokens 1.1.13
atomicwrites 1.1.5
attrs 18.2.0
automationhat 0.2.0
beautifulsoup4 4.7.1
blinker 1.4
blinkt 0.1.2
buttonshim 0.0.2
cached-property 1.5.2
cachetools 4.2.2
Cap1xxx 0.1.3
certifi 2018.8.24
chardet 3.0.4
Click 7.0
colorama 0.3.7
colorzero 1.1
cookies 2.2.1
cryptography 2.6.1
cupshelpers 1.0
cycler 0.10.0
Cython 0.29.23
decorator 4.3.0
docutils 0.14
drumhat 0.1.0
entrypoints 0.3
envirophat 1.0.0
ExplorerHAT 0.4.2
filelock 3.0.12
Flask 1.0.2
fourletterphat 0.1.0
future 0.18.2
gast 0.2.2
gdown 3.13.0
google-auth 1.30.0
google-auth-oauthlib 0.4.4
gpiozero 1.5.1
grpcio 1.37.1
guizero 0.6.0
h5py 3.2.1
html5lib 1.0.1
idna 2.6
importlib-metadata 4.0.1
ipykernel 4.9.0
ipython 5.8.0
ipython-genutils 0.2.0
isort 4.3.4
itsdangerous 0.24
jedi 0.13.2
Jinja2 2.10
joblib 0.13.0
jupyter-client 5.2.3
jupyter-core 4.4.0
kazam 1.4.5
Keras 2.3.1
keyring 17.1.1
keyrings.alt 3.1.1
kiwisolver 1.0.1
lazy-object-proxy 1.3.1
logilab-common 1.4.2
lxml 4.3.2
Markdown 3.3.4
MarkupSafe 1.1.0
matplotlib 3.0.2
mccabe 0.6.1
microdotphat 0.2.1
more-itertools 4.2.0
mote 0.0.4
motephat 0.0.3
mypy 0.670
mypy-extensions 0.4.1
nose 1.3.7
nudatus 0.0.4
numpy 1.20.2
oauthlib 2.1.0
olefile 0.46
opencv-python 4.5.1.48
opt-einsum 3.3.0
pandas 1.2.4
pantilthat 0.0.7
parso 0.3.1
pexpect 4.6.0
pgzero 1.2
phatbeat 0.1.1
pianohat 0.1.0
picamera 1.13
pickleshare 0.7.5
picraft 1.0
piglow 1.2.5
pigpio 1.44
Pillow 5.4.1
pip 21.1.1
pluggy 0.8.0
prompt-toolkit 1.0.15
protobuf 3.15.8
psutil 5.5.1
py 1.7.0
pyasn1 0.4.8
pyasn1-modules 0.2.8
pycairo 1.16.2
pycocotools 2.0.2
pycodestyle 2.4.0
pycrypto 2.6.1
pycups 1.9.73
pyflakes 2.0.0
pygame 1.9.4.post1
Pygments 2.3.1
PyGObject 3.30.4
pyinotify 0.9.6
PyJWT 1.7.0
pylint 2.2.2
pyOpenSSL 19.0.0
pyparsing 2.2.0
pyserial 3.4
pysmbc 1.0.15.6
PySocks 1.7.1
pytest 3.10.1
python-apt 1.8.4.3
python-dateutil 2.7.3
pytorch-wheel-installer 0.2.1
pytz 2021.1
pyxdg 0.25
PyYAML 5.4.1
pyzmq 17.1.2
qtconsole 4.3.1
rainbowhat 0.1.0
reportlab 3.5.13
requests 2.21.0
requests-oauthlib 1.0.0
responses 0.9.0
roman 2.0.0
RPi.GPIO 0.7.0
rsa 4.7.2
RTIMULib 7.2.1
scikit-learn 0.20.2
scipy 1.5.1
scrollphat 0.0.7
scrollphathd 1.2.1
seaborn 0.11.1
SecretStorage 2.3.1
semver 2.0.1
Send2Trash 1.5.0
sense-emu 1.1
sense-hat 2.2.0
setuptools 56.0.0
simplegeneric 0.8.1
simplejson 3.16.0
six 1.12.0
skywriter 0.0.7
sn3218 1.2.7
soupsieve 1.8
spidev 3.4
ssh-import-id 5.7
tensorboard 2.0.2
tensorboard-data-server 0.6.0
tensorboard-plugin-wit 1.8.0
tensorflow 1.14.0
Theano 1.0.5
thonny 3.3.0
thop 0.0.31.post2005241907
torch 1.6.0a0+b31f58d
torchvision 0.7.0a0+78ed10c
torchvision-raspi 0.2.1
tornado 5.1.1
touchphat 0.0.1
tqdm 4.60.0
traitlets 4.3.2
twython 3.7.0
typed-ast 1.3.1
typing-extensions 3.10.0.0
uflash 1.2.4
unicornhathd 0.0.4
UNKNOWN 0.0.0
urllib3 1.24.1
wcwidth 0.1.7
webencodings 0.5.1
Werkzeug 0.14.1
wheel 0.32.3
wrapt 1.12.1
zipp 3.4.1
```

</div></details>