ビジネスパーソン・ガジェット置場 empty lot for business

営業や仕事、それに伴う生活を便利に楽にするツール、ガジェットを作ります。既にあるツールも自分用にカスタマイズ。

openCV: 画像の水増し

ディープラーニングで使用するために画像を水増しします。何度か画像をディープラーニングの学習器にかけているのですが、やはり画像の枚数が少ないと結果が向上しない。また、画像を集めるのにも限界があるので水増しで対応です。

OpenCVのflip、threshold、GaussianBlur

今回も参照させていただいたサイトは下記のサイトさんです。

機械学習で乃木坂46を顏分類してみた | Aidemy | 10秒で始めるAIプログラミング学習サービスAidemy[アイデミー]

 

 

今回使った水増しの方法

 flip

  • 手法・・・反転
  • 引数・・・(元の配列, 反転方向を示す値) 
  • 備考・・・0:上下反転, >0:左右反転, <0:上下左右反転 

threshold

  • 手法・・・閾値処理
  • 引数・・・(元の配列, 閾値, 閾値を超えた場合に変更する値, 二値化の方法)  
  • 備考・・・thresholdは閾値と二値化された画像を返す  

GaussianBlur

  • 手法・・・ぼかし
  • 引数・・・(元の配列, カーネルサイズ, G分ンプのσ)  

flipはホクロの位置とか変わってしまうから迷ったのですが実装しました。

 

コード

パス以外は参照サイトさんのそのままです。(インデントが見えなかったのでインデントはこちらで入れています)

import os
import numpy as np
import matplotlib.pyplot as plt
import cv2

# 水増し用の関数(手法は3種類で初期値でTrue, 引数imgに水増しする画像ファイルパス)
def scratch_image(img, flip=True, thr=True, filt=True):
    
    methods = [flip, thr, filt]
    # ぼかしに使うフィルター
    filter1 = np.ones((3, 3))
    # 元画像データを配列に格納
    images = [img]
    # 手法に用いる関数
    scratch = np.array([
        lambda x: cv2.flip(x, 1),
        # thresholdは閾値と二値化された画像を返すため[1]で画像の方を受け取る
        lambda x: cv2.threshold(x, 100, 255, cv2.THRESH_TOZERO)[1],
        lambda x: cv2.GaussianBlur(x, (5, 5), 0)
    ])
    doubling_images = lambda f, imag: np.r_[imag, [f(i) for i in imag]]
    
    for func in scratch[methods]:
        images = doubling_images(func, images)
    return images

d_name = ['イソ', 'ウォニョン', 'ガウル', 'ユジン', 'リズ', 'レイ']
for name in d_name:
    # パスをfilesに格納
    files = glob.glob(f'face_image/train/{name}/*')
    # ファイル名をimg_filename_listに格納
    img_filename_list = os.listdir(f'face_image/train/{name}')
    
    for i in range(len(files)):
        img = cv2.imread(files[i])
        scratch_face_images = scratch_image(img)
        for idx, val in enumerate(scratch_face_images):
            fn, ext = os.path.splitext(img_filename_list[i])
            file_name = os.path.join(f'face_scratch_image/{name}', fn+'_'+str(idx)+'.png')
            cv2.imwrite(file_name, val) 
            

このコードで300枚程度だった画像が2550枚になりました。ディープラーニングの学習器に通すのが楽しみですね!

 

numpyのr_やc_

scratch_image関数内にあるnp.r_は、np.c_と同様に配列を結合するオブジェクトです。r_は縦方向に配列を結合し、c_は横方向に配列を結合します。

 

- 配列と数値を混在させて結合できる
- スライスでステップ数やか分割数を指定して数列をつくれる
- vstack()やhstack()の代わりに使える