Jetsonを使ったDeep Learning リアルタイム画像分類推論（カスタムモデルを利用）

#目的
[前回作成したカスタムモデル](https://qiita.com/otomon10/items/2b9b4f3730c7121a8e92)を使って、Jetsonに接続したUSBカメラでリアルタイムに画像分類を推論する。
※[このページ](https://github.com/dusty-nv/jetson-inference#running-jetpack-on-the-host)のJetsonに関する部分を日本語で書いているだけです

こちらの画像の右型部分（Jetsonを使った推論）を動作させるイメージです。
![Qiita](https://github.com/dusty-nv/jetson-inference/raw/master/docs/images/digits-workflow.jpg "NVIDIA Deep Learning Tools")

#環境
- [PC環境は前回を参照のこと](https://qiita.com/otomon10/items/ad965d5f8c1cfa8b1a41#pc%E7%92%B0%E5%A2%83)
- Jetson TX1
- USBカメラまたはJetsonカメラモジュール（今回はLogicool C920を利用する）

# Jetpackのインストール

[こちら](https://developer.nvidia.com/embedded/jetpack)から、JetPackのインストーラーをダウンロードする。
インストーラーに実行権限を与えて、ホストPCで実行する。（現時点ではJetPack 3.3が最新）

```terminal
$ cd ~/Downloads/JetPack-L4T-3.3-linux-x64_b39.run
$ chmod +x JetPack-L4T-3.3-linux-x64_b39.run
$ ./JetPack-L4T-3.3-linux-x64_b39.run
```
[インストールガイド](https://docs.nvidia.com/jetpack-l4t/index.html#jetpack/3.3/install.htm%3FTocPath%3D_____3)を参考に、インストールすること。
完了すると、ホストPCとターゲットのJetsonの両方にCUDA Toolkit等がインストールされる。

# 推論デモプログラムの実行

Jetsonで、TensorRTおよびcuDNNを使った推論デモプログラムを実行する。
TensorRTとは、高性能なDeep Learning推論ライブラリのこと。画像分類、セグメンテーション、およびオブジェクト検出に対応している。
cuDNNとは、CUDAを使ったDeep Neural Network(DNN)用のライブラリのこと。畳み込み、正規化演算等が高速実行できるようにチューニングされている。
Jetsonにて、gitとcmakeをインストールし、リポジトリをクローンしてビルドする。（数十分）


```terminal
$ sudo apt-get install git cmake
$ cd ~
$ git clone https://github.com/dusty-nv/jetson-inference
$ cd jetson-inference
$ mkdir build
$ cd build
$ cmake ../
$ make
```

`imagenet-console`プログラムを使用する。
このプログラムは、入力画像に対してImageNet（ILSVRC2012）データセットを使った画像分類デモを実行し、認識率と識別名称を画像にオーバーレイしてファイル出力する。

```terminal
$ cd aarch64/bin
$ ./imagenet-console orange_0.jpg output_0.jpg
```
<img src="https://qiita-image-store.s3.amazonaws.com/0/266169/d1c83847-bf12-a976-3697-a75452757c54.jpeg" width=60%>
次は、`imagenet-camera`プログラムを使用する。
Jetsonにカメラを接続しておくこと。引数に応じて、googlenetまたはalexnetをTensorRTにロードする。

```terminal
$ ./imagenet-camera googlenet   ＃ googlenetを使用
$ ./imagenet-camera alexnet     ＃ alexnetを使用
```

識別率および識別名称がカメラ映像にオーバーレイして表示される。
今回の環境の場合、1280x720、30fpsでリアルタイム推論可能。映像フレームワークにはGstreamerを利用している。
<img src="https://qiita-image-store.s3.amazonaws.com/0/266169/477e2960-42e9-9173-3e42-bc6929e80121.png" width=90%>

# カスタムモデルを利用した推論

上記のプログラムを、前回作成したカスタムモデルで動作させる。
ダウンロードしたカスタムモデルを展開し、以下のディレクトリに格納する。

```terminal
$ mkdir ~/jetson-inference/data/networks/GoogleNet-ILSVRC12-subset-2
$ cd ~/jetson-inference/data/networks/GoogleNet-ILSVRC12-subset-2
$ tar -zxvf ~/Downloads/20180918-135303-14b6_epoch_30.0.tar.gz
```

引数にカスタムモデルのパスを指定してロードする。

```terminal
$ cd ~/jetson-inference/build/aarch64/bin

$ NET=networks/GoogleNet-ILSVRC12-subset-2

$ ./imagenet-console bird_0.jpg output_0.jpg \
--prototxt=$NET/deploy.prototxt \
--model=$NET/snapshot_iter_176340.caffemodel \
--labels=$NET/labels.txt \
--input_blob=data \
--output_blob=softmax
```

左側が元のGoogleNet-1000で、右側が12種類に分けたカスタムモデルの結果。
正しくモデルが読み込めていることがわかる。
![output_0.jpg](https://qiita-image-store.s3.amazonaws.com/0/266169/955ebf20-1f24-fdc2-3129-bb682690385b.jpeg)　　![output_0.jpg](https://qiita-image-store.s3.amazonaws.com/0/266169/5b807c37-a907-7c14-44c4-3b4746c73740.jpeg)

カメラを利用する場合は以下の通り。

```terminal
$ ./imagenet-camera \
--prototxt=$NET/deploy.prototxt \
--model=$NET/snapshot_iter_176340.caffemodel \
--labels=$NET/labels.txt \
--input_blob=data \
--output_blob=softmax
```

Google検索"dog"で出てきた画像で試してみた。
<img src="https://qiita-image-store.s3.amazonaws.com/0/266169/afcacb8d-2d57-4fe3-ba82-3428b4e57a39.png" width=60%>

我が家の猫で試してみた。
<img src="https://qiita-image-store.s3.amazonaws.com/0/266169/3ad365af-8a28-0cca-a219-f47b130370e9.png" width=60%>

たまに**dog**になる。
<img src="https://qiita-image-store.s3.amazonaws.com/0/266169/156a63a0-de09-d6d6-79c7-5d7701a9dd74.png" width=60%>