Jetson Xavier NX で YOLOv4 による物体検出

# はじめに

この記事では，Jetson Xavier NXを使ってdarknetをインストールし，[YOLOv4](https://github.com/AlexeyAB/darknet)を動作させる手続きをまとめます．

Jetson Xavier NXのセットアップについては[別記事](https://qiita.com/futakuchi0117/items/b815fa64563e98602bfc)にまとめており，本記事はセットアップが完了したところから作業を始めています．

# [YOLOv4](https://github.com/AlexeyAB/darknet)とは

- [論文](https://arxiv.org/abs/2004.10934)
- [github](https://github.com/AlexeyAB/darknet)
- [物体認識モデルYOLOv3を軽く凌駕するYOLOv4の紹介](https://blog.seishin55.com/entry/2020/05/16/183132)：日本語によるまとめ

# darknetのインストール

[本家](https://github.com/AlexeyAB/darknet)にしたがってインストールします．

### リポジトリをクローン．

```
$ git clone https://github.com/pjreddie/darknet.git
$ cd darknet
```

### Makefileの編集

`darknet`ディレクトリ直下に`Makefile`があるので，これを編集します．

1. `GPU`, `CUDNN`, `CUDNN_HALF`, `OPENCV`, `LIBSO`の設定を1に変更
2. `ARCH`の設定のうち，`-gencode arch=compute_61,code=[sm_61,compute_61]`をコメントアウト
3. `ARCH= -gencode arch=compute_72,code=[sm_72,compute_72]`をコメントイン

詳しく書くと以下の通りです．

```
GPU=0
CUDNN=0
CUDNN_HALF=0
OPENCV=0
AVX=0
OPENMP=0
LIBSO=0
```

を

```
GPU=1
CUDNN=1
CUDNN_HALF=1
OPENCV=1
AVX=0
OPENMP=0
LIBSO=1
```

のように，書き換えます．また，

```
ARCH= -gencode arch=compute_30,code=sm_30 \
      -gencode arch=compute_35,code=sm_35 \
      -gencode arch=compute_50,code=[sm_50,compute_50] \
      -gencode arch=compute_52,code=[sm_52,compute_52] \
	    -gencode arch=compute_61,code=[sm_61,compute_61]
```

を

```
ARCH= -gencode arch=compute_30,code=sm_30 \
      -gencode arch=compute_35,code=sm_35 \
      -gencode arch=compute_50,code=[sm_50,compute_50] \
      -gencode arch=compute_52,code=[sm_52,compute_52] \
#	    -gencode arch=compute_61,code=[sm_61,compute_61]
```

のように書き換えます．また，

```
# Jetson XAVIER
# ARCH= -gencode arch=compute_72,code=[sm_72,compute_72]
```

を

```
# Jetson XAVIER
ARCH= -gencode arch=compute_72,code=[sm_72,compute_72]
```

のように書き換えます．

### コンパイル

`make`でコンパイルするのですが，そのままだとCUDAへのパスが通っておらず，途中でエラーを吐いて失敗します．

CUDAその他のパスを通します．

```
$ export DARKNET_HOME=/home/_name_/darknet/
$ export CUDA_HOME=/usr/local/
$ export PATH=${DARKNET_HOME}:${CUDA_HOME}bin:${PATH}
$ export PATH=/usr/local/cuda/bin${PATH:+:${PATH}}
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64
```

```
$ source ~/.bashrc
```

パスが通っているか確認

```
$ nvcc -V
```

以下のように出力されれば成功です．

```:output
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2019 NVIDIA Corporation
Built on Wed_Oct_23_21:14:42_PDT_2019
Cuda compilation tools, release 10.2, V10.2.89
```

コンパイル

```
$ make
```

### 画像に対する物体検出

YOLOv4の重みファイルをダウンロード

```
$ wget https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights
```

最初に，darknetのリポジトリにデフォルトで含まれている画像に対して物体検出コードを実行します．

```
$ ./darknet detect cfg/yolov4.cfg yolov4.weights data/dog.jpg
```

処理が完了すると，`~/darknet`配下に`predictions.jpg`が生成されます．

![predictions.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193401/4bc3fd6b-fce2-82bb-4b13-be8b63c213fe.jpeg)

### 動画に対する物体検出

適当な動画（5～10秒程度を推奨）をダウンロードし，`~/darknet`直下に置きます．（以下では`video.mp4`という名前にしています）

動画を対象として物体検出を実行し，検出後の動画を`out.mp4`として保存します．

```
$ ./darknet detector demo ./cfg/coco.data ./cfg/yolov4.cfg ./yolov4.weights video.mp4 -i 0 -thresh 0.25 -dont_show -out_filename out.mp4
```

FPSは11.0～12.0程度でした．Jetson nanoでは1～2FPS程度でしたので，かなり速くなりましたね．

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/jetson?src=hash&amp;ref_src=twsrc%5Etfw">#jetson</a> <a href="https://twitter.com/hashtag/jetsonxaviernx?src=hash&amp;ref_src=twsrc%5Etfw">#jetsonxaviernx</a> <a href="https://twitter.com/hashtag/yolov4?src=hash&amp;ref_src=twsrc%5Etfw">#yolov4</a> <a href="https://t.co/tUoobrgqEg">pic.twitter.com/tUoobrgqEg</a></p>&mdash; S.Tabayashi (@tabayashi0117) <a href="https://twitter.com/tabayashi0117/status/1266042954860253184?ref_src=twsrc%5Etfw">May 28, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 最後に

Webカメラを用いたリアルタイム物体検出を試みたのですが，動作するものの1～2FPSになってしまい，満足な速度が得られていません．

また，[Raspberry Pi Camera Module V2](https://www.amazon.co.jp/Raspberry-Pi-Camera-%E3%82%AB%E3%83%A1%E3%83%A9%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB-Daylight/dp/B01ER2SKFS)から画像を取り込んで物体検出も試みましたが，yolov4にうまく画像が渡せない問題を抱えています．

方法をご存じの方がおられましたら，ご教示ください．

# 免責

本記事の内容は個人的な主張であり，著者の属する企業・集団の公式見解ではありません．

掲載しているコードは著者のメモ程度で，動作を保証するものではありません．