
リアルタイム映像から特定の人物検出
こんにちは。
AI coordinatorの清水秀樹です。
以前からやってみたかった映像からの特定人物検出にチャレンジしてみたので、その内容の紹介です。
SSD_Kerasで試してみたかったのですが、こちらで物体検出をやるためには、それを実装するための学習モデル作成が大変だということが判明。
別の方法を模索していたところ、手軽に映像からの人物検出?を実装している記事を見つけたので、ほぼロジック丸パクリで実装してみました。
学習モデルさえ作ってしまえば手軽に映像からの特定人物検出ができるようになりますで、興味がある方は当記事を参考に挑戦してみてください。
参考にさせて頂いたサイト
以下のサイトを参考にさせて頂きました。
Raspberry Pi 深層学習でリアルタイム顔認識(Keras・Open CV)
いつも筆者はこちらの方の記事を参考にさせて頂いております。
貴重な技術の公開ありがとうございます。
また、もしこれからDeep Learningの勉強をするなら、こちらで紹介する書籍も参考になりますので一読してみることをオススメします。
テスト環境
macOS Sierra
Anaconda3-4.2.0-MacOSX-x86_64
python 3.5.2
opencv3 3.1.0
tensorflow-0.12.1
keras 1.2.2
学習モデルの作成
今回も美人女優さん達に登場していただきました。





顔画像の準備については、「大量の画像から顔の部分のみトリミングして保存する方法」を参考にしてください。
顔画像が準備できたら、画像データを数値データにするnpyファイルを作成しましょう。
npyファイルの作成方法については、「ディープラーニングで美人女優の顔認識に挑戦」の記事の最初のソースコードを参考にしてください。
一点注意点として、image_size = 32 で作成してください。
npyファイルが作成できたら、学習モデルの作成です。
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
import numpy as np
root_dir = "./photo_out/"
categories = ["aya ueto", "ayame gouriki", "mayu watanabe", "nozomi sasaki","yui aragaki"]
nb_classes = len(categories)
image_size = 32
def main():
X_train, X_test, y_train, y_test = np.load("作成したnpyファイルのパスを指定してください")
X_train = X_train.astype("float") / 256
X_test = X_test.astype("float") / 256
y_train = np_utils.to_categorical(y_train, nb_classes)
y_test = np_utils.to_categorical(y_test, nb_classes)
model = model_train(X_train, y_train)
model_eval(model, X_test, y_test)
def build_model(in_shape):
model = Sequential()
model.add(Convolution2D(32, 3, 3,
border_mode='same',
input_shape=in_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Convolution2D(64, 3, 3, border_mode='same'))
model.add(Activation('relu'))
model.add(Convolution2D(64, 3, 3))
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(nb_classes))
model.add(Activation('softmax'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
return model
def model_train(X, y):
model = build_model(X.shape[1:])
history = model.fit(X, y, batch_size=32, nb_epoch=10, validation_split=0.1)
hdf5_file = "./idol_makedata/idol-model.h5"
model.save_weights(hdf5_file)
return model
def model_eval(model, X, y):
score = model.evaluate(X, y)
print('loss=', score[0])
print('accuracy=', score[1])
if __name__ == "__main__":
main()
epoch=10で学習しました。
結果はというと、
Train on 6732 samples, validate on 748 samples
Epoch 1/10
6732/6732 [==============================] - 23s - loss: 0.3369 - acc: 0.8598 - val_loss: 0.2699 - val_acc: 0.8877
Epoch 2/10
6732/6732 [==============================] - 20s - loss: 0.1994 - acc: 0.9169 - val_loss: 0.1796 - val_acc: 0.9337
Epoch 3/10
6732/6732 [==============================] - 23s - loss: 0.1331 - acc: 0.9482 - val_loss: 0.1682 - val_acc: 0.9294
Epoch 4/10
6732/6732 [==============================] - 24s - loss: 0.0874 - acc: 0.9667 - val_loss: 0.1414 - val_acc: 0.9449
Epoch 5/10
6732/6732 [==============================] - 23s - loss: 0.0630 - acc: 0.9764 - val_loss: 0.2256 - val_acc: 0.9168
Epoch 6/10
6732/6732 [==============================] - 23s - loss: 0.0532 - acc: 0.9805 - val_loss: 0.1453 - val_acc: 0.9537
Epoch 7/10
6732/6732 [==============================] - 22s - loss: 0.0405 - acc: 0.9861 - val_loss: 0.2356 - val_acc: 0.9366
Epoch 8/10
6732/6732 [==============================] - 22s - loss: 0.0363 - acc: 0.9868 - val_loss: 0.1890 - val_acc: 0.9401
Epoch 9/10
6732/6732 [==============================] - 24s - loss: 0.0279 - acc: 0.9898 - val_loss: 0.1861 - val_acc: 0.9535
Epoch 10/10
6732/6732 [==============================] - 23s - loss: 0.0252 - acc: 0.9922 - val_loss: 0.1890 - val_acc: 0.9428
288/294 [============================>.] - ETA: 0sloss= 0.489020828487
accuracy= 0.9136054528
良いんだが悪いんだが分かりませんが、とりあえず学習モデルが出来上がれば、とりあえず良しとします。
学習モデルが出来上がったら早速映像からの人物検出を試してみましょう。
import face_keras as face
import sys, os
from keras.preprocessing.image import load_img, img_to_array
import numpy as np
import cv2
import time
cascade_path = "./haarcascades/haarcascade_frontalface_alt.xml"
cascade = cv2.CascadeClassifier(cascade_path)
cam = cv2.VideoCapture('6.mp4')
color = (255, 0, 255)
image_size = 32
categories = ["aya ueto", "ayame gouriki", "mayu watanabe", "nozomi sasaki","yui aragaki"]
def main():
while(True):
ret, frame = cam.read()
facerect = cascade.detectMultiScale(frame, scaleFactor=1.3, minNeighbors=2, minSize=(10, 10))
for rect in facerect:
cv2.rectangle(frame, tuple(rect[0:2]),tuple(rect[0:2] + rect[2:4]), color, thickness=2)
x = rect[0]
y = rect[1]
width = rect[2]
height = rect[3]
cv2.imwrite("frontalface.png", frame)
img = cv2.imread("frontalface.png")
dst = img[y:y+height, x:x+width]
cv2.imwrite("output.png", dst)
cv2.imread("output.png")
X = []
img = load_img("./output.png", target_size=(image_size,image_size))
in_data = img_to_array(img)
X.append(in_data)
X = np.array(X)
X = X.astype("float") / 256
model = face.build_model(X.shape[1:])
model.load_weights("./idol_makedata/idol-model.h5")
pre = model.predict(X)
print(pre)
if pre[0][0] > 0.95:
print(categories[0])
text = categories[0]
font = cv2.FONT_HERSHEY_PLAIN
cv2.putText(frame,text,(rect[0],rect[1]-10),font, 2, color, 2, cv2.LINE_AA)
elif pre[0][1] > 0.95:
print(categories[1])
text = categories[1]
font = cv2.FONT_HERSHEY_PLAIN
cv2.putText(frame,text,(rect[0],rect[1]-10),font, 2, color, 2, cv2.LINE_AA)
elif pre[0][2] > 0.95:
print(categories[2])
text = categories[2]
font = cv2.FONT_HERSHEY_PLAIN
cv2.putText(frame,text,(rect[0],rect[1]-10),font, 2, color, 2, cv2.LINE_AA)
elif pre[0][3] > 0.95:
print(categories[3])
text = categories[3]
font = cv2.FONT_HERSHEY_PLAIN
cv2.putText(frame,text,(rect[0],rect[1]-10),font, 2, color, 2, cv2.LINE_AA)
elif pre[0][4] > 0.95:
print(categories[4])
text = categories[4]
font = cv2.FONT_HERSHEY_PLAIN
cv2.putText(frame,text,(rect[0],rect[1]-10),font, 2, color, 2, cv2.LINE_AA)
cv2.imshow("Show FLAME Image", frame)
#time.sleep(0.1)
k = cv2.waitKey(1)
if k == ord('q'):
break
cam.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
ソースコードはほぼ丸パクリです。
気になる実行結果はというと、

上戸彩さんをしっかり検出してくれています。
斎藤工さんは顔検出のみでラベルが出ていないので、うまく学習できているようです。
というのは嘘で、結構な頻度で誤検知します。

学習モデルの精度が低いようです。
この辺は今後の課題ですね。
ただ、目的としたリアルタイムからの特定人物検出ができました。
今後はSSD_Kerasが使える学習モデルでの人物検出にチャレンジしてみたいと思います。
それではまた。
コメントはまだありません。