データの水増し(DataAugmentation)をopenCVで

# はじめに
８月に入り激アツな日々皆さんいかがお過ごしですか？</br>
私はいまにも溶けそうな勢いでありますが[米津玄師の新曲](https://youtu.be/XeFQJ6-XoD0)を聞きながら</br>
冷房の効いた昼夜がわからない部屋でコーディングをしてるわけですが</br>

皆さん夏と言ったらなんですか？
- 夏祭り？
- 花火？
- かき氷？

いや夏と言ったら***DataAugmentationの夏ですよ！！！***
ということでopenCVでちゃちゃっとDataAugmentationする方法をメモ代わりに書いときます。

# 誰向けなの
- 大量のデータをディレクトリ構造を維持したままDataAugmentationしたい人！
- とりあえず早くデータを作らないと誰かに怒られる人
- プログラム組むのが面倒な人！
- 以下のコマンドで実行<br>
```
python3 img_change.py input_directory output_directory
```
- 例
```
python3 img_change.py /data/imageset /data/imagser_change
```

# プログラム
```py:img_change.py
# -*- coding: utf-8 -*-
import numpy as np

import os
import cv2
import sys
import pathlib
import glob
from scipy.signal import qspline1d, qspline1d_eval, qspline2d,cspline2d


if len(sys.argv) != 3:
    print("python3 test.py inputdir outputdir")
    sys.exit()
else:   
    input_path = sys.argv[1]
    file_list = glob.glob(input_path + "/**/**.png", recursive=True)
    for item in file_list:
        split_name = item.split('/')
        output_name = sys.argv[2] + "/" + split_name[-3] + "/" + split_name[-2] + "/" + split_name[-1]
        output_dir = sys.argv[2] + "/" + split_name[-3] + "/" + split_name[-2]
        pathlib.Path(output_dir).mkdir(parents=True,exist_ok=True)
        img = cv2.imread(item, cv2.IMREAD_UNCHANGED)  # read image
        
        #画像処理部分
        ###画像の輝度を上げる
        chg_img=img*1.2 #輝度が２倍になる

        
        ###画像のリサイズ
        height = img.shape[0]
        #img.shape[0]*0.5でもとの半分のサイズ
        width = img.shape[1]
        chg_img = cv2.resize(img , (int(width), int(height)))

        ###CLAHE（ヒストグラムができるだけ均等にバラけるように再配分）
        clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
        chg_img = clahe.apply(img)

        ###ノイズ
        row,col,ch = img.shape
        # 白
        pts_x = np.random.randint(0, col-1 , 1000) #0から(col-1)までの乱数を千個作る
        pts_y = np.random.randint(0, row-1 , 1000)
        img[(pts_y,pts_x)] = (255,255,255) #y,xの順番になることに注意

        # 黒
        pts_x = np.random.randint(0, col-1 , 1000)
        pts_y = np.random.randint(0, row-1 , 1000)
        img[(pts_y,pts_x)] = (0,0,0)

        ###画像を歪める
        chg_img = cv2.flip(img, 1) #水平方向に反転
        chg_img = cv2.flip(img, 0) #垂直方向に反転


        cv2.imwrite(output_name,chg_img )  #write image
```
- 上のプログラムでは以下のディレクトリ構造でプログラムを作成している

```sh
$ tree
/data
└── val
    ├── A1
    │   │  
    │   ├── 0.png
    │   ├── 1.png
    │   ├── 2.png
    │   └── ....
    ├── B1
    │   │  
    │   ├── 0.png
    │   ├── 1.png
    │   ├── 2.png
    │   └── ....    
    │            
    train
    ├── A1
    │   │  
    │   ├── 0.png
    │   ├── 1.png
    │   ├── 2.png
    │   └── ....
    ├── B1
    │   │  
    │   ├── 0.png
    │   ├── 1.png
    │   ├── 2.png
    │   └── ....    
    │              
    test
    ├── A1
    │   │  
    │   ├── 0.png
    │   ├── 1.png
    │   ├── 2.png
    │   └── ....
    ├── B1
    │   │  
    │   ├── 0.png
    │   ├── 1.png
    │   ├── 2.png
    │   └── ....    
    │            
    └── 
```
- よって指定したディレクトリの２つ下のディレクトリの.pngをすべてリストとして取得する感じ

# 終わりに
- 　色々画像の変える方法はあるのでOpenCV画像加工とかで調べて見てね
- 　参考サイト[Pythonで画像処理② Data Augmentation (画像の水増し)](https://lp-tech.net/articles/nCvfb?page=1)