kerasでCNNを使ってサッカー選手の顔画像を分類してみた
以前にディープラーニングを使ってりんごとみかんの分類を行った
pythonでkerasを使った全結合での画像分類 - ヘビ夫のプログラミング備忘録
少し発展させて、サッカー選手の顔画像を分類してみることとした
参考
ディープラーニングでザッカーバーグの顔を識別するAIを作る①(学習データ準備編)
今回の取り組み
今回対象としたのは、南米出身のスター選手4名
画像 | 名前 | ナショナルチーム |
---|---|---|
メッシ | アルゼンチン | |
ハメス・ロドリゲス | コロンビア | |
ネイマール | ブラジル | |
スアレス | ウルグアイ |
事前準備
各サッカー選手の画像をbingAPIを使用して収集する
bing image search APIを使ってみた - ヘビ夫のプログラミング備忘録
画像の収集が終わったら、OpenCVを使って顔のみを抽出する
pythonでOpenCVを使った顔検出 - ヘビ夫のプログラミング備忘録
検出した顔画像は、以下のようなディレクトリ構成で格納しておく
trainには各選手最低50枚の画像を格納した
train --00_messi 01_james 02_neymar 03_suarez test --00_messi 01_james 02_neymar 03_suarez
例 00_messi 配下
ソースコード
りんごとみかんの分類には、全結合NNを使用したが、
本ケースでも同様に試してみたところ、全くと行っていいほど効果がなかった
そこで今回は画像認識で定番のCNNを使用して分類を行った
from keras.models import Sequential from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D from keras.utils.np_utils import to_categorical from keras.optimizers import Adam import numpy as np from PIL import Image import os #定数 imgxsize=25 imgysize=25 epoch=2000 label_dict={"00_messi":0,"01_james":1,"02_neymar":2,"03_suarez":3} label_mean_dict={0:"Argentina",1:"columbia",2:"brazil",3:"uruguay"} # 教師データ読み込み label_list = [] image_list = [] image_list_array = [] for dataset_name in sorted(os.listdir("./train")): try: label=label_dict[dataset_name] except: print("label not defined:"+dataset_name) continue dataset_path = "./train/" + dataset_name for file_name in sorted(os.listdir(dataset_path)): label_list.append(label) file_path = dataset_path + "/" + file_name image = np.array(Image.open(file_path).resize((imgxsize, imgysize))) print(file_path) # 0〜1の範囲に変換 image_list.append(image / 255.) # numpy変換 X = np.array(image_list) # labelを配列に変換 Y = to_categorical(label_list) # モデル定義 model = Sequential() model.add(Conv2D(32, (3, 3), padding='same',input_shape=X.shape[1:])) model.add(Activation('relu')) model.add(Conv2D(32, (3, 3))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Conv2D(64, (3, 3), padding='same')) model.add(Activation('relu')) model.add(Conv2D(64, (3, 3))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(512)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(len(label_dict))) model.add(Activation('softmax')) model.compile(loss="categorical_crossentropy", optimizer=Adam(lr=0.001), metrics=["accuracy"]) model.summary() # 学習 model.fit(X, Y, nb_epoch=epoch, batch_size=100, validation_split=0.1) # 推論 total = 0. ok_count = 0. for testset_name in sorted(os.listdir("./test")): testset_path = "./test/" + testset_name try: label=label_dict[testset_name] except: print("label not defined:"+testset_name) continue for file_name in sorted(os.listdir(testset_path)): label_list.append(label) file_path = testset_path + "/" + file_name image = np.array(Image.open(file_path).resize((imgxsize, imgysize))) print(" ") print(file_path) result = model.predict_classes(np.array([image / 255.])) print("correct_label:", label_mean_dict[label], " result_label:", label_mean_dict[result[0]]) total += 1. if label == result[0]: ok_count += 1. print("accuracy: ", ok_count / total * 100, "%")
結果
accuracy: 85.32608695652173 %
分類はできたが、まだ精度があまい様子
詳細を確認すると、ネイマールの認識が結構間違っている
./test/01_james/288.jpg 1/1 [==============================] - 0s correct_label: columbia result_label: columbia ./test/01_james/289.jpg 1/1 [==============================] - 0s correct_label: columbia result_label: columbia ./test/02_neymar/063.jpg 1/1 [==============================] - 0s correct_label: brazil result_label: Argentina ./test/02_neymar/064.jpg 1/1 [==============================] - 0s correct_label: brazil result_label: columbia ./test/02_neymar/067.jpg 1/1 [==============================] - 0s correct_label: brazil result_label: brazil
もう少し教師データを増やして対応する予定