#1. 背景
現在,私はディープラーニングを用いて,顔を認識するプログラムを作成している.まず,学習データとして,大量の顔画像を用意した.この際,人物が映った画像から,顔を検出し,顔の部分だけを切り取る処理をした.このうち,顔を検出する手法として,カスケード分類器を用いた.この記事では,カスケード分類器について説明する.
#2.カスケード分類器とは
カスケード分類器は,複数の単純な分類器によって構成される分類器である.対象画像に対し,これらの単純な分類器が順番に適用される.すべての分類器を通過したら,検出される.一方で,単純な分類器に1回でも拒否されたら,その時点で検出はされない.よって,検出対象に明らかに該当しない画像は初期の段階で拒否されるため,高速である.
OpenCVでは,HAAR-Like特徴量を使ったカスケード分類器が用意されている.
OpenCVのcascadeファイル
https://github.com/opencv/opencv/tree/master/data/haarcascades
HAAR-Like特徴量とは,画像の明暗による特徴量である.画像の局所領域における白領域と黒領域の差を特徴としている.よって,画像をグレースケールに変換してから用いるのが一般的である.
3.OpenCVにおけるカスケード分類器
OpenCVにおいては,カスケード分類器が含まれるcascadeファイルを読み込んだ後,detect.MultiScake()によって検出を行う.detect.MultiScake()の返り値はN×4行列となっていてNは検出した数,4は[x,y,width,height]の4要素である.この4要素は,検出した領域を矩形で囲んだ範囲である.xが矩形の左上のx座標,yが矩形の左上のy座標,widthが矩形の幅,heightが矩形の高さである,よって,検出した部分に印を付けたい場合は,OpenCVの描画関数rectangle()を用いて,rectangle(image,(x,y),(x+width,y+height),(255,0,0),2)などと書けば良い.
以下の画像に対して,試してみる.
ソースコードを以下に示す.
import cv2
#画像を読み込む
image = cv2.imread('sample.jpg')
#画像をグレースケールに変換する
image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
#ファイルから分類器を読み込む
cascade = cv2.CascadeClassifier("/opencv/data/haarcascades/haarcascade_frontalface_alt.xml")
#分類器を用いて検出を行う
faces = cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1))
#detectMultiScale()の返り値を出力する(確認用)
print(faces)
#検出した顔画像の部分を矩形でマークする
for (x,y,width,height) in faces:
cv2.rectangle(image,(x,y),(x+width,y+height),(255,0,0),2)
#画像を表示する
cv2.imshow('result',image)
cv2.waitKey(0)
cv2.destroyAllWindows()
実行結果は以下のようになった.1個だけ誤認識があるが,顔は全て検出できている.
ちなみに,detectMultiScale()の返り値を出力したので,出力結果も見てみると...
上のように,検出された領域(矩形)における,左上の座標,幅,高さの情報が返されている.
#4.余談
前回の記事では,imreadで返される配列を利用して,画像から一部分だけを切り取る手法を学んだ.
[OpenCV]imreadで返される配列について
https://qiita.com/Castiel/items/53ecbee3c06b9d92759e
そして,今回は顔を検出する手法を学んだ.これらを利用すれば,ディープラーニングにおける,顔画像の学習データを集められるはずだ.今度は,顔画像の学習データを作成することに取り組もうと思う.