画像判定
今回は、画像判定のプログラムを作っていきます。
以前に、"tiger","snake","monkey"の3つの画像を保存しましたが、今回作る画像判定は、ある画像を渡したときに、この3つのうちどれに該当するかというものです。
以下がどの画像かを推定するためのプログラムです。
from keras.models import Sequential,load_model
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.utils import np_utils
from PIL import Image
import keras
import numpy as np
import os,sys
image_path = "./image"
classes = os.listdir(image_path)
num_classes = len(classes)
image_size = 50
def build_model():
model = load_model('./image_cnn.h5')
return model
def main():
image = Image.open(sys.argv[1])
image = image.convert('RGB')
image = image.resize((image_size,image_size))
data = np.asarray(image)
X = []
X.append(data)
X = np.array(X)
model = build_model()
result = model.predict([X])[0]
predicted = result.argmax()
percentage = int(result[predicted] * 100)
print("{0}({1}%)".format(classes[predicted],percentage))
if __name__ == "__main__":
main()
このプログラムの引数に画像判定したいファイルをおき実行します。
今回は、画像収集に使用した"tiger"の画像の1つを名前を変更し使用しました。この判定に使う画像は、predict.pyと同じディレクトリに置いておきます。
"python predict.py tiger.jpg"と実行した結果が以下のようになります。

実行結果で、tiger(100%)と出力されていますね。これは訓練で使用している画像データなのでちゃんと画像判定ができていますが、使用する画像に、その動物以外のものや、背景が大きく写っているものは、画像判定がきちんとできない場合があります。
これを改善していくには、画像の中の領域を検知したり、そもそも訓練用の画像データに適切でないものを取り除いたりと改善の余地は多くあります。
まず画像のデータ量が少ないと思われますが、質の良い画像はそんなに多く転がっていないので、その画像を回転させて使いまわしていきます。画像を少し回転させた画像は別データとして扱われるので、1枚の画像を±20~0度の範囲で、1枚の画像を5枚分としたものと左右反転させたものを加えて増量していきます。以下が改善したプログラムです。
from PIL import Image
import os,glob
import numpy as np
from sklearn import model_selection
image_path = "./image"
classes = os.listdir(image_path)
num_classes = len(classes)
image_size = 50
num_testdata = 150
X_train = []
Y_train = []
X_test = []
Y_test = []
for index,classlabel in enumerate(classes):
photos_dir = "./image/" + classlabel
files = glob.glob(photos_dir + "/*.jpg")
for i,file in enumerate(files):
if i > 300: break
image = Image.open(file)
image = image.convert("RGB")
image = image.resize((image_size, image_size))
data = np.asarray(image)
if i < num_testdata:
X_test.append(data)
Y_test.append(index)
else:
for angle in range(-20,20,5):
img_r = image.rotate(angle)
data = np.asarray(img_r)
X_train.append(data)
Y_train.append(index)
img_trans = image.transpose(Image.FLIP_LEFT_RIGHT)
data = np.asarray(img_trans)
X_train.append(data)
Y_train.append(index)
X_train = np.array(X_train)
y_train = np.array(Y_train)
X_test = np.array(X_test)
y_test = np.array(Y_test)
xy = (X_train, X_test, y_train, y_test)
np.save("./image_data_aug.npy", xy)
これで、新しいNPYデータを保存するので、"image_data_aug.npy"として名前を変更しています。また、"image_cnn.py"の中で、"image_data.npy"となっている部分を"image_data_aug.npy"に変更します。また同じように、"image_cnn.h5"となっている部分を"image_cnn.h5"と変更します。
これで、"python image_cnn.py"と実行したところ、以下のようになりました。訓練用データ、テスト用データは微量ですがaccuracyは増加しました。

他にも先ほど述べたように改善する余地としては、
- 画像の選定
- image_cnn.pyで"model.fit(X, y, batch_size=32, epochs=100)"ここのbatch_sizeやepochsの値を大きくする。
実際に、上の画像が、epochs=200としたもの、下の画像が、batch_size=128としたものです。どちらもテスト用データのAccuracyが増加しています。


画像判定のプログラムの紹介は以上になります。