Python, OpenCVでカスケード型分類器を使った顔検出と瞳検出(顔認識と瞳認識)を行う。
以下に公式のチュートリアル(英語)がある。
· OpenCV: Face Detection using Haar Cascades
ここでは、
· 静止画: 画像ファイルを読み込んで顔検出と瞳検出
· 動画: Webカメラを使ってリアルタイムで顔検出と瞳検出
について説明する。
サンプルコード
まず最初に画像ファイルを読み込んで顔検出と瞳検出を行うサンプルコードを示す。説明およびリアルタイム処理のサンプルコードは後述。
import cv2
face_cascade_path = '/usr/local/opt/opencv/share/'\
'OpenCV/haarcascades/haarcascade_frontalface_default.xml'
eye_cascade_path = '/usr/local/opt/opencv/share/'\
'OpenCV/haarcascades/haarcascade_eye.xml'
face_cascade = cv2.CascadeClassifier(face_cascade_path)
eye_cascade = cv2.CascadeClassifier(eye_cascade_path)
src = cv2.imread('data/src/lena_square.png')
src_gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(src_gray)
for x, y, w, h in faces:
cv2.rectangle(src, (x, y), (x + w, y + h), (255, 0, 0), 2)
face = src[y: y + h, x: x + w]
face_gray = src_gray[y: y + h, x: x + w]
eyes = eye_cascade.detectMultiScale(face_gray)
for (ex, ey, ew, eh) in eyes:
cv2.rectangle(face, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 2)
cv2.imwrite('data/dst/opencv_face_detect_rectangle.jpg', src)
source: opencv_face_eye_detection.py
カスケード型分類器の読み込み
Macにhomebrewでopencv3をインストールした場合、
· /usr/local/opt/opencv/share/OpenCV/haarcascades/
に学習済のHaar-like特徴を用いた分類器のデータ(xmlファイル)がある。
xmlファイルの場所がわからない場合は、GItHubのレポジトリからダウンロードして任意の場所に置いてもいい。
· opencv/data/haarcascades at master · opencv/opencv
以下のようにいくつかの種類のデータが用意されている。
· 正面の顔検出用: haarcascade_frontalface_default.xml
· 瞳検出用: haarcascade_eye.xml
· 笑顔検出用: haarcascade_smile.xml
cv2.CascadeClassifier()
でパスを指定してxmlファイルを読み込む。
detectMultiScaleで検出
読み込んだ検出器のメソッドdetectMultiScale()
で顔や瞳(目)などを検出する。
検出領域の(
左上の点の
x
座標
, y
座標
,
幅
,
高さ
)
のリスト(配列)が返される。
· OpenCV: cv::CascadeClassifier Class Reference
上のサンプルコードでは、まず顔を検出し、その顔に対して瞳(目)の検出をしている。
引数としてグレースケール(白黒)の画像データを渡す。カラー画像からグレースケール(白黒)画像への変換はcv2.cvtColor()
で行う。
そのほか以下のような引数を指定できる(省略可能)。
· scaleFactor
(初期値1.1)
· minNeighbors
(初期値3)
detectMultiScale()
では様々なスケールで検出を行うが、それぞれのスケールの縮小量を定義するのがscaleFactor
。
scaleFactor
の値が小さいとスケールを細かく変更して検出するため、見落としは少ないが処理時間がかかる。
また様々なスケールで検出した結果、同じエリアで重複して検出される。いくつ重複した場合に真とみなすかを定義するのがminNeighbors
。
minNeighbors
の値が小さいと重複が少ない領域も真とするため、見落としは少ないが誤検出が増える。
scaleFactor
もminNeighbors
も対象となる画像や使用する検出器のデータなどによって最適な値は異なるが、基本的には初期値のままでもある程度は検出できる。
検出領域に対して処理(枠描画、塗りつぶし、モザイク)
上のサンプルコードでは、cv2.rectangle()
で検出した領域の枠を描画している。
図形描画については以下の記事を参照。
· 関連記事: Python, OpenCVで図形描画(線、長方形、円、矢印、文字など)
検出した領域を塗りつぶす場合はcv2.rectangle()
で塗りつぶしてもいいし、以下のようにも書ける。
faces = face_cascade.detectMultiScale(src_gray)
for x, y, w, h in faces:
src[y: y + h, x: x + w] = [0, 128, 255]
cv2.imwrite('data/dst/opencv_face_detect_fill.jpg', src)
source: opencv_face_eye_detection.py
検出した領域にモザイクをかけたりすることもできる。
faces = face_cascade.detectMultiScale(src_gray)
ratio = 0.05
for x, y, w, h in faces:
small = cv2.resize(src[y: y + h, x: x + w], None, fx=ratio, fy=ratio, interpolation=cv2.INTER_NEAREST)
src[y: y + h, x: x + w] = cv2.resize(small, (w, h), interpolation=cv2.INTER_NEAREST)
cv2.imwrite('data/dst/opencv_face_detect_mosaic.jpg', src)
source: opencv_face_eye_detection.py
モザイク処理についての詳細は以下の記事を参照。
· 関連記事: Python, OpenCVで画像にモザイク処理(全面、一部、顔など)
Webカメラを使ってリアルタイムで顔検出と瞳検出
以前、Macの内蔵カメラでキャプチャした動画をリアルタイムで処理した。
· 関連記事: Python, OpenCVでMacBook ProのFaceTime HD Cameraの動画を処理
カメラでキャプチャした各フレームに対して上述の画像ファイルでの処理を行えば、リアルタイムで顔検出や瞳検出をすることができる。
サンプルコードは以下の通り。
import cv2
face_cascade_path = '/usr/local/opt/opencv/share/'\
'OpenCV/haarcascades/haarcascade_frontalface_default.xml'
eye_cascade_path = '/usr/local/opt/opencv/share/'\
'OpenCV/haarcascades/haarcascade_eye.xml'
face_cascade = cv2.CascadeClassifier(face_cascade_path)
eye_cascade = cv2.CascadeClassifier(eye_cascade_path)
cap = cv2.VideoCapture(0)
while True:
ret, img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)
for x, y, w, h in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
face = img[y: y + h, x: x + w]
face_gray = gray[y: y + h, x: x + w]
eyes = eye_cascade.detectMultiScale(face_gray)
for (ex, ey, ew, eh) in eyes:
cv2.rectangle(face, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 2)
cv2.imshow('video image', img)
key = cv2.waitKey(10)
if key == 27: # ESCキーで終了
break
cap.release()
cv2.destroyAllWindows()
source: opencv_face_eye_detection_camera.py