データ拡張

## はじめに
前回の記事で、事前学習モデルについてある程度の動きを確認することができました。これからAIに教師データを学習させて画像認識を体感してみたいと思います。モデルも事前学習モデルではなく、独自でモデルを作成してみたいと思います。
具体的にやりたいことはお酒の画像をAIに学習させて、それがどのジャンルのお酒なのかを判別するプログラムを作りたいと思っています。AIにデータ学習させるため、お酒データ（教師データ）を大量に準備する必要があるのですが、用意できたのは7つのジャンルに分類されたお酒画像が50枚ずつで学習データが全く足りません。
そこでまずはデータ拡張を行い、データを水増ししようと思います。

## データ拡張方法
データ拡張方法としてはいろいろな方法があると思いますが、今回は以下の方法を使います。
* 画像の反転
![1719312498021_trans.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/d51cfaea-9268-55cb-58e4-793954d9067d.jpeg)

* 画像の回転
![1719312498021_rotate1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/2f6b6e58-d717-d8c6-e332-9e3bdc5c9211.jpeg)

* 平行移動
![1719312498021_rotate1_translate1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/77552043-9491-9982-5b63-b2aa0a7cf3af.jpeg)

* グレースケール
![1719312498021_gray1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/11b59da2-2118-9f23-598e-c96801bf29a2.jpeg)

## 実際に使ったコード
VGG16などの事前学習モデルがデフォルトの入力サイズとしているからそれに合わせて、データ拡張での出力サイズは224x224としました。

```python
import glob
import os
from PIL import Image

IMAGE_PATH = '/home/cnysntry/resize/liquor/'
LIQUOR_CLASS = ["beer",
                "bourbon",
                "brandy",
                "japanese_sake",
                "shochu",
                "whisky",
                "wine"]
IMG_WIDTH = 224
IMG_HEIGHT = 224

for base_class in LIQUOR_CLASS:
    search_dir = IMAGE_PATH + base_class + '/*.jpg'
    search_result = glob.glob(search_dir, recursive=True)
    for cur_jpg in search_result:
        basename = os.path.basename(cur_jpg)
        img = Image.open(cur_jpg)
        img_resized = img.resize((IMG_WIDTH, IMG_HEIGHT))
        index = cur_jpg.find(base_class)
        out_dir_name = cur_jpg[0:index+len(base_class)] + '/out/'
        if os.path.isdir(out_dir_name) == False:
            os.mkdir(out_dir_name)
        out_jpg = out_dir_name + basename
        img_resized.save(out_jpg)

        # transpose
        img_trans = img_resized.transpose(Image.FLIP_LEFT_RIGHT)
        index2 = out_jpg.find(".jpg")
        out_trans_jpg = out_jpg[0:index2] + '_trans.jpg'
        img_trans.save(out_trans_jpg)
        
        # rotate
        num = 1
        trans_arrays = [[50, 50], [-50, 50], [-50, -50], [50, -50]]
        for angle in range(-90, 90, 5):
            img_rotate = img_resized.rotate(angle)
            out_rotate_jpg = out_jpg[0:index2] + '_rotate' + str(num) + '.jpg'
            img_rotate.save(out_rotate_jpg)

            # translate
            num2 = 1
            for trans in trans_arrays:
                img_translate = img_rotate.rotate(0, translate=(trans[0], trans[1]))
                index3 = out_rotate_jpg.find(".jpg")
                out_translate_jpg = out_rotate_jpg[0:index3] + '_translate' + str(num2) + '.jpg'
                img_translate.save(out_translate_jpg)
                num2 += 1

            # grayscale
            img_gray = img_rotate.convert("L")
            out_gray_jpg = out_jpg[0:index2] + '_gray' + str(num) + '.jpg'
            img_gray.save(out_gray_jpg)
                
            num += 1
```

## あとがき
これによりデータ拡張前は、7×50=350枚の画像データしかありませんでしたが、データ拡張後は、7×10900=76300枚となりました。これでも教師データとしては少ないんですけどね。
ちなみにデータ学習をRaspberry Pi 4で動かしていたので以下の通り、これだけのデータを作成するだけでもかなりの時間がかかってしまいました。
```
$ time python3 jpg_resize.py
real    2m59.290s
user    2m1.422s
sys     0m19.072s
```