LoginSignup
5
3

More than 3 years have passed since last update.

【Python】OpenCVによる顔検出 (Haar Cascade)

Posted at

はじめに

今回はOpenCVを用いて、顔か検出をやってみたいと思います。顔検出の手法は色々あるのですが、今回はHaar cascadeを用います。

環境

MacOS Mojave
Python 3.7

Haar Casecade?

顔っぽさを表す特徴量 (Haar特徴量) から、これは顔であるかないかを判断する分類器のことです。この分類器は、高速化の為に複数の分類器が結合してできていることから、Cascade (結合) 分類器と呼ばれます。Haar特徴量は以下のような白黒の特徴量が用いられます。
スクリーンショット 2020-03-24 16.45.21.png
図. Haar特徴量
(画像引用元:http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_objdetect/py_face_detection/py_face_detection.html)

なんだこの白黒は、、、と思ったんじゃないでしょうか。少し人間の顔がどうなっているのかを考えてみましょう。

人間の顔って高度に抽象化すると、大体は以下のようになるのではないでしょうか (ならないか...w)
スクリーンショット 2020-03-24 16.53.30.png
図. 高度に抽象化された顔

上図から、例えば目元は左から"黒白黒"の色の配置になっていると思いませんか。
スクリーンショット 2020-03-24 17.01.59.png
図. 高度に抽象化された顔の白と黒の配置

この高度に抽象化された顔っぽい白と黒の配置を表したのがHaar特徴量です。
入力画像から任意の領域を切り出し、この特徴量がたくさん存在すれば、顔だと判断します。
スクリーンショット 2020-03-24 16.45.32.png
図. 顔だと判断された画像 (目元など、Haar特徴量がたくさん存在する)
(画像引用元:http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_objdetect/py_face_detection/py_face_detection.html)

ここではざっくりとしたイメージの解説だけなので、詳細を知りたい方は以下の論文を読んでみてください。
https://www.cs.cmu.edu/~efros/courses/LBMV07/Papers/viola-cvpr-01.pdf

顔検出

では、haar cascadeを用いて人の顔を認識してみたいと思います。画像は以下の画像 (woman.jpg) を使用しました。
woman.jpg

実行したコードは以下のようになります。

import cv2
import matplotlib.pyplot as plt

#画像の読み込み (画像1066x1600)
img = cv2.imread("woman.jpg")
#顔のカスケード分類器を読み込む
face_cascade = cv2.CascadeClassifier("haarcascades/haarcascade_frontalface_default.xml")
#画像をグレースケールにする
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#顔検出を実行!
faces = face_cascade.detectMultiScale(gray)
#facesに顔の位置が入っているので、for文で読み取る
for (x,y,w,h) in faces:
    #矩形を顔の位置に矩形を描画する
    img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),10)
#色の順番を変更する
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#出力
plt.imshow(img)
plt.show()

結果
スクリーンショット 2020-03-24 17.27.20.png

ちゃんと認識されてますね!
次にコードの中のポイントだけ解説していきます。

カスケード分類器の読み込み

#顔のカスケード分類器を読み込む
face_cascade = cv2.CascadeClassifier("haarcascades/haarcascade_frontalface_default.xml")

この部分では、上記で述べた顔を分類するためのcascade分類器を読み込んでいます。もし

OpenCV(4.2.0) /Users/travis/build/skvark/opencv-python/opencv/modules/objdetect/src/cascadedetect.cpp:1689: error: (-215:Assertion failed) !empty() in function 'detectMultiScale'

のようなメッセージが出てきたら、多分カスケード分類器のxmlファイルががないので、以下からダウンロード (もしくはclone) してください。
https://github.com/opencv/opencv

ダウンロードしたら、data/haarcascadesのフォルダを自分のpythonファイル(またはipynb)と同じフォルダ内にいれて実行してください。

矩形描画

for (x,y,w,h) in faces:
    #矩形を顔の位置に矩形を描画する
    img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),10)

顔の位置は(x,y,幅,高さ)で出力されます。これは以下のようになります。
スクリーンショット 2020-03-24 17.44.01.png

cv2.reactangleの引数は以下のようになります。
cv2.reactangle(画像,(左上x,左上y),(右下x,右下y),(色),線の太さ)
スクリーンショット 2020-03-24 17.47.45.png

終わりに

カスケード分類器は顔だけでなく胴体や下半身、猫なども検出できます。近々その記事も執筆したいと思います。もし、記事に対してのご意見、誤りなどがあればコメントください。

Twitter

Twitterでも発信をしてます。もしよければフォローお願いします、、、!
https://twitter.com/ryuji33722052

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3