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(畳み込みニューラルネットワーク)による画像識別の実験を行っていきます。