【Keras】ImageDataGeneratorで画像の水増しをしてみた

こんにちは。のっくん(@yamagablog)です。

ディープラーニングでは、そもそも学習する画像の枚数が少なかったりします。

そんな時はデータ拡張(data augmentation)と呼ばれる方法でデータを水増しします。

簡単に言うと、横にずらしたり、縦にずらしたり、回転させたりして、類似画像をたくさん作ることです。

kerasのImageDataGeneratorを使うとデータ拡張が容易にできます。コードを書いて試してみました。

 

書いてみたコード

 

まずはコード全体から。

import PIL
from keras.preprocessing.image import load_img,img_to_array,ImageDataGenerator,array_to_img
import numpy as np
import os
import matplotlib.pyplot as plt
%matplotlib inline

IMAGE_FILE = "/home/matsu/kaggle_original_data/dog.0.jpg"

# 画像をロード(PIL形式画像)
img = load_img(IMAGE_FILE)

#貼り付け
plt.imshow(img)

#表示
plt.show()

# numpyの配列に変換
x = img_to_array(img)

# 4次元配列に変換、以下同じ意味
# x = np.expand_dims(x, axis=0)
x = x.reshape((1,) + x.shape)

#(1,縦サイズ, 横サイズ, チャンネル数)
print(x.shape)

# -90 - 90の範囲でランダムに回転
datagen = ImageDataGenerator(rotation_range=90)

# generatorから9個の画像を生成
# 今回は1枚のみなのでbatch_sizeは1
g = datagen.flow(x, batch_size=1)
for i in range(4):
    batches = g.next()
    
    #(1,縦サイズ, 横サイズ, チャンネル数)
    print(batches.shape)
    
    # 画像として表示するため、4次元から3次元データにし、配列から画像にする。
    gen_img = array_to_img(batches[0])

    plt.subplot(2, 2, i + 1)
    plt.imshow(gen_img)
    plt.axis('off')

plt.show()

コードの解説

Jupyterでコードを書いていきます。

主な流れは以下の通り。

  1. 画像を読み込んで表示する
  2. 画像から配列に変換する
  3. ImageDataGeneratorを使って、画像を水増しする
  4. 水増しした画像を表示する

まずは順番に見ていきましょう。

画像を読み込んで表示する

画像を読み込むには、kerasのload_imgと言う関数を使います。ロードした画像をjupyter上に表示するには、`matplotlib`を使用します。

import PIL
from keras.preprocessing.image import load_img,img_to_array,ImageDataGenerator,array_to_img
import numpy as np
import os
import matplotlib.pyplot as plt
%matplotlib inline

IMAGE_FILE = "/home/matsu/kaggle_original_data/dog.0.jpg"

# 画像をロード(PIL形式画像)
img = load_img(IMAGE_FILE)

#貼り付け
plt.imshow(img)

#表示
plt.show()

 

画像から配列に変換する

なんで画像から配列に変換する必要があるの?って思う人がいるかもしれません。

水増しに使うImageDataGeneratorのflow関数をみてみましょう。

kerasのドキュメントです。

flow

flow(x, y=None, batch_size=32, shuffle=True, seed=None, save_to_dir=None, save_prefix='', save_format='png', subset=None)

numpyデータとラベルの配列を受け取り,拡張/正規化したデータのバッチを生成します.

引数

  • x: データ.4次元データである必要があります.グレースケールデータではチャネルを1に,RGBデータではチャネルを3にしてください.
  • y: ラベル.
  • batch_size: 整数(デフォルト: 32).
  • shuffle: 真理値(デフォルト: True).
  • seed: 整数(デフォルト: None).
  • save_to_dir: Noneまたは文字列(デフォルト: None).生成された拡張画像を保存するディレクトリを指定できます(行ったことの可視化に有用です).
  • save_prefix: 文字列(デフォルト'').画像を保存する際にファイル名に付けるプリフィックス(set_to_dirに引数が与えられた時のみ有効).
  • save_format: “png”または”jpeg”(set_to_dirに引数が与えられた時のみ有効).デフォルトは”png”.

戻り値

xが画像データのNumpy配列でyがそれに対応したラベルのNumpy配列である(x, y)から生成されるイテレータです.

https://keras.io/ja/preprocessing/image/#flow

 

デフォルト引数と言って、引数=”◯”となっている引数はデフォルト値が入っているので指定しなくても構いません。

ここで指定する必要があるのは、最初の引数xです。

引数xは、numpyの4次元データにしないといけないって書かれています。つまり、

  • 画像からnumpyの配列にする必要がある
  • 3次元から4次元にする必要がある

ってことがわかります。

3次元の画像データから4次元にする上で追加するデータはバッチサイズです。バッチサイズと言うのは画像枚数です

1枚ずつやっていると時間がかかってしまうので、まとめて処理します。

まとめて処理する単位のことをバッチと呼んでいます。今回は1枚の画像しかないので、バッチサイズは1です。

(横サイズ、縦サイズ、チャンネル数)を(1、横サイズ、縦サイズ、チャンネル数)に変換すれば良いですね。

kerasには、画像とnumpyの配列を変換する関数`img_to_array`が用意されていますのでそれで変換してみましょう。

# numpyの配列に変換
x = img_to_array(img)

3次元から4次元に変換するのには、二種類の方法があります。

  • numpyの次元を増やす関数expand_dimsを使う
  • reshapeを使って次元を増やす。

以下のコードでは直感的にわかりやすいreshapeを使ってみます。

# 4次元配列に変換、以下同じ意味
# x = np.expand_dims(x, axis=0)
x = x.reshape((1,) + x.shape)

#(1,縦サイズ, 横サイズ, チャンネル数)
print(x.shape)

画像を水増しする

プラスマイナス90度の範囲で画像を回転させてみます。ImageDataGeneratorの引数を以下のように指定します。

# -90 - 90の範囲でランダムに回転
datagen = ImageDataGenerator(rotation_range=90)

# generatorから9個の画像を生成
# 今回は1枚のみなのでbatch_sizeは1
g = datagen.flow(x, batch_size=1)

水増ししたデータを表示する

水増ししたデータを4枚表示してみましょう。

ジェネレータでは、画像が無限に生成されるので、for文の繰り返し回数を制限することで、生成する枚数を制限できます。

for i in range(4):
    batches = g.next()
    
    #(1,縦サイズ, 横サイズ, チャンネル数)
    print(batches.shape)
    
    # 画像として表示するため、4次元から3次元データにし、配列から画像にする。
    gen_img = array_to_img(batches[0])

    plt.subplot(2, 2, i + 1)
    plt.imshow(gen_img)
    plt.axis('off')

plt.show()

 

 

横に平行移動

パラメータを変えて他の水増し方法を試してみます。

# 横サイズ×0.2の範囲で移動する
datagen = ImageDataGenerator(width_shift_range=0.2)

 

拡大・縮小する

datagen = ImageDataGenerator(zoom_range=0.5)

 

上下反転

datagen = ImageDataGenerator(vertical_flip=True)

 

最後に

画像処理というとopencvのイメージですが、kerasでも手軽に画像変換ができます。

kerasは画像処理やディープラーニングがシンプルに書ける本当に素晴らしいフレームワークだと思います。

Udemy

Udemyの無料講座でディープラーニングについて説明していますのでよろしければどうぞ。

https://www.udemy.com/course/deeplearning-practice-dogcat/learn/lecture/29144680#overview

参考

pynote : http://pynote.hatenablog.com/entry/keras-image-data-generator