#はじめに
今回はOpenCVを用いて、顔か検出をやってみたいと思います。顔検出の手法は色々あるのですが、今回はHaar cascadeを用います。
#環境
MacOS Mojave
Python 3.7
#Haar Casecade?
顔っぽさを表す特徴量 (Haar特徴量) から、これは顔であるかないかを判断する分類器のことです。この分類器は、高速化の為に複数の分類器が結合してできていることから、Cascade (結合) 分類器と呼ばれます。Haar特徴量は以下のような白黒の特徴量が用いられます。
図. 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)
図. 高度に抽象化された顔
上図から、例えば目元は左から"黒白黒"の色の配置になっていると思いませんか。
図. 高度に抽象化された顔の白と黒の配置
この高度に抽象化された顔っぽい白と黒の配置を表したのがHaar特徴量です。
入力画像から任意の領域を切り出し、この特徴量がたくさん存在すれば、顔だと判断します。
図. 顔だと判断された画像 (目元など、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) を使用しました。
実行したコードは以下のようになります。
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()
ちゃんと認識されてますね!
次にコードの中のポイントだけ解説していきます。
##カスケード分類器の読み込み
#顔のカスケード分類器を読み込む
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,幅,高さ)で出力されます。これは以下のようになります。
cv2.reactangleの引数は以下のようになります。
cv2.reactangle(画像,(左上x,左上y),(右下x,右下y),(色),線の太さ)
#終わりに
カスケード分類器は顔だけでなく胴体や下半身、猫なども検出できます。近々その記事も執筆したいと思います。もし、記事に対してのご意見、誤りなどがあればコメントください。
#Twitter
Twitterでも発信をしてます。もしよければフォローお願いします、、、!
https://twitter.com/ryuji33722052