Python + OpenCVで顔認識


前記事で顔認識をほとんど丸コピでさらっと流してしまったので、勉強も兼ねて。


見てもらえばわかるように、僕はブログでいつも写真をたくさん貼ってて、一応肖像権への配慮から顔にはフォトショでモザイクを入れるようにしているけど、これも量が多くなってくると(ショートカット一つとはいえ)面倒になってくる。てことで、これを自動化できたらなと思いやってるんだけど、感触としてなかなか難しそう…。(判定が思いの外うまくいかない)


image.jpgに写っている顔を認識して、矩形で囲うプログラム。

import cv2
import numpy as np

faceCascade = cv2.CascadeClassifier('/usr/local/Cellar/opencv3/3.2.0/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml')

img = cv2.imread('image.jpg', cv2.IMREAD_COLOR)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
face = faceCascade.detectMultiScale(gray, 1.1, 3)

if len(face) > 0:
    print(len(face), "face")
    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")

cv2.imwrite('detected.jpg', img)


忘備録として少しコメントを。

face = faceCascade.detectMultiScale(gray, 1.1, 3)

顔を見つける関数。引数は(image, objects, scaleFactor)で、objectsとscaleFactorがよくわからん。公式のドキュメントを読んでも意味不明だった。英語版も見てみたけど一緒だった。scaleFacorは各スケールで画像サイズをどのくらいreductするかってあるから、僕が想像するに、画像をスケールを変えて走査していくなかで、どのくらい荒く調べるかってことだと思う。1より大きい値を入れないといけなくて、1.01とかの1に近い値にすると誤認識が増える。objectsは…なんだろう?判定のしきい値的なやつなのかな?上げると、認識される顔の数が減る。


cv2.rectangle(img, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), (0, 0, 255), thickness=2)

矩形を描画する関数。引数は(image, pt1, pt2, color, thickness)。さっきの検出のところで戻り値(face)は [[x1, y1, w1, h1], ..., [xi, yi, wi, hi]...[xn, yn, wn, hn]](それぞれi番目の顔の左上のx座標、左上のy座標、横幅、縦幅)のnumpy配列になっている。だから、矩形の対角座標pt1、pt2はtuple(rect[0:2])tuple(rect[0:2]+rect[2:4])で指定。(足し算されているのを見ると左下のx, yじゃないの?って思うけど、左上と書いてあった。よくわからん。軸の取り方が違うのか?一応、公式のドキュメントはこれ




で、まあこれでやるんだけど、


このくらいの写真(フリ素)でも


誤認識があって、これくらいならパラメータをいじって(例えばobjectsを10に)、


上手くはいくんだけど、このレベルでそういうことしないといけないとなると、少なくとも僕の考えている用途ではそこまで実用的ではないなぁと思ってしまう。(実際手持ちの画像でやるともっと酷く、パラメータの変更では対処できなかった。)正確を期すならこれまで通りフォトショでやったほうが速いかもしれん。



なので、この続きはもうないかも。



P.S. Googleのストリートビューとかちゃんとできてるから、技術的には可能だと思うんですけどね。。


Python + OpenCVで顔認識 Python + OpenCVで顔認識 Reviewed by mug on 7/30/2017 Rating: 5

0 件のコメント:

Powered by Blogger.