映像から顔判定

ゆうき( @BASEBALLY15 )です^^

前回に,畳み込みニューラルネットワークを使って,顔画像から本人か他人かを判定しました.

画像から判定する場合,毎回画像を読み込む必要があり,手間だなと感じていました.

そこで,今回は,映像から,本人か他人かを判定してみました.

AIを使って映像から顔を判定するまでの流れ

1. まずは,本人の顔と他人の顔をカスケードファイルで読み込み,保存します.

2. 保存した顔画像を,学習用とテスト用に分けます.そして,学習用とテスト用に分けたデータを畳み込みニューラルネットワークで学習します.

AIを使って映像から顔を判定してみた!

前回にご紹介した,『顔画像』から本人か他人かを判定する場合は,このように,毎回,画像を読み込ませていました.

顔画像をニューラルネットワークで学習させる
(PowerPointで作成)

これだと,判定したい画像をわざわざ探してきて,本人か他人かを判定する必要があります.

そこで,今回は,このように映像から本人か他人かを判定できるようにしました.

映像から顔を判定
(PowerPointで作成)

これで,毎回画像を探してくる手間が省けます^^

それでは,コードをご紹介します⤵

ライブラリ

#画像を編集するために使う
import cv2

#画像を編集するために使う
from PIL import Image

import numpy as np

import keras

#ニューラルネットワークのモデルを定義するためのライブラリ
from keras.models import Sequential

#畳み込みの処理やプーリングの処理をするためのライブラリ
from keras.layers import Conv2D, MaxPooling2D

#Activationは活性化関数,Dropoutはドロップアウト処理,
#Flattenはデータを1次元に変換,Denseは全結合
from keras.layers import Activation, Dropout, Flatten, Dense

#ファイルをロードするためのライブラリ
from keras.models import load_model

コード

クラスと画像サイズを決めよう!

まずは,クラスを作成し,ニューラルネットワークで読み込むためのサイズを決めます.

##クラスとクラス数と画像のサイズを指定##
#クラスを作成
face_classes = ["my_face", "other_face"]

#クラスの数(=2)
num_face_classes = len(face_classes)

#画像のサイズを指定(映像から画像にする際のサイズ変更)
width = 500

height = 300

#画像のサイズを指定(ニューラルネットワークで学習するため)
image_size = 50

畳み込みニューラルネットワークのモデルを作成しよう!

#ニューラルネットワークのモデルを作成する
def neural_model():
    
    #------------------------------------------------
    
    model = Sequential()

    model.add(Conv2D(32, 
                     kernel_size=(3,3), 
                     padding="same",
                     input_shape=(image_size, image_size, 3)))
    
    #マイナスの値を除去
    model.add(Activation("relu"))

    #------------------------------------------------ 

    model.add(Conv2D(32, 
                     kernel_size=(3,3)))
    
    model.add(Activation("relu"))
    
    model.add(MaxPooling2D(pool_size=(2,2))) 
    
    #過学習の抑制(ランダムでニューロンを無効化)
    #偏ったニューロンに依存しないため
    model.add(Dropout(rate=0.25))#25%無効化
        
    #------------------------------------------------

    model.add(Conv2D(64, 
                     kernel_size=(3,3), 
                     padding="same"))
    
    model.add(Activation("relu"))

    #------------------------------------------------

    model.add(Conv2D(64, 
                     kernel_size=(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(num_face_classes))
    
    model.add(Activation("softmax"))
    
    #------------------------------------------------
    
    #オプティマイザーを作成
    opt = keras.optimizers.RMSprop(learning_rate=0.0001, 
                                   decay=1e-6)
    
    #コンパイル
    model.compile(loss="categorical_crossentropy", 
                  optimizer=opt, 
                  metrics=["accuracy"])
    
    #モデルのロード
    model = load_model("./face_cnn.h5")
    
    return model

(本題)映像から顔を判定しよう!

前回の,画像から顔を判定する方法からの変更点は以下の通りです⤵

  • 前回からの変更点1・・・顔が検出された時と,検出されなかった時で場合分けをする
  • 前回からの変更点2・・・本人の顔の時は『青色の枠』,他人の顔の時は『赤色の枠』で囲む

(※コード内で,変更点を示しています^^)

def main_predict():
    
    #---------------------------------------------------------------------------
    
    #映像を表示
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
    
    #顔の検出器を作成
    face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml")
    
    #---------------------------------------------------------------------------
    
    while True:
    
        ret, frame = cap.read()
        
        #画像にする際のサイズを変更する
        frame = cv2.resize(frame,(width, height))
        
        #グレイスケールに変換
        frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        
        
        #顔認証を実行
        face_list = face_cascade.detectMultiScale(frame_gray, minNeighbors=20)
        
        #--------------------------------------------------------------------------- 
        #前回からの変更点1-ココから-
        #--------------------------------------------------------------------------- 
       
        #もし,顔が検出できなかったら,
        if len(face_list) == 0:
            
            #検出できるまで,続ける
            continue
        
        #もし,顔が検出できたら,
        elif len(face_list) > 0: 
        
            #認証した部分に印をつける(枠で囲む)
            for (x,y,w,h) in face_list:
                
                #赤を用意
                red = (0,0,255)
                
                #顔の部分を囲む
                cv2.rectangle(frame, (x,y), (x+w, y+h), red, 1)
                
                #顔の部分のみ取り出す
                trim_face = frame[y:y+h,x:x+w]
                                
                #RGBに変換する(OpenCVのBGRをRGBに変換する)
                image_rgb = cv2.cvtColor(trim_face,cv2.COLOR_BGR2RGB)
 
        #--------------------------------------------------------------------------- 
        #前回からの変更点1-ココまで-                   
        #---------------------------------------------------------------------------
        
        #pillowに変換
        change_pillow = Image.fromarray(image_rgb)
    
        
        #OpenCVのRGBからpillowのRGBに変換する
        rgb_pillow = change_pillow.convert("RGB")
            
        #画像のサイズをリサイズする(顔のみの画像)
        resize_face = rgb_pillow.resize((image_size, image_size))
    
    
        #顔の部分のみの画像を数値に変換する
        data = np.asarray(resize_face)
        
        #リストを用意
        X = []
        
        #Xにdataを入れる
        X.append(data)
        
        #XをTensorFlowが扱いやすいようにNumpy型に変換する
        X = np.array(X)
        
        #ニューラルネットワークのモデル関数を呼び出す
        model = neural_model()
        
        #画像をニューラルネットワークのモデルから予測する
        result = model.predict([X])[0]
        
        #一番値の大きい配列の添え字を返す
        pred = result.argmax()
    
        #--------------------------------------------------------------------------- 
        #前回からの変更点2-ココから-
        #--------------------------------------------------------------------------- 
        
        #もし,"my_face"なら,
        if face_classes[pred] == "my_face":
        
            #映像の顔の部分を青色で囲む
            for (x,y,w,h) in face_list:
                
                #青色を準備
                blue = (255,0,0)
                
                #顔を枠で囲む
                cv2.rectangle(frame, (x, y), (x+w,y+h), blue, 2)
            
            cv2.imshow("Detect_Face", frame)
            
            #もし,Enterキーが押されたら終了する
            exit_wind = cv2.waitKey(1)
            
            if exit_wind == 13:

                break
              
        #もし,"other_face"なら,
        elif face_classes[pred] == "other_face":
            
            #映像の顔の部分を赤色で囲む
            for (x,y,w,h) in face_list:
                
                #赤色を準備
                red = (0,0,255)
                
                #顔を枠で囲む
                cv2.rectangle(frame, (x, y), (x+w,y+h), red, 2)
            
            cv2.imshow("Detect_Face", frame)
            
            #もし,Enterキーが押されたら終了する
            exit_wind = cv2.waitKey(1)
            
            if exit_wind == 13:

                break
       
        #--------------------------------------------------------------------------- 
        #前回からの変更点2-ココまで-                   
        #---------------------------------------------------------------------------


#Anaconda Prompt上で実行する          
if __name__ == "__main__":
    
    main_predict()

Anaconda Prompt上で判定してみよう!

Anaconda Promptを開き,以下の通りに記述すると,AIが顔を判定してくれます.

  • activate tf140
  • cd Desctop
  • python video_face_predict.py

・本人の顔の時

畳み込みニューラルネットワークによって,映像から本人の顔を判定する.

・他人の顔の時

畳み込みニューラルネットワークによって,映像から他人の顔を判定する.

(※顔は隠してありますが,判定は出来ています.)

今後の課題

映像から本人の顔と他人の顔を判定することが出来たけれど,カメラの動きが遅いという問題点があります.

この原因として,映像を畳み込みニューラルネットワークで判定する際に,

映像を1枚ずつ読み込まないといけないからではないかと考えています.

今後は,コードを変更し,カメラの映像をスムーズに動くようにしていきたいです!

終わりに

今回は,AIを使って,映像から本人の顔と他人の顔を判定しました.

無事,判定は出来たけれど,動きが遅いという問題があるので,

改善していきます^^

それでは・・・

Q &A

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA