TensorFlowのObject Detection APIのData Augmentationで何をやっているか動かして確認

![data_augmentation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/6daefb3e-73f1-c4f6-db08-7b8b1254058b.png)

# Data Augmentation
　Data Augmentation（データの水増し）は、ディープラーニングの画像認識で、学習の際に精度を上げるためのテクニックです。

　この記事は、TensorFlowのObject Detection APIでの物体検出でData Augmentationが何をしているかを、実際に動かしながら確認する方法に関して記載しています。

　Mac/Linuxでの動作を想定しています。WindowsでもPythonのセットアップ部分をWindowsに合わせて修正すれば動くと思います（未確認）。


# TensorFlowのObject Detection APIでのData Augmentation確認
　Object Detection APIでのData Augmentationは[preprocessor.py](https://github.com/tensorflow/models/blob/master/research/object_detection/core/preprocessor.py)というプログラム内で行われています。

　この動作を確認するために、以下2つが必要です。

- Object Detection APIセットアップ
- Data Augmentationの結果をJupyter Notebookで確認

　順に説明していきます。

## Object Detection APIセットアップ
　まずは、Object Detection APIを使えるようにするためにセットアップします。Python環境として、Pyenv, Anaconda, Jupyter Notebook, TensorFlowが必要です。以下記事参照してセットアップ下さい。

[Pythonで機械学習をするための環境を雑にセットアップする方法（Jupyter notebook環境、ディープラーニング環境含む）on Mac/Linux](https://karaage.hatenadiary.jp/entry/2017/10/06/073000)

　環境構築できたら、Object Detection APIをダウンロードします。

```sh
$ cd && git clone https://github.com/tensorflow/models
$ cd ~/models/research
```

　続いて、以下ページを参考にProtobufをコンパイルします。

[Manual protobuf-compiler installation and usage](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/installation.md#manual-protobuf-compiler-installation-and-usage)

　これでObject Detection APIのセットアップは完了です。

## Data Augmentationの結果をJupyter Notebookで確認
　次に、[preprocessor.py](https://github.com/tensorflow/models/blob/master/research/object_detection/core/preprocessor.py)が何をしているかをJupyter Notebookで可視化します。

　可視化に関しては、あらかじめ私が[data_augmentation.ipynb](https://github.com/karaage0703/object_detection_tools/blob/master/scripts/data_augmentation.ipynb)というNotebookを作成したので、そちらを使用していきます。

　以下のコマンドで、Notebookをダウンロードして、Jupyter Notebookでひらけます。

```sh
$ cd ~/models/research/object_detection
$ wget https://raw.githubusercontent.com/karaage0703/object_detection_tools/master/scripts/data_augmentation.ipynb
$ jupyter notebook data_augmentation.ipynb
```

　以下のようにJupyter Notebookが開いたらOKです。順に実行していくと、[preprocessor.py](https://github.com/tensorflow/models/blob/master/research/object_detection/core/preprocessor.py)のData Augmentationの関数が何をしているかが、なんとなく見えてくると思います。

![data_augmentation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/6daefb3e-73f1-c4f6-db08-7b8b1254058b.png)

　可視化した水増しデータを可視化した様子の詳細は、以下ブログ記事参照下さい。

[フリー素材で遊びながら理解するディープラーニング精度向上のための画像データ水増し（Data Augmentation）手法](https://karaage.hatenadiary.jp/entry/2019/07/22/073000)

## Random Black PatchesをRandom Erasingっぽいものに3行で変える方法
 上記記事のRandom Black Patchesは、CutoutとRandom Erasingを元に実装されたData Augment手法と思うのですが、単純な黒よりは、Random Erasingで用いられるランダムなピクセルノイズにした方が効果がありそうな気がします。

　なので、Object Detection APIの[preprocessor.py](https://github.com/tensorflow/models/blob/master/research/object_detection/core/preprocessor.py)に3行だけ追加して、Random Erasingっぽくしてみます。

　実は、論文のRandom Erasingの実装は、ピクセルノイズの位置やサイズもランダムに変えていますが、Object Detection APIで手軽に実現することが自分には難しかったので、あくまでっぽいものとなります。ご了承下さい。

　変更内容は、preprocessor.pyのrandom_black_patches関数に以下3行を追加します。

```python
diff --git a/research/object_detection/core/preprocessor.py b/research/object_detection/core/preprocessor.py
index c89a228c..571182fa 100644
--- a/research/object_detection/core/preprocessor.py
+++ b/research/object_detection/core/preprocessor.py
@@ -2267,6 +2267,11 @@ def random_black_patches(image,
     mask = 1.0 - tf.image.pad_to_bounding_box(black_box, y_min, x_min,
                                               image_height, image_width)
     image = tf.multiply(image, mask)
+    erase_area = tf.random.uniform([box_size, box_size, 3], 0, 255, tf.float32)
+    erase_area = tf.image.pad_to_bounding_box(erase_area, y_min, x_min,
+                                              image_height, image_width)
+    image = tf.add(image, erase_area)
+
     return image

   with tf.name_scope('RandomBlackPatchInImage', values=[image]):
```

　これを用いた、画像処理の結果は以下のようになります。

　![random_erasing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/6a6eeecb-33cc-5631-c72b-1e34bc2a5b5c.png)

　ランダムに位置やサイズを変える代わりに、ノイズの最大数を増やして`size_to_image_ratio`を0.1から0.2に変更して、少しノイズのボックスサイズを大きめにしています。

　効果に関しては、検証はしておりません。悪しからず（検証できたら追記します）。


# 参考リンク
- https://github.com/uranusx86/Random-Erasing-tensorflow

# 関連記事
[TensorFlowの「Object Detection API」で物体検出の自前データを学習する方法](https://qiita.com/karaage0703/items/76ef6b774e3cd69028bb)

[PyTorchでデータ水増し（Data Augmentation）する方法](https://qiita.com/karaage0703/items/9b56a68a5dba4ad330d9)