はじめに
前回の記事で少ない画像データを回転や平行移動などを行い、増やす手段について記載したが、これをそのままディープラーニングの教師データとして使うことができないことが発覚した。
今回は備忘録として何に躓き、どうやって解決したかについて記載する。
問題点
前回は教師データとして以下のデータ拡張方法を採用した。
- 画像の反転
- 画像の回転
- 平行移動
- グレースケール
データ拡張後のデータには、RGBの24ビットデータとグレースケールの8ビットデータが混在した状態になってしまいました。KerasのConv2DやInputオブジェクトでは入力画像のshape(縦, 横, チャンネル数)を指定してモデルを作成しますが、チャンネル数が混在した教師データを使うと学習中にエラー終了してしまいます。
また、データ拡張を行うために使用した入力画像データは、画像サイズがバラバラで混在していてこれらの画像データも教師データに紛れていました。
解決策
データ拡張を行うpythonスクリプトに以下の修正を行いました。
- グレースケール変換を削除
- データ拡張後、入力に使った画像データを削除
- データ拡張の出力ディレクトリoutからラベルとして使うディレクトリ配下に移動し、outディレクトリは削除
以下は使用したpythonスクリプトです。
import glob
import os
import shutil
from PIL import Image
IMAGE_PATH = '/home/cnysntry/resize/liquor/'
LIQUOR_CLASS = ["beer",
"bourbon",
"brandy",
"japanese_sake",
"shochu",
"whisky",
"wine"]
IMG_WIDTH = 64
IMG_HEIGHT = 64
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 = [[10, 10], [-10, 10], [-10, -10], [10, -10]]
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
num += 1
os.remove(cur_jpg)
postdir = IMAGE_PATH + base_class
search_dir2 = postdir + '/out/*.jpg'
for search_result2 in glob.glob(search_dir2, recursive=True):
shutil.move(search_result2, postdir)
os.rmdir(postdir + '/out')
他の前回との変化点
- 学習時間を短縮するため、入力画像サイズを64x64に設定
- 入力画像サイズを小さくしたため、平行移動の距離を小さくした
終わりに
上記のスクリプトを使ってデータ拡張した結果、ディープラーニングにより学習することができました。