前回の記事のとおり、Anaconda環境でOpenCVを使えるようになったので、早速顔認識のプログラムを書いてみた。
結果、予想以上に簡単だったので、コードの解説を交えながら紹介しよう。
コンテンツ
フリー素材サイトから写真を用意
「ぱくたそ」から人物写真をダウンロードした。
今回用意した写真は以下のリンクからダウンロードできる。
https://pakutaso.com/20140912244post-4510.html
画像の読み込み
まずはOpenCVをインポートし、用意した画像を読み込む。
今回はメインとなるPythonファイルと同じディレクトリに「sample_img.jpg」というファイル名で画像を保存した。
import cv2
image = cv2.imread('sample_img.jpg')
GitHubから顔検出用の学習済みモデルをダウンロード
次に、顔検出のために必要な学習済みモデルをGitHubからダウンロードする。
https://github.com/opencv/opencv/tree/master/data/haarcascades
たくさんのファイルが並んでいるが、今回は下記の赤枠で囲った「haarcascade_frontalface_alt2.xml」をダウンロードする。
ダウンロードは上記のリンクをクリックし、「Raw」ボタンをクリック。
そしてブラウザの「ファイルを保存」(Mac Chromeの場合Cmd + S)で、作業ディレクトリに保存すればOKだ。
分類器の用意
ダウンロードしたモデルを使って、次は分類器を用意する。
cascade_file = 'haarcascade_frontalface_alt2.xml'
cascade_face = cv2.CascadeClassifier(cascade_file)
CascadeClassifier関数でモデルファイルを読み込むだけだ。
顔検出処理を実行
先ほど用意した分類器cascade_faceのdetectMultiScale関数を実行すると、見つかった顔の位置(左上x, y座標)と、顔のサイズ(w, h)が配列として返される。
# 顔を探して配列で返す
face_list = cascade_face.detectMultiScale(image, minSize=(20, 20))
ここまでのコードを実行してみると、次の結果が返ってくる。
print(face_list)
# [[752 239 167 167]
# [546 337 128 128]]
検出された顔に枠をつけて画像を保存する
いよいよ最終の処理に入る。
for (x, y, w, h) in face_list:
border_color = (0, 0, 255)
border_size = 2
cv2.rectangle(image, (x, y), (x+w, y+h), border_color, thickness=border_size)
cv2.imwrite('out.jpg', image)
行っていることはそれほど難しくはない。
border_colorはBGR形式で色を指定している。
OpenCVはよくあるRGBと異なり、BGRとなっているので注意が必要だ。
border_sizeは枠線のサイズを指定。
rectangleの第一引数には画像を、第二引数に枠線の開始点(左上座標)、第三引数に終了点(右下座標)、第四引数に線色、thicknessに線の太さをそれぞれ指定している。
最後にimwrite関数で任意のファイル名で画像を保存すればプログラム完成だ。
早速ターミナルで完成したPythonファイルを実行してみよう。
作業ディレクトリに新しく「out.jpg」が生成され、見事に顔に赤い枠線が描かれているはずだ。
コード全文
import cv2
image = cv2.imread('sample_img.jpg')
cascade_file = 'haarcascade_frontalface_alt2.xml'
cascade_face = cv2.CascadeClassifier(cascade_file)
# 顔を探して配列で返す
face_list = cascade_face.detectMultiScale(image, minSize=(20, 20))
for (x, y, w, h) in face_list:
border_color = (0, 0, 255)
border_size = 2
cv2.rectangle(image, (x, y), (x+w, y+h), border_color, thickness=border_size)
cv2.imwrite('out.jpg', image)