リアルタイム映像から特定の人物検出
こんにちは。
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が使える学習モデルでの人物検出にチャレンジしてみたいと思います。
その他の物体検出記事はこちらから
それではまた。
この記事へのコメントはありません。