Keras+TensorFlowで実践CNN(その1)
被写体が何なのかを識別する
今回は、Keras+TensorFlowを使用して、画像の被写体が何なのかを識別する実験を行います。
これまで、MNISTの手書き文字を分類で解いてきましたが、今回は、畳み込みニューラルネットワーク(Convolution Neuron Network:CNN)を使って、画像に映っているものが何なのかを識別していきます。
CNNは、画像認識に強力なニューラルネットワークです。画像認識では、通常、リッジを強調したり画像をぼやかしたりして行われます。この処理をニューラルネットワーク内部で行うのがCNNです。
CNNは、「入力層」と「出力層」の間に隠れ層として「畳み込み層」「プーリング層」及び「全結合層」が挟まったモデル構造になっています。この隠れ層を深くすることによって、画像の判別精度が向上するといわれています。
画像の前処理
CNNによるディープラーニングを効率的に処理させるためには、学習や検証に使用する画像データのピクセル数を全て同一にする必要があります。そこで今回は、PythonモジュールのPillowを使用して、画像データを加工していきます。
カリフォルニア工科大学が公開しているcaltec 101 サンプル画像データを使用して、CNNに入力する画像データを作成していきます。
from sklearn.model_selection import train_test_split
from PIL import Image
import os, glob
import numpy as np
def convert_image(conv_type, name):
if conv_type is not 'L' and conv_type is not 'RGB':
print(conv_type + "==>入力された画像変換タイプはありません")
return
#読み込み対象ディレクトリの設定
sample_dir = "./images/101_ObjectCategories"
categories = ["panda","wild_cat","rhino","elephant","flamingo","platypus",
"okapi","llama","kangaroo","hedgehog","emu","beaver"]
#カテゴリ数(12種類)と縦横のリサイズするピクセル数の設定
num_class = len(categories)
img_width = 64
img_height = 64
#画像データとラベルを格納するリストの初期化
X = []
Y = []
#画像変換処理
for idx, cat in enumerate(categories):
label = [0 for i in range(num_class)]
label[idx] = 1
image_dir = sample_dir + "/" + cat
files = glob.glob(image_dir + "/*")
for i, fl in enumerate(files):
img = Image.open(fl)
img = img.convert(conv_type)
img = img.resize((img_width,img_height))
if i == 0:
img.save(name + "_" + cat + "_" + os.path.basename(fl))
data = np.asarray(img)
X.append(data)
Y.append(label)
#画像データとラベルを格納したリストをnumpy.ndarrayに変換
X = np.array(X)
Y = np.array(Y)
#学習用データとテスト用データに分割
train_data, test_data, train_label, test_label = \
train_test_split(X, Y, test_size=0.3, shuffle=True)
#分割したデータをタプルで並べてファイルに出力
xy = (train_data, test_data, train_label, test_label)
np.save("./images/wildlife_"+ name + ".npy", xy)
#処理した画像数を出力して終わり
print("Success to convert " + name + " images=,", len(Y))
if __name__ == "__main__":
#グレースケールの画像を作成
convert_image("L", "gray")
#RGB画像の作成
convert_image("RGB", "rgb")
このスクリプトで重要なところは、Pillow(PIL)のImageモジュールを使用してファイル操作を行うところです。
for i, fl in enumerate(files):
img = Image.open(fl)
img = img.convert(conv_type)
img = img.resize((img_width,img_height))
if i == 0:
img.save(name + "_" + cat + "_" + os.path.basename(fl))
data = np.asarray(img)
X.append(data)
Y.append(label)
ファイルを開き、画像変換後に縮小リサイズします。また、各カテゴリの1番目の画像データについては、リサイズ後(64×64ピクセル)の画像を確認用としてファイルに出力させます。
#画像データとラベルを格納したリストをnumpy.ndarrayに変換
X = np.array(X)
Y = np.array(Y)
#学習用データとテスト用データに分割
train_data, test_data, train_label, test_label = \
train_test_split(X, Y, test_size=0.3, shuffle=True)
#分割したデータをタプルで並べてファイルに出力
xy = (train_data, test_data, train_label, test_label)
np.save("./images/wildlife_"+ name + ".npy", xy)
変換処理後のデータを格納したリスト変数XとYをnumpy.ndarrayに変換します。その後、学習用データとテスト用データに分割し、タプルに並べてから変数xyに代入します。最後にnp.save()メソッドで画像データをファイル出力しています。このファイルはバイナリですので、テキストエディタなどで内容を確認することはできません。
変換後の画像を確認する
では、作成したPythonコードを実行して、入力した画像がどんな画像に変換されたのか確認してみましょう。
ヤマネコの元画像はRGB(カラー)の300×256ピクセルの画像です。画像変換後は、64×64ピクセルに変換されていますので、縦横ともに約1/4程度に解像度が荒くなっており、元画像と比べると歪んでいることがわかります。また、被写体もぼやけてしまっています。
次回は、変換した画像を使用して、CNN(畳み込みニューラルネットワーク)による画像識別の実験を行っていきます。