Python | OpenCVで顔を検出する

Python | OpenCVで顔を検出する

今回はOpenCVの顔検出機能を検証します。

Haar Cascadesのダウンロード

物体検出を行うための測定器である「Haar Cascades(Haar特徴ベースのCascade型分類器)」を利用します。

あらかじめ特徴量を学習しておいたxmlファイルをプログラムにセットすることで、簡単に顔検出器を作成することができます。

XMLファイルは以下のリンクから取得することができます。

今回は「顔検出」ということで、「haarcascade_frontalface_default.xml」を利用します。

顔画像の準備

今回は「Lena」画像をもとに顔認証します。

画像の入手方法はこちらを参照ください。

検証

今回のソースは以下の通りです。

#------------------------------------------------------------
#顔検出のプログラム(画像)
#------------------------------------------------------------
import cv2

try:

    # 1)画像を読み取る
    img = cv2.imread('lena_std.bmp')
    if img is None:
        raise FileNotFoudError('IMG Not Found!')

    # 2)検出器をロードする
    cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    if cascade is None:
        raise FileNotFoudError('XML Not Found!')

    # 3)画像に検出器を適用する
    #   arrayが返ってくる
    #    例:array([[217, 201, 173, 173]])
    #        array([[x, y, w, h]])
    face = cascade.detectMultiScale(img)
    
    # 4)顔を枠で囲む
    #   cv2.retangle(画像,xy座標,対角線上のxy座標,色,線の太さ)
    if len(face)>0:
        for (x,y,w,h) in face:
            cv2.rectangle(img, (x,y), (x+w,y+h),(0,255,0), thickness=2)
    else:
        print('ERROR')
    
    # 5)画像を表示
    cv2.imshow('lena',img)
    
    # 6)キーイベントの待機 / 引数=0 で何か入力されるまで待つ
    cv2.waitKey(0)

    # 7)入力されたら、ウィンドウを閉じる
    cv2.destroyAllWindows()

# except) Error時
except FileNotFoundError as e:
    print(e)

顔検出を行うことができました!

応用:目の検出

目を検出する場合は「haarcascade_eye.xml」を利用します。

cascadeを以下のように変更します。

cascade = cv2.CascadeClassifier('haarcascade_eye.xml')

応用:目と顔を検出する

顔を赤色、目を緑色で示します。

#------------------------------------------------------------
#顔&目検出のプログラム(画像)
#------------------------------------------------------------
import cv2

try:

    # 1)画像を読み取る
    img = cv2.imread('lena_std.bmp')
    if img is None:
        raise FileNotFoudError('IMG Not Found!')

    # 2)検出器をロードする
    cascade_face = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    cascade_eye = cv2.CascadeClassifier('haarcascade_eye.xml')
    
    if cascade is None:
        raise FileNotFoudError('XML Not Found!')

    # 3)画像に検出器を適用する
    face = cascade_face.detectMultiScale(img)
    eye = cascade_eye.detectMultiScale(img)

    
    # 4)顔を枠で囲む
    if len(face)>0 and len(eye)>0:
        for (x,y,w,h) in face:
            cv2.rectangle(img, (x,y), (x+w,y+h),(0,0,255), thickness=2)
        for  (x,y,w,h)  in eye:
            cv2.rectangle(img, (x,y), (x+w,y+h),(0,255,0), thickness=2)
    else:
        print('ERROR')
        
        
    # 5)画像を表示
    cv2.imshow('lena',img)
    
    # 6)キーイベントの待機 / 引数=0 で何か入力されるまで待つ
    cv2.waitKey(0)

    # 7)入力されたら、ウィンドウを閉じる
    cv2.destroyAllWindows()

# except) Error時
except FileNotFoundError as e:
    print(e)

応用:映像から顔を検出する

上記の画像処理を応用して、カメラから取得した画像にたいして、顔検出を適用してみます。

import cv2

try:
    
    # 1)カメラIDを設定
    camera = cv2.VideoCapture(0)
    
    # 2)検出器をロードする
    cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    if cascade is None:
        raise FileNotFoudError('XML Not Found!')
        
    # 3)繰り返し画像を取得する
    while True:
        
        # 4)設定したカメラから画像を取得
        ret, img = camera.read()

        # 5)画像に検出器を適用する
        face = cascade.detectMultiScale(img)
        
        # 6)顔を枠で囲む
        if len(face)>0:
            for (x,y,w,h) in face:
                cv2.rectangle(img, (x,y), (x+w,y+h),(0,255,0), thickness=2)

        # 7) 画像を表示
        cv2.imshow('Face_Capture',img)

        # 8) Escが入力されたらループ処理を終了する
        key = cv2.waitKey(10)
        if key == 27:
            break       
        
    # 9)入力されたら、ウィンドウを閉じる
    cv2.destroyAllWindows()
    
    # 10)カメラのメモリを解放する
    camera.release()

# except) Error時
except FileNotFoundError as e:
    print(e)

こちらも映像から顔を検出することができたかと思います。

原理としては、画像から顔を検出する処理を繰り返しているだけです。

ただ、この検出器は「横顔」や「眼鏡」には対応しきれないようでした。

いろいろな検出器がありますので、試してみるのもよいですね!

ではまた!