Splatoon2 のイカアバター画像の位置判定

## 動機

スプラトゥーン2において **画面の中での敵味方の位置を特定する** という点が重要な場面にちょくちょく出くわします。

スプラ上位勢は比較的容易にそうした技術を備えていたりしますが、スプラ2から始めた私のような下位勢にとってはそもそもそうした敵味方の位置特定自体が難しいという課題があったりします。そうした **職人芸のような位置特定を自動化できないのか** というところが動機の一つとしてあります。

そこでまず始めのとっかかりとして **スプラトゥーン2のハイカラスクウェア（広場）のなかで自身のイカアバター（通称イカちゃん）を縦横無尽に動かしながらパシャパシャと画面を撮り、その画像に対してイカちゃんの位置情報を付与して、 Deep Learning（[YOLOv3](https://pjreddie.com/darknet/yolo/)） で学習させた後、その学習データを用いて学習データ以外の画像でイカちゃんの位置を判定させてみる** ということを試してみました。

その結果と手順を以下に紹介しようと思います。

イカちゃん（学習画像データ作成中の様子)：
![Screenshot from 2018-04-09 01-42-03.png (1.0 MB)](https://img.esa.io/uploads/production/attachments/6271/2018/04/09/31597/16ecb91d-5ee6-49e4-a71b-d516d94fa48b.png)

## 環境

今回用いた環境は下記です。

ハード：

* PC: [GTX1080 の載ったマシン(一例)](https://amzn.to/2ELMHvt)
* ゲーム機本体: [Nintendo Switch](https://amzn.to/2Hp4Y7k)
* ソフト: [スプラトゥーン2](https://amzn.to/2GX0bXb)
* [MicroSDカード64GB](https://amzn.to/2qvBc6X)

ソフト：

* OS: Ubuntu 16.04
* [YOLOv3](https://pjreddie.com/darknet/yolo/)
* NVIDIA Driver Version : 390.30
* Cuda compilation tools : release 9.1, V9.1.85

データ：

* 今回用いた[イカちゃん画像のデータ](https://drive.google.com/open?id=1VVxqL-qaochv4aldALWrYkDy_LjlkXrI) ※ラベル情報付き

## 結果

できました。

20000イテレーション（30時間分くらい）の学習結果を用いて以下のような感じでした。

1枚目は比較的スタンダードな姿、2枚目は走っている姿、3枚目は光が差し込んでる姿です。

分類クラス名は **ika_boy（イカちゃん）** としました。

**それぞれ位置をしっかり認識できてそうな印象でした**。

![predictions00.png (1.9 MB)](https://img.esa.io/uploads/production/attachments/6271/2018/04/11/31597/2baaf1d4-117a-4598-8001-b36590ffaa04.png)
![predictions01.jpg (414.8 kB)](https://img.esa.io/uploads/production/attachments/6271/2018/04/11/31597/7cbe16ce-7977-45fb-b521-cee72ddcef6d.jpg)
![predictions03.jpg (312.9 kB)](https://img.esa.io/uploads/production/attachments/6271/2018/04/11/31597/4786dea0-e1b8-437f-9370-aeed666771aa.jpg)

1クラスしか学習させていないためか、基本100%で ika_boy を認識してる様子（**認識時間は約 0.15 sec でした**）。

実行時のCUI画面：
![Screenshot from 2018-04-10 23-42-14.png (221.5 kB)](https://img.esa.io/uploads/production/attachments/6271/2018/04/11/31597/a1f4d9c5-c3eb-44a4-aa2d-fad0da473c28.png)

ちなみに 900 イテレーションの訓練結果で画像認識させると下の結果です。

**やはりちょっとズレており。画像判定結果としても70%程度でした（エイムを合わせる用途としてはやや不満が残りそう）。**

![predictions.jpg (311.2 kB)](https://img.esa.io/uploads/production/attachments/6271/2018/04/11/31597/a0b53ea1-e185-4775-b0c8-bbfbd9270103.jpg)

## 手順

以下におおまかな手順を示します。

### 1. 学習させたいアバター画像データの用意

今回Nintendo Switch にデフォルトで付いている画面キャプチャ機能を利用し、 スプラトゥーン2 のイカアバター画像を143枚撮影しました。

 Nintendo Switch に MicroSDカードを挿してイカアバターを撮影し、その MicroSDカードをそのまま抜いて [変換アダプタ](https://amzn.to/2EusCcM) 等でPCに接続して jpg データを吸い出しました。

MicroSDを開くと2018（おそらく年）フォルダのなかの4（月フォルダ）のなかに日付フォルダが格納されているので、撮影当日のフォルダを選んで、必要な画像をPCに保存します。

**躍動感のあるイカちゃん**：
![2018040813250000-C616B031331154665D639EF16DA76BC0.jpg (210.5 kB)](https://img.esa.io/uploads/production/attachments/6271/2018/04/09/31597/93924621-481d-4380-b24f-ed22cce4f116.jpg)

**バイト小屋の前のイカちゃん**：
![2018040813243800-C616B031331154665D639EF16DA76BC0.jpg](https://qiita-image-store.s3.amazonaws.com/0/92806/f236229d-623e-a6b7-bde7-5247fa775574.jpeg)

**ジャンプしてるイカちゃん**：
![2018040813263600-C616B031331154665D639EF16DA76BC0.jpg](https://qiita-image-store.s3.amazonaws.com/0/92806/b1537f44-8431-a695-edf4-2453dae33d9f.jpeg)

### 2. 位置情報の設定

 [BBox Label Tool](https://github.com/puzzledqs/BBox-Label-Tool) などの画像の位置情報設定ツールを用いて　143枚の画像一枚一枚についてイカアバターの位置を手で設定します。

 [BBox Label Tool](https://github.com/puzzledqs/BBox-Label-Tool) は Python2.7 のみ対応のツールのため conda create でPython2.7 の仮想環境を作ってそちらを activate して利用します。

git clone でツールをダウンロードし、 Python2.7 でターミナルからツールを実行します。

```:terminalコマンド
git clone https://github.com/puzzledqs/BBox-Label-Tool.git
cd BBox-Label-Tool
python main.py
```

初期サンプル画像は `.BBox-Label-Tool/Images/001` に入っています。今回用意した 143枚のjpgデータを`.BBox-Label-Tool/Images/002` に保存します。

GUI の Image Dirs に ”002” し Load ボタンをクリックすると画像が表示されるので、マウスでイカアバターの左上の位置にカーソルを合わせてクリックし、次に右下の位置でクリックします。

そうすると赤枠の四角い箱でアバターが囲まれて、その四角い箱の位置情報が `.BBox-Label-Tool/Labels/002` 以下に jpg と同じ名前の txt ファイルとして保存されます。 

**この作業を 143枚一枚一枚すべてに実施します（この作業はむちゃくちゃ単調ですが、学習の精度に関わる大事な部分なので重要と思われます（[コメント参考](https://timebutt.github.io/static/how-to-train-yolov2-to-detect-custom-objects/)）**）。 

![Screenshot from 2018-04-09 02-09-35.png (1.4 MB)](https://img.esa.io/uploads/production/attachments/6271/2018/04/09/31597/5bc92400-0cb1-4671-9e81-d4a6bda48cd6.png)
 
### 3. イカちゃん画像・ラベルの加工

さらに [こちらの記事](https://qiita.com/lnkusu/items/0073cb428bb1950d1e0c) を参考に学習画像とそのラベル情報に加工を加えます。

### 4. YOLOv3の実行

あとは [YOLOv3の本家サイト](https://pjreddie.com/darknet/yolo/) を参考にしながら、GPUマシンでガリガリと学習のための計算を実行させます。

次のコマンドで計算を実行しました（設定ファイル等適宜設定済みのうえ実行）。

```:terminal
./darknet detector train cfg/ika.data cfg/yolov3-ika.cfg darknet53.conv.74
```

計算途中の表示(1826イテレーション、2~3時間ほど）：

```
Region 94 Avg IOU: 0.892867, Class: 0.998944, Obj: 0.963608, No Obj: 0.000429, .5R: 1.000000, .75R: 1.000000,  count: 1
Region 106 Avg IOU: 0.650335, Class: 0.996200, Obj: 0.958325, No Obj: 0.000104, .5R: 1.000000, .75R: 0.000000,  count: 1
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000013, .5R: -nan, .75R: -nan,  count: 0
Region 94 Avg IOU: 0.879506, Class: 0.999516, Obj: 0.997915, No Obj: 0.000791, .5R: 1.000000, .75R: 1.000000,  count: 2
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000002, .5R: -nan, .75R: -nan,  count: 0
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000030, .5R: -nan, .75R: -nan,  count: 0
Region 94 Avg IOU: 0.770652, Class: 0.999293, Obj: 0.998482, No Obj: 0.000616, .5R: 1.000000, .75R: 0.500000,  count: 2
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000003, .5R: -nan, .75R: -nan,  count: 0
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000012, .5R: -nan, .75R: -nan,  count: 0
Region 94 Avg IOU: 0.608555, Class: 0.999868, Obj: 0.640924, No Obj: 0.000364, .5R: 1.000000, .75R: 0.000000,  count: 2
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000075, .5R: -nan, .75R: -nan,  count: 0
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000035, .5R: -nan, .75R: -nan,  count: 0
Region 94 Avg IOU: 0.812624, Class: 0.999592, Obj: 0.942768, No Obj: 0.000543, .5R: 1.000000, .75R: 1.000000,  count: 1
Region 106 Avg IOU: 0.868808, Class: 0.997298, Obj: 0.881743, No Obj: 0.000094, .5R: 1.000000, .75R: 1.000000,  count: 1
1826: 0.174976, 0.161351 avg, 0.000250 rate, 6.205813 seconds, 116864 images
```

ログの見方:

* Region Avg IOU: 高いほど良い
* Avg Recall: 高いほど良い
* 0.161351 avg: 0.006以下が望ましい

[こちら](https://qiita.com/lnkusu/items/0073cb428bb1950d1e0c) の記事によると収束まで 20000イテレーション（記事の環境では19時間）かかったとありました。

そのため、**2~3時間経過時点でざっくりと今回の計算ではおよそ20~30時間は必要** という見積もりが立ちました。

## テスト

計算終了したら下記コマンドで test.jpg を用いたテストが可能となります。

コマンド実行したパスのディレクトリに下記のような**ピンクの四角い箱とクラス名 ika_boy（イカちゃん）と書かれた画像ファイルが書き出されます**。

```:terminal
./darknet detector test cfg/ika.data cfg/yolov3-ika.cfg backup/ika/yolov3-ika_final.weights test.jpg
```

結果（再掲）：
![predictions00.png (1.9 MB)](https://img.esa.io/uploads/production/attachments/6271/2018/04/11/31597/2baaf1d4-117a-4598-8001-b36590ffaa04.png)
![predictions01.jpg (414.8 kB)](https://img.esa.io/uploads/production/attachments/6271/2018/04/11/31597/7cbe16ce-7977-45fb-b521-cee72ddcef6d.jpg)
![predictions03.jpg (312.9 kB)](https://img.esa.io/uploads/production/attachments/6271/2018/04/11/31597/4786dea0-e1b8-437f-9370-aeed666771aa.jpg)


## まとめ・所感

* **YOLOv3にて独自データセットを用いてイカちゃんの位置判定をさせることができました**
* **画像の用意およびそれに対してのラベルを一つ一つ設定するところに手間がかかる印象でした**
* **また実際スプラトゥーン2をプレイしながら活用を考えると [ARゴーグル](https://www.dronediy.jp/2016/05/ar-hmd-holoLens-magicleap.html) のような装備が必要となるかもしれません**