プログラミング備忘録

初級プログラマ。python、DL勉強中

kerasでCNNを使ってサッカー選手の顔画像を分類してみた

以前にディープラーニングを使ってりんごとみかんの分類を行った
pythonでkerasを使った全結合での画像分類 - ヘビ夫のプログラミング備忘録


少し発展させて、サッカー選手の顔画像を分類してみることとした

参考

ディープラーニングでザッカーバーグの顔を識別するAIを作る①(学習データ準備編)

今回の取り組み

今回対象としたのは、南米出身のスター選手4名

画像 名前 ナショナルチーム
f:id:programdl:20171126182925j:plain:w80 メッシ アルゼンチン
f:id:programdl:20171126182959j:plain:w100 ハメス・ロドリゲス コロンビア
f:id:programdl:20171126183101j:plain:w100 ネイマール ブラジル
f:id:programdl:20171126183201j:plain:w80 スアレス ウルグアイ


事前準備

各サッカー選手の画像を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 配下

f:id:programdl:20171126184700p:plain

ソースコード

りんごとみかんの分類には、全結合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

もう少し教師データを増やして対応する予定