6,115 views
この記事は最終更新から 1646日 が経過しています。
1. やりたいこと
Pythonで OpenCVの第 6回目、今回は OpenCVの Haar Cascades を使って写真から顔検出して遊んでみる。
敢えて「遊んでみる」と書いたのは、原理的な所を学習せずに顔検出機能を使ってみるだけだから…
2. 前準備
(1) 顔の写った写真を用意する。
顔検出に使った写真をこのブログに掲載するので、以下の条件を満たしている必要がある。
・自分や知り合いの顔が写っている写真はダメだ。
・ライセンス上の問題が発生する写真はダメだ。
ということで CC0ライセンス画像を使うことにする。
pixabay
(2) OpenCVで使用する学習済みデータを入手する。
こちらから入手する。
https://github.com/opencv/opencv
この中から以下の2ファイルを使用する。
・opencv/data/haarcascades/haarcascade_eye.xml
・opencv/data/haarcascades/haarcascade_frontalface_default.xml
3. やってみる
基本的にはこちらのチュートリアルのまんま書いて遊んでみる。
Face Detection using Haar Cascades
(1) まずは顔だけを抽出してみる。
import numpy as np import cv2 as cv # 顔検出対象の画像をロードし、白黒画像にしておく。 imgS = cv.imread('face.png') imgG = cv.cvtColor(imgS, cv.COLOR_BGR2GRAY) # 学習済みデータをロード face_cascade = cv.CascadeClassifier('haarcascade_frontalface_default.xml') # 顔検出を実行 faces = face_cascade.detectMultiScale(imgG, 1.3, 5) # 顔検出箇所を矩形で囲む。 for (x,y,w,h) in faces: cv.rectangle(imgS,(x,y),(x+w,y+h),(0,255,255),2) # 表示 cv.imshow('image',imgS) cv.waitKey(0) # 表示消去 cv.destroyAllWindows()
斜め後ろから見ている人を除き 5人を検出できた。
(2) 次に顔の中から目を検出してみる。
import numpy as np import cv2 as cv # 顔検出対象の画像をロードし、白黒画像にしておく。 imgS = cv.imread('face.png') imgG = cv.cvtColor(imgS, cv.COLOR_BGR2GRAY) # 学習済みデータをロード face_cascade = cv.CascadeClassifier('haarcascade_frontalface_default.xml') eye_cascade = cv.CascadeClassifier('haarcascade_eye.xml') # 顔検出を実行 faces = face_cascade.detectMultiScale(imgG, 1.3, 5) # 顔検出箇所を矩形で囲む。 for (x,y,w,h) in faces: cv.rectangle(imgS,(x,y),(x+w,y+h),(0,255,255),4) # 目を検出 imgG_face = imgG[y:y+h, x:x+w] imgC_face = imgS[y:y+h, x:x+w] eyes = eye_cascade.detectMultiScale(imgG_face) for (ex,ey,ew,eh) in eyes: cv.rectangle(imgC_face,(ex,ey),(ex+ew,ey+eh),(0,128,255),4) # 表示 cv.imshow('image',imgS) cv.waitKey(0) # 表示消去 cv.destroyAllWindows()
口を誤検出しているが概ね良好な結果かも。
4. おまけ
(1) 検出パラメーターを変更してみる。
(scaleFactor, minNeighbors) = (1.1, 3)
(scaleFactor, minNeighbors) = (1.1, 5)
(scaleFactor, minNeighbors) = (1.3, 3)
(scaleFactor, minNeighbors) = (1.3, 5)
(scaleFactor, minNeighbors) = (2.0, 3)
(scaleFactor, minNeighbors) = (2.0, 5)
(2) 検出した顔をファイル保存する。
検出した顔をくり抜いて PNGファイルに保存してみる。
import numpy as np import cv2 as cv import os, shutil imgS = cv.imread('face2.jpg') imgG = cv.cvtColor(imgS, cv.COLOR_BGR2GRAY) face_cascade = cv.CascadeClassifier('haarcascade_frontalface_default.xml') faces = face_cascade.detectMultiScale(imgG, 1.1, 3) img_out_path = './out' if os.path.exists(img_out_path): shutil.rmtree(img_out_path) os.mkdir(img_out_path) i = 1 for (x,y,w,h) in faces: cv.rectangle(imgS,(x,y),(x+w,y+h),(0,255,255),4) imgC_face = imgS[y:y+h, x:x+w] fpath = img_out_path + '/face_%05d.png' % i cv.imwrite(fpath, imgC_face) i = i + 1
こんな感じで切り抜けた。
当然だが誤検出した物も PNGファイル出力されている。
人間であれば「これ顔じゃないだろ」ってすぐに判別できる物でも、機械は顔と認識してしまう。
スピードと精度のトレードオフだ。
商用の顔認識モジュールの精度がどれほどのものなのか気になるなぁ…
5. 所感
いつかちゃんとアルゴリズムを学習しよう。
特徴点を抽出し、マッチングし、なのだとは思うが。