Python OpenCVの基礎 ついに顔検出してみます
OpenCVでの顔検出
やっとそれっぽいことを始めます。助走が長くてなかなかここまでたどり着きませんでしたね。
さてさて、OpenCVでググると大体顔検出ってのが上位にきます。
ということなので、詳しいところを知りたい方はそちらをご覧いただくのがいちばんなのですが。。。。 とりあえず私も頑張ってチャレンジしてみますので、お暇なら読んでみてください。
顔検出の流れ
- 分類器の読み込み
- 画像読み込み
- BGR2GRAY変換
- 顔検出
- (おまけ)顔の部分を四角く描画
顔検出できた時点でOKなんですけど、座標で出してもいまいち分かりにくいので、みなさん顔枠を描画してらっしゃるようです。
ソースはこちら
カスケード分類器
ここでカスケード分類器というモノが登場します。
こちらを参照してください
カスケード型分類器 — opencv 2.2 (r4295) documentation
ざっくり言うと、顔検出についてのいろんな情報が集まっていて、それを参照しながら画像を見てきましょう、という感じのものですね。 この精度により、顔が検出できたりできなかったりするみたいです。面白いですね。
分類器は、自分で作ることもできるようですし、それが必ずしも顔である必要はないみたいです。特定のモノ(ボールとか)を指定することもアリなんですね。
デフォルトで用意されている分類器を使ってみます。
で、その分類器をゼロから作るのは大変です(だと思います、作ったことないから分かりませんが、、) なので、OpenCVをインストールした時に一緒に付属してきた分類器を使ってみようと思います。
カスケード分類器の場所は
ここにあります。 opencv-2.4.9/data/haarcascades
22ファイルもありました。名前から色々と推測できますが、今回はhaarcascade_frontalface_default.xmlを使ってみます。
機会があれば、それぞれがどういう特徴を持っているのかを調べてみたいですね。
ファイルはxmlです。中身をちらっと見てみましたが、よくわからない。。。。この中身が何なのかはまた次の機会に。
ちなみにカスケード以外の分類器もあります。色々と勉強することが多いです。
ソースを詳しく見ていきましょう
#カスケード分類器を読み込む faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cv2.CascadeClassifierでカスケード分類器を読み込む
こちらにCascadeClassifierの説明がありました。
Cascade Classification — OpenCV 2.4.12.0 documentation
Loads a classifier from a file.
cv2.CascadeClassifier([filename]) →
Parameters: filename – Name of the file from which the classifier is loaded.
要はカスケード分類器のファイルの中身を読み込んでくれているわけですね。
ここでは、faceCascadeにCascadeClassifierのオブジェクトが設定されました。
画像の読み込みとBGR2GRAY変換
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
グレイに変換したほうが処理が早いようです。変換しなくても処理はできますし、結果もあまり変わらないと思いますが(多分)、変換したうえで検出するのが一般的のようですね。
detectMultiScaleで検出処理
face = faceCascade.detectMultiScale(gray, 1.1, 3)
これでとりあえずはfaceに画像の中の顔情報が格納されているはずです。すごい便利ですね、これだけでいいなんて!
ちょっと詳細を見てみます。
CascadeClassifier::detectMultiScale
Python: cv2.CascadeClassifier.detectMultiScale(image[, scaleFactor[, minNeighbors[, flags[, minSize[, maxSize]]]]]) → objects
ここで、imageはgrayを入れますが、あとの1.1と3は何でしょうか??
- scaleFactor
- minNeightbors
とりあえずまたここで調べました
Cascade Classification — OpenCV 2.4.12.0 documentation
ちょっと古い資料のようですが、日本語訳はここを参考にしました。
物体検出 — opencv v2.1 documentation
scaleFactor
Parameter specifying how much the image size is reduced at each image scale.
各画像スケールにおける縮小量を表します
minNeightbors
Parameter specifying how many neighbors each candidate rectangle should have to retain it.
物体候補となる矩形は,最低でもこの数だけの近傍矩形を含む必要があります
...よくわからないですね。。。ここは後回しにしましょう。すみません。
検出した顔について、顔枠の描画処理を行う
if len(face) > 0: for rect in face: cv2.rectangle(img, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), (0, 0,255), thickness=2) else: print "no face"
すでに顔の検出はできましたので描画していきます。ここは特に解説の必要はないと思いますが、ついでなのできちんと抑えておきましょう。
rectangle
Drawing Functions — OpenCV 2.4.12.0 documentation
Draws a simple, thick, or filled up-right rectangle.
Python: cv2.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) → None
Parameters:
img – Image. pt1 – Vertex of the rectangle. pt2 – Vertex of the rectangle opposite to pt1 . color – Rectangle color or brightness (grayscale image). thickness – Thickness of lines that make up the rectangle. Negative values, like CV_FILLED , mean that the function has to draw a filled rectangle.
画像、枠の左上、枠の幅高、色、枠線の太さを指定すればいいんですね。
カスケード分類器を変えてみたら?
ちなみに分類器を変えてみたらどうなるでしょうか?
ソースはそのまま、分類器だけhaarcascade_eye.xmlに変更してみました。
はい、その結果がこれです
顔は4人を全て性格に検出できたのに、目となるとこうなってしまいました。難しい画だとは思えないのですが。。。。
今回はこちらを参考にさせていただきました
大変勉強になりました。ありがとうございました。