2018年5月20日日曜日

【Python x OpenCV】道路標識のデータセットを拡張

AI(機械学習, 深層学習, ディープラーニング, ニューラルネットワーク)を使って道路標識を分類したい時に使うデータ拡張の備忘録。

データセット拡張 (data augmentation)


ニューラルネットワークで必要になるトレーニング用のデータセット。

German Traffic Sign Datasetの様に枚数があれば良いのですが、
現実には整備済みデータセットはまだまだ少ないというのが現状です。。

そこで必要になるのがデータの水増し。
人工的にデータ増やしてしまおう作戦です。既に


など分かりやすい解説はあるので、

  1. 左右反転
  2. 明るさチェンジ
  3. 上下左右にシフト

の3つのopencvバージョンでも紹介します。
コードはこちらからどうぞ。

1. 左右反転


opencvでの左右反転は
flipped = cv2.flip(img,1)
の一行でおしまいです。1は反転方向を左右に指定してるだけです。ちょろい。

2. 明るさチェンジ


def change_brightness(image):
    image1 = cv2.cvtColor(image,cv2.COLOR_RGB2HSV)
    image1 = np.array(image1, dtype = np.float64)
    # can be changed the brightness at here (currently 2.0)
    random_bright = 2.0 #+np.random.uniform()*.4 
    image1[:,:,2] = image1[:,:,2]*random_bright
    image1[:,:,2][image1[:,:,2]>255]  = 255
    image1 = np.array(image1, dtype = np.uint8)
    image1 = cv2.cvtColor(image1,cv2.COLOR_HSV2RGB)
    return image1

rgb空間だと明るさ変えられないのでhsv空間に変換してからゲインかけてるだけです。
2.0のところを小さくすれば暗くなりますし、ランダムにもできます。ちょろい。

3. 上下左右にシフト


def shift(image,trans_range):
    rows,cols = image.shape[0:2]
    # Translation
    tr_x = trans_range*np.random.uniform()-trans_range/2
    tr_y = trans_range*np.random.uniform()-trans_range/2
    #tr_y = 0
    Trans_M = np.float32([[1,0,tr_x],[0,1,tr_y]])
    image_tr = cv2.warpAffine(image,Trans_M,(cols,rows))
    return image_tr

x, y方向にtrans_rangeに応じたピクセル数だけずらしてるだけです。ちょろい。

ということで、結果はこちら。


関数にしとくとシフトと明るさチェンジの両方適用したりが簡単です。
手前方向に回転(ワープ処理)とかは気が向いたら実装します。

おしまい。