2019年10月14日月曜日

[OpenCV] 静止画の顔認識

OpenCVのライブラリを使用して顔認識を行ってみた際のメモです.なお,Python3とOpenCVがインストールされている前提です(Python3のインストールはこちら,OpenCVのインストールはこちら).

コードは以下のようになります.

import cv2 as cv

face_cascade = cv.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv.CascadeClassifier('haarcascade_eye.xml')

img = cv.imread('image.jpg')

gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5) #default setting
print(len(faces))

for (x, y, w, h) in faces:
    cv.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
    eye_gray = gray[y:y+h, x:x+w]
    eye_color = img[y:y+h, x:x+w]
    eyes = eye_cascade.detectMultiScale(eye_gray)
    for (ex, ey, ew, eh) in eyes:
        cv.rectangle(eye_color, (ex, ey), (ex+ew, ey+eh), (0, 255, 0), 2)

cv.imshow('img', img)
cv.waitKey(0)

cv.destroyAllWindows()

以下は,コードの解説です.
1行目
import cv2 as cv
OpenCVのパッケージを読み込む.

3行目
face_cascade = cv.CascadeClassifier('haarcascade_frontalface_default.xml')
face_cascade にClasfierメソッドとしてxmlファイルを読み込む.

4行目
eye_cascade = cv.CascadeClassifier('haarcascade_eye.xml')
eye_cascade にClasfierメソッドとしてxmlファイルを読み込む.

6行目
img = cv.imread('image.jpg')
imgに画像をimreadメソッドとして読み込む.

8行目
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
gray変数にimgを引数としてOpenCVのCOLOR_BGR2GRAYメソッドを使ってグレースケールの画像に変換する.

9行目
faces = face_cascade.detectMultiScale(gray, 1.35#default setting
face_cascadeのdetectMultiScaleメソッドを使って,グレースケールに変換した画像(gray)を渡す.セッテイングの引数としては,1.3, 5のデフォルトの値とする.
引数1.3を小さくして設定するとより細かく画像認識を行うようになる.
引数5は,顔が重複した時にどのように認識するかの値.
顔が認識されると,その数が変数facesに入る.

10行目
print(len(faces))
認識した顔の数を出力する.

12〜16行目
for (x, y, w, h) in faces:
    cv.rectangle(img, (x, y), (x+w, y+h), (25500), 2)
    eye_gray = gray[y:y+h, x:x+w]
    eye_color = img[y:y+h, x:x+w]
    eyes = eye_cascade.detectMultiScale(eye_gray)
認識した顔(faces)のx座標(x),y座標(y),横幅(w),高さ(h)の座標を取得する.
ループするので,結果として,認識したひとつひとつの顔に対して以下の処理を行うことになる.

cvのrectangleに引数としてimgを渡して四角で囲む.imgの中の顔として認識したエリア(座標(x, y)と(x+w, y+h))を指定して,その次に色((255, 0, 0) 青色)を指定する.さらにラインの太さ(2)を指定する.
なお,画像の座標は左上が (0, 0) となり,横軸(x座標)は左側が正で縦軸(y座標)は下側が正になる.よって,顔として認識するエリアの左上((x, y))から,右下((x+w, y+h))となる.

続いて,顔と認識した領域から目を検出する.
変数eye_grayに,グレースケールに変換した画像から顔と認識した領域を入れる.
同じようにして,元のカラー画像を変数eye_colorに入れる.
グレースケール画像に対して,eye_cascadeのdetectMultiScaleメソッドを使って目の検出を行う.

17〜18行目
    for (ex, ey, ew, eh) in eyes:
        cv.rectangle(eye_color, (ex, ey), (ex+ew, ey+eh), (02550), 2)
ネストのforループで,目が見つかった場合も,先と同様に検出領域を四角で囲む.
cvのrectangleに引数としてeye_colorを渡して四角で囲む.eye_colorの中の目として認識したエリア(座標(ex, ey)と(ex+ew, ey+eh))を指定して,その次に色((0, 255, 0) 緑色)を指定する.さらにラインの太さ(2)を指定する.

20行目
cv.imshow('img', img)
OpenCVのimgshowメソッドを使って,画像を表示させる.
表示する画像の名前をimgとして,四角の書いてあるimgを上書きする.

21行目
cv.waitKey(0)
OpenCVのwaitKeyメソッドを使って表示する.
0の単位はミリセカンド.

23行目
cv.destroyAllWindows()
OpenCVのdestroyAllWindowメソッドを使って,何らかの入力があった際にウィンドウを閉じることとする.

上記のコードを実行してみた結果は以下のようになりま.

Test1
使用する写真
実行結果
$ python3 image_face_detect.py
3
顔を3つと認識しています.
Daniel Craig(左側)の目は一つだけ,Eva Green(右側)の目は2つ認識しています.

Test2
写真を変えて実行してみます.

実行結果
$ python3 image_face_detect.py
2
顔を2つ認識していて,Daniel Craig(中央)とGemma Arterton(右側)の目は二つ認識していますが,Olga Kurylenko(左側)の顔は認識していません.

Test3
さらに,写真を変えて実行してみます.

実行結果
$ python3 image_face_detect.py
3

顔を3つ認識しています.
Daniel Craig(左)とJavier Bardem(右から2人目)の目は一つ認識しています.またNaomie Harris(右)の顔は認識していますが,目は認識していません.Bérénice Marlohe(左から2人目)の顔は認識していません.

また,写真を変えて実行してみます.
実行結果
$ python3 image_face_detect.py
6
顔を6つ認識しています.
上段では,Ben Whishaw(左)の顔は認識していません.Ralph Fiennes(中央)とAndrew Scott(右)の顔は認識していますが,目は認識していません.中段ではMonica Bellucci(左)とDaniel Craig(中央)の顔は認識していますが,Léa Seydoux(右)の顔は認識していません.下段ではErnst Blofeld(左)とDavid Bautista(右)の顔は認識していますが,Naomie Harris(中央)の顔は認識していません.

0 件のコメント :

コメントを投稿