【Python+OpenCV】顔検出応用!目と笑顔の検出方法

以前の記事でOpenCVで顔検出するプログラムを解説しました。

今回は、顔検出の応用として、目と笑顔を検出する方法について解説します。

目次

サンプルプログラム

こちらが目、笑顔を検出するサンプルプログラムです。

import cv2 as cv

# カスケード分類器読み込み
frontalface_cascade = cv.CascadeClassifier("haarcascade_frontalface_default.xml")
eye_cascade = cv.CascadeClassifier("haarcascade_eye.xml")
smile_cascade = cv.CascadeClassifier("haarcascade_smile.xml")

# 画像の読み込み
img = cv.imread("sample.jpg")

# 顔検出
face = frontalface_cascade.detectMultiScale(img)

# 顔部を赤枠で囲む
for x, y, w, h in face:
    cv.rectangle(img,(x,y), (x+w, y+h), (0,0,255), 1)
    
    # 顔部の上3/4を切り取り
    upper_face_img = img[y:int(y+3*h/4), x:x+w]
    
    # 目検出
    eye = eye_cascade.detectMultiScale(upper_face_img)
    
    # 目部を青枠で囲む
    for x1, y1, w1, h1 in eye:
        cv.rectangle(img, (x+x1,y+y1), (x+x1+w1, y+y1+h1), (255,0,0), 1)
      
    # 顔部の下半分を切り取り  
    under_face_img = img[int(y+h/2):(y+h), x:x+w]

    # 笑顔検出
    smile = smile_cascade.detectMultiScale(under_face_img)
     
    # 笑顔を緑枠で囲む
    for x2, y2, w2, h2 in smile:
        cv.rectangle(img,(x+x2, int(y+h/2)+y2), (x+x2+w2, int(y+h/2)+y2+h2), (0,255,0), 1)

cv.imshow("img", img)
cv.waitKey(0)
cv.destroyAllWindows()

実行結果がこちら

3人とも目が検出できました。右2人は笑っているので、口元が笑顔と判定されています。

次章ではサンプルプログラムを解説していきます。

プログラム解説

サンプルプログラムの流れは以下のとおりとなっています。

STEP
カスケード分類器読み込み
STEP
画像の読み込み
STEP
顔の検出
STEP
目の検出
STEP
笑顔の検出

STEP1~3は、別記事で解説していますので、本記事では割愛しました。

ここでは、STEP4: 目の検出、STEP5: 笑顔の検出について解説していきます。

目の検出

目を検出するには「haarcascade_eye.xml」を使用します。

# カスケード分類器読み込み
eye_cascade = cv.CascadeClassifier("haarcascade_eye.xml")

# 顔部の上3/4を切り取り
upper_face_img = img[y:int(y+3*h/4), x:x+w]

# 目検出
eye = eye_cascade.detectMultiScale(upper_face_img)

# 目部を青枠で囲む
for x1, y1, w1, h1 in eye:
    cv.rectangle(img, (x+x1,y+y1), (x+x1+w1, y+y1+h1), (255,0,0), 1)mg)

顔部の上3/4を切り取り、この中から目を検出して青枠で囲むということをしています。

もし、顔部を切り取らなかったらどうなるのでしょうか?

下図は顔部を切り取らなかった場合の実行結果です。

左の女性のおでこと口が目と誤判定されてしまいました。目は顔の上部に位置していますので、誤判定しないためにも検出範囲を顔の上部のみに絞る方が良いことが分かります。

笑顔の検出

笑顔を検出するのは「haarcascade_smile.xml」です。

# カスケード分類器読み込み
smile_cascade = cv.CascadeClassifier("haarcascade_smile.xml")

# 顔部の下半分を切り取り  
under_face_img = img[int(y+h/2):(y+h), x:x+w]

# 笑顔検出
smile = smile_cascade.detectMultiScale(under_face_img)
    
# 笑顔を緑枠で囲む
for x2, y2, w2, h2 in smile:
    cv.rectangle(img,(x+x2, int(y+h/2)+y2), (x+x2+w2, int(y+h/2)+y2+h2), (0,255,0), 1)

目の検出同様、顔部の下半分を切り取り、この中から笑顔を検出して緑枠で囲みます。

こちらも顔部を切り取らなかった場合を確認してみましょう。

様々なところで笑顔が検出されてしまいました。検出範囲を絞ることが重要です!

色々な画像で目・笑顔の検出

こちらの画像では右側女性の右目が検出出来ませんでした。

こちらの写真は3人とも笑顔ではないですが、口元が笑顔と検出されています。

笑顔検出というよりは、口検出に近いですね。

まとめ

顔検出の応用として、OpenCVの「カスケード分類器」を使用した目・笑顔検出プログラムについて解説しました。

手順のおさらい

  • カスケード分類器読み込み
  • 画像の読み込み
  • 顔の検出
  • 目の検出
  • 笑顔の検出

今回の記事が皆さんのPython学習に役立つなら幸いです。

Python独学が大変な方は、書籍やスクールを活用するのも手です。

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

大学で機械工学を学んだ後、製造業で働く40代の会社員です。
IT系、電気系を学んでこなかった機械系人間が、ゲーム制作、電子工作に奮闘してます。
極力低コストでものづくりを楽しむのがモットー。

目次