BETA

OpenCVで顔認証やってみた(Part1:学習編)

投稿日:2019-09-28
最終更新:2019-11-01

OpenCVで顔認証をサンプルコードを参考に作ってみた......
使った各種バージョンは以下

  • MacOS Mojave / python3.5.6 / Opencv3.4.2 / VS Code1.38.1

コメント

掲載したソースは「Mac」で動作確認済み
「ラズパイ」/「Tinkerboard」でも動作可能。USBカメラのVideoポート変更必要
数ヶ月前に「Opencv」「Python」勉強し始めたレベルなので間違いあったらごめんなさい

簡単な顔学習の概要

  • 顔認証するために学習する人物毎に番号をつけて顔画像を保存する
  • 保存した顔画像ファイルの全員分データを一つのモデルファイルとして作成する

顔学習方法(ソースファイル説明)は以下の流れ

  • カメラから顔をキャプチャー
  • キャプチャーした後は顔認識用のカスケードファイル(haarcascade_frontalface_alt2.xml)を使用して顔認識する
  • 顔認識した画像から顔の部分を抽出し、画像ファイルに保存する
  • 最後に保存している複数人の顔画像からYAMLファイル(モデルファイル)を作成する

学習用サンプル画像

  • 画像ファイルから顔認証学習データを作成する際に使用した画像(サンプル)
    (注)ソースコードはカメラからキャプチャー

ファイル構成

  • ./data_xml/ # カスケードファイルを格納しているフォルダ
  • ./image_data/ # キャプチャーした画像ファイルを保存するフォルダ
  • ./trainer/ # 最後に学習したYAMLファイルとして保存するフォルダ
  • face_datamake.py # 顔学習するためのPythonファイル(下のソースコード)

ソースコード

# -*- coding: UTF-8 -*-  
import cv2  
import os  
import numpy as np  
from PIL import Image  

# 学習画像データ枚数取得変数初期化  
sample_cnt = 0  

###############################  
# VideoCapture用インスタンス生成 #  
###############################  
cap = cv2.VideoCapture(0)  

###############################  
# 画像サイズをVGAサイズに変更する  #  
###############################  
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)   
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)   

#######################################################################  
# 顔検出を認識する カスケードファイルは「haarcascade_frontalface_alt2.xml」 #  
# カスケードファイルは以下からローカルにダウンロードしておく                    #  
# <https://github.com/opencv/opencv/tree/master/data/haarcascades>    #  
#######################################################################  
face_detector = cv2.CascadeClassifier('/Users/local/source/opencv/face_recognition/data_xml/haarcascade_frontalface_alt2.xml')  

#######################################################  
# 学習画像用データから顔認証データymlファイル作成するメソッド  #  
# このファイルを顔認証デートのモデルファイルとして使用する     #  
#######################################################  
def image_learning_make_Labels():  

    # リスト保存用変数  
    face_list=[]  
    ids_list=[]  

    # 学習画像データ保存領域パス情報  
    path = '/Users/local/source/opencv/face_recognition/image_data'  
    # Local Binary Patterns Histogram(LBPH)アルゴリズム インスタンス  
#    recognizer = cv2.face.createLBPHFaceRecognizer()  
    recognizer=cv2.face_LBPHFaceRecognizer.create()  

    # 学習画像ファイルパスを全て取得  
    imagePaths = [os.path.join(path,f) for f in os.listdir(path)]  

    # 学習画像ファイル分ループ  
    for imagePath in imagePaths:  

        # グレースケールに変換  
        PIL_img = Image.open(imagePath).convert('L')  
        img_numpy = np.array(PIL_img,'uint8')  

        # UseriDが入っているファイル名からUserID番号として取得  
        id = int(os.path.split(imagePath)[-1].split(".")[1])  
        # 物体認識(顔認識)の実行  
        faces = face_detector.detectMultiScale(img_numpy)  

        # 認識した顔認識情報を保存  
        for (x,y,w,h) in faces:  
            face_list.append(img_numpy[y:y+h,x:x+w])  
            ids_list.append(id)  

    print ("\n Training Start ...")  
    ##############################  
    # 学習スタート                 #  
    ##############################  
    recognizer.train(face_list, np.array(ids_list))  

    #####################################  
    # 学習用した結果を.ymlファイルに保存する  #  
    #####################################  
    recognizer.save('/Users/local/source/opencv/face_recognition/trainer/trainer.yml')   

    # 学習した顔種類を標準出力  
    print("\n User {0} trained. Program end".format(len(np.unique(ids_list))))  


#####################################  
# 顔認証したい人物の通し番号を入力させる  
#####################################  
User_id = input('\n User Id Input <ex:001> >>>  ')  
print("\n Face capture Wait ............")  

####################################  
#  学習用画像データ取得と保存  
####################################  
while(True):  

    # カメラで顔データを取得する  
    ret, img = cap.read()  
    # 画像をグレースケールに変換する  
    image_pil = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
    # NumPyの配列に格納  
    gray = np.array(image_pil, 'uint8')  
    # Haar-like特徴分類器で顔を検知  
    faces = face_detector.detectMultiScale(gray)  
    # 学習用画像データを作成  
    for (x,y,w,h) in faces:  
        # 顔部分を切り取り  
        cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)       
        sample_cnt += 1  

        # 画像ファイル名にUSERIDを付与して保存  
        cv2.imwrite("/Users/local/source/opencv/face_recognition/image_data/User." + str(User_id) + '.' + str(sample_cnt) + ".jpg", image_pil[y:y+h,x:x+w])  
        # 画像データを画面表示  
        cv2.imshow('image', img)  

    # 認証学習画像を10枚  
    if sample_cnt >= 10:  
         break  

print("\n Face capture End ")  
########################  
# 学習ファイル作成  
########################  
image_learning_make_Labels()  

### カメラ解放 ###  
cap.release()  
cv2.destroyAllWindows()  
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@主にプログラム技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!