トップページ人工知能,実世界DB顔情報(顔検出,顔識別、表情判定,顔のクラスタリングや類似度や分類,肌色部分の抽出,瞳孔の検出,顔姿勢の推定)Dlib を用いて,顔検出,顔のランドマーク検知(68 ランドマーク法),表情判定を行う(Windows 上)

Dlib を用いて,顔検出,顔のランドマーク検知(68 ランドマーク法),表情判定を行う(Windows 上)

Dlibは,数多くの機能を持つ C++ ライブラリ.機能には,機械学習,数値計算,グラフィカルモデル推論,画像処理,スレッド,通信,GUI,データ圧縮・一貫性,テスト,さまざまなユーティリティなどがある.Python API もある.

このページでは,Dlib の次の機能を使う

利用条件などは利用者において確認してください

【サイト内の関連ページ】

先人に感謝

dlib の Web ページ: http://dlib.net/

前準備

Python のインストール,pip と setuptools の更新,Python 開発環境

Python の URL: http://www.python.org/

【Python, pip の使い方】

Python, pip は,次のコマンドで起動できる.

Python 開発環境のインストール】

Dlib のインストール

Dlib は c:\dlib にインストールされているとして,以下,説明する.

Python 用 numpy, scikit-image, opencv-python のインストール

Windows の場合

コマンドプロンプト管理者として実行し,次のコマンドを実行.

Windows での pip の実行では,コマンドプロンプト管理者として実行することにする。

[image]

python -m pip install -U numpy scikit-image scikit-learn

imutils のインストール

Dlib は c:\dlib にインストールされているとして,以下,説明する.

  • Windows で,コマンドプロンプト管理者として実行する.

    [image]
  • imutils のインストール
    mkdir c:\pytools
    cd c:\pytools
    rmdir /s /q imutils
    

    [image]

    cd c:\pytools
    git clone https://github.com/jrosebr1/imutils
    cd imutils
    python setup.py build
    python setup.py install 
    

    [image]
    (以下省略)
  • imutils のバージョン確認

    Windows のコマンドプロンプトで、次のコマンドを実行

    Python プログラムを動かすために, Windows では「python」, Ubuntu では「python3」などのコマンドを使う. あるいは, 開発環境や Python コンソール(Jupyter Qt ConsoleSpyderPyCharmPyScripter など)の利用も便利である.

    py -c "import imutils; print( imutils.__version__ )"
    

    [image]

    学習済みのモデルデータのダウンロードと展開(解凍)

    Dlib のための「学習済みのモデルデータ」をダウンロードする

    1. Web ブラウザで次の URL を開く

      http://dlib.net/files

    2. 次の3つのファイルをダウンロードする
      • dlib_face_recognition_resnet_model_v1.dat.bz2
      • shape_predictor_5_face_landmarks.dat.bz2
      • shape_predictor_68_face_landmarks.dat.bz2

      [image]
    3. ダウンロードした .bz2 ファイルを,すべて展開(解凍)する.

      Windows での展開(解凍)のためのソフトには,「7-Zip」などがある.

    4. 展開(解凍)してできたファイルを確認する.

      [image]
    5. 展開(解凍)してできたファイルを3つとも,先ほど作成した c:\dlib (Dlib のディレクトリ)の下の「python_example」にコピー

      c:\dlib が無いときは作る

    dlib サンプルプログラムのいくつかを実行してみる.

    1. Windows のコマンドプロンプトを開く
    2. カレントディレクトリの移動

      c:\dlib」は,Dlib のディレクトリ

      cd c:\dlib\python_examples
      

      [image]

      ※ 「c:\dlib」は,Dlib をインストールしたディレクトリに読み替えること。

      ※ まだ Dlib のインストールを行っていないときは, 別のWebページで説明している.手順によりインストールすること.(このWebページにある「前準備」も行うこと)

    3. 顔検出 (face detector) のサンプルプログラムを実行してみる

      顔検出が行われ,顔を囲むようなバウンディングボックス (bounding box) が表示される. そして,バウンディングボックスの座標値が数値データとして得られていることが,画面表示で確認できる.

      python face_detector.py ..\examples\faces\2007_007763.jpg
      

      [image]

      [image]
    4. 顔のランドマークの検知 (face landmark detector) のサンプルプログラムを実行してみる

      顔ごとに,最大で 68 のランドマーク (68 landmarks) が得られる.

      python face_landmark_detection.py shape_predictor_68_face_landmarks.dat ..\examples\faces\
      

      [image]

      [image]

    ezgiakcora/Facial-Expression-Keras を動かしてみる

    GitHub の ezgiakcora/Facial-Expression-Keras で公開されているプログラムを試してみる. これは Dlibを使う表情認識のプログラムである

    1. Windows で,コマンドプロンプト管理者として実行する.

      [image]
    2. インストール
      mkdir c:\pytools
      cd c:\pytools
      rmdir /s /q Facial-Expression-Keras
      

      [image]

      cd c:\pytools
      git clone https://github.com/ezgiakcora/Facial-Expression-Keras
      cd Facial-Expression-Keras
      

      [image]
    3. Dlib 関連のファイルをコピーして使う
      cd c:\pytools\Facial-Expression-Keras
      copy c:\dlib\python_examples\shape_predictor_68_face_landmarks.dat .
      

      [image]
    4. 表情判定のプログラムを動かしてみる

      USB接続できるビデオカメラを準備し,パソコンに接続しておく.

      1. Windows のコマンドプロンプトを開く
      2. プログラムの実行
        cd c:\pytools\Facial-Expression-Keras
        py demo.py 
        

        [image]

        ※ 途中で止めたいとき,右上の「x」をクリックしない.画面の中をクリックしてから,「q」のキーを押して閉じる

      3. demo.py を少し書き変えて動かす
        import numpy as np
        import cv2
        from tensorflow.keras.preprocessing import image
        import dlib
        from imutils import face_utils
        import imutils
        from sklearn import preprocessing
        import math
        from keras.models import model_from_json
        #-----------------------------
        #opencv initialization
        face_cascade = cv2.CascadeClassifier('C:/pytools/Facial-Expression-Keras/haarcascade_frontalface_default.xml')
        cap = cv2.VideoCapture(0)
        
        #-----------------------------
        #face expression recognizer initialization
        # Using pretrained model
        model = model_from_json(open("C:/pytools/Facial-Expression-Keras/model/model.json", "r").read())
        model.load_weights('C:/pytools/Facial-Expression-Keras/model/model.h5') #load weights
        
        #-----------------------------
        
        emotions = ( 'Angry' , 'Disgust' , 'Fear' , 'Happy'  , 'Neutral' ,  'Sad' , 'Surprise')
        # initialize dlib's face detector and create a predictor
        detector = dlib.get_frontal_face_detector()
        predictor = dlib.shape_predictor("C:/pytools/Facial-Expression-Keras/shape_predictor_68_face_landmarks.dat")
        
        
        def detect_parts(image):
            distances = []
            # resize the image, and convert it to grayscale
            image = imutils.resize(image, width=200, height=200)
            
            gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
            # detect faces in the grayscale image
            rects = detector(gray, 1)
            
            # loop over the face detections
            for (i, rect) in enumerate(rects):
                shape = predictor(gray, rect)
                shape = face_utils.shape_to_np(shape)
                distances = euclidean_all(shape)
                # visualize all facial landmarks with a transparent overlay
                #output = face_utils.visualize_facial_landmarks(image, shape)
                #cv2.imshow("Image", output)
                #cv2.waitKey(0)    
            return distances
        
        def euclidean(a, b):
            dist = math.sqrt(math.pow((b[0] - a[0]), 2) + math.pow((b[1] - a[1]), 2))
            return dist 
        
        # calculates distances between all 68 elements
        def euclidean_all(a):  
            distances = ""
            for i in range(0, len(a)):
                for j in range(0, len(a)):
                    dist = euclidean(a[i], a[j])
                    dist = "%.2f" % dist;
                    distances = distances + " " + str(dist)
            return distances
        
        
        def box_label(bgr, x1, y1, x2, y2, label): 
            cv2.rectangle(bgr, (x1, y1), (x2, y2), (255, 0, 0), 1, 1)
            cv2.rectangle(bgr, (int(x1), int(y1-25)), (x2, y1), (255,255,255), -1)
            cv2.putText(bgr, label, (x1, int(y1-5)), cv2.FONT_HERSHEY_COMPLEX, 0.7, (0,0,0), 1)
        
        
        while(True):
            ret, img = cap.read()
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray, 1.3, 5)
        
            for (x,y,w,h) in faces:
                detected_face = img[int(y):int(y+h), int(x):int(x+w)] #crop detected face
                distances = detect_parts(detected_face)
        
                if(len(distances)!=0):
                    val = distances.split(" ")[1:]
                    val = np.array(val)
                    val = val.astype(np.float)
                    val = np.expand_dims(val, axis = 1)            
                    minmax = preprocessing.MinMaxScaler()
                    val = minmax.fit_transform(val)
                    val = val.reshape(1,4624)
        
                    predictions = model.predict(val) #store probabilities of 6 expressions
                #find max indexed array ( 'Angry' , 'Disgust' , 'Fear' , 'Happy'  , 'Neutral' ,  'Sad' , 'Surprise')
                    print ("Angry: %", predictions[0][0]/1.0 * 100)
                    print ("Disgust: %", predictions[0][1]/1.0 * 100)
                    print ("Fear: %", predictions[0][2]/1.0 * 100)
                    print ("Happy: %", predictions[0][3]/1.0 * 100)
                    print ("Neutral: %", predictions[0][4]/1.0 * 100)
                    print ("Sad: %", predictions[0][5]/1.0 * 100)    
                    print ("Surprised: %", predictions[0][6]/1.0 * 100)        
                    print ("----------------------"    )    
                    max_index = np.argmax(predictions[0])
                    emotion = emotions[max_index]
                
                    #write emotion text above rectangle
                box_label(img, x, y, x+w, y+h, emotion+":"+'{:2.2f}'.format(np.max(predictions[0])/1.0 * 100))
                
            cv2.imshow('img',img)
        
            if cv2.waitKey(1) & 0xFF == ord('q'): #press q to quit
                break
        
        #kill open cv things        
        cap.release()
        cv2.destroyAllWindows()
        

        ※ 途中で止めたいとき,右上の「x」をクリックしない.画面の中をクリックしてから,「q」のキーを押して閉じる

        [image]