【Python】OpenCVで顔検出
OpenCVはインストールも簡単で、ひとまず顔検出を試すにはもってこいです。
正面以外の検出精度は微妙ですが、正面の顔を検出するなら十分です。短時間かつ低精度で構わないの場面で用いるのが良いでしょう。
[1] OpenCVのインストール
pip3 install opencv-python --user
上記だけではインポートエラーが発生するため「mesa-libGL」をインストールします。
sudo yum -y install mesa-libGL
詳しくは以下の記事にまとめています。
[2] ソースコード
公式のDocumentationを元に作成しました。
公式の例ではカメラから画像を取り込んでいますが、ここではダウンロード済みの画像を扱う例を紹介します。
import cv2 import os # サンプルデータのパスを追加 homedir = os.path.expanduser('~') cv2dir = '.local/lib/python3.7/site-packages/cv2/' cv2path = os.path.join(homedir, cv2dir) cv2.samples.addSamplesDataSearchPath(cv2path) # サンプル分類器を取得 face_cascade_name = 'data/haarcascade_frontalface_alt.xml' eyes_cascade_name = 'data/haarcascade_eye_tree_eyeglasses.xml' face_cascade = cv2.CascadeClassifier() eyes_cascade = cv2.CascadeClassifier() face_cascade.load(cv2.samples.findFile(face_cascade_name)) eyes_cascade.load(cv2.samples.findFile(eyes_cascade_name)) # 画像を読み込み(imgディレクトリにsample.jpgを置く) imgdir = 'img' imgpath = os.path.join(imgdir, 'sample.jpg') img = cv2.imread(imgpath) # 画像をグレースケールに変換 img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 顔検出 faces = face_cascade.detectMultiScale(img_gray) for face in faces: # 顔検出した領域を赤枠で描画 xf, yf, wf, hf = face cv2.rectangle(img, (xf, yf), (xf+wf, yf+hf), color=(0,0,255), thickness=4) # 顔検出した領域から、目を検出 face_img = img[yf:yf+hf, xf:xf+wf] eyes = eyes_cascade.detectMultiScale(face_img) for eye in eyes: # 目を検出した領域を緑楕円で描画 xe, ye, we, he = eye eye_center = (xf + xe + we//2, yf + ye + he//2) cv2.ellipse(img, eye_center, axes=(we//2, he//2), angle=0, startAngle=0, endAngle=360, color=(0, 255, 0), thickness=4) # 検出領域を示した画像を表示 cv2.imshow('Capture - Face detection', img)
[3] 顔検出の結果
[3-1] 非常に上手くいった例
赤枠が顔検出した領域、緑枠が顔検出した領域内から目を検出した領域です。
これは非常に上手くいった例です。正面の顔であれば、このように高精度で検出してくれます。
[3-2] すこし微妙な例
<Werner HeiberによるPixabayからの画像>
6人中3人を顔検出できています。顔が正面以外の向きだと、検出精度が下がります。
[3-3] 上手くいかない例
5人中1人しか顔検出できていません。顔が正面以外の向きだと、検出精度が下がります。
[4] 補足とトラブルシューティング
[4-1] 検出器の種類
検出器は、OpenCVで用意されたものを利用しています。
Amazon Linux2の環境では/home/{ユーザ名}/.local/lib/python3.7/site-packages/cv2/data
に格納されています。
顔検出以外にも様々な分類器が用意されています。
ls /home/{ユーザ名}/.local/lib/python3.7/site-packages/cv2/data # haarcascade_eye_tree_eyeglasses.xml haarcascade_licence_plate_rus_16stages.xml # haarcascade_eye.xml haarcascade_lowerbody.xml # haarcascade_frontalcatface_extended.xml haarcascade_profileface.xml # haarcascade_frontalcatface.xml haarcascade_righteye_2splits.xml # haarcascade_frontalface_alt2.xml haarcascade_russian_plate_number.xml # haarcascade_frontalface_alt_tree.xml haarcascade_smile.xml # haarcascade_frontalface_alt.xml haarcascade_upperbody.xml # haarcascade_frontalface_default.xml __init__.py # haarcascade_fullbody.xml __pycache__ # haarcascade_lefteye_2splits.xml
各ファイルの役割は下記サイトなど、いくつかのサイトがまとめてくれています。
【Python版OpenCV】Haar Cascadeで顔検出、アニメ顔検出、顔にモザイク処理 | 西住工房
[4-2] 検出器の読込失敗
用意された検出器を読み込もうとすると、ファイルが見つからないエラーが発生します。
face_cascade_name = 'data/haarcascade_frontalface_alt.xml' face_cascade = cv.CascadeClassifier() face_cascade.load(cv.samples.findFile(face_cascade_name)) # OpenCV(4.5.3) /tmp/pip-req-build-l1r0y34w/opencv/modules/core/src/utils/samples.cpp:64: error: (-2:Unspecified error) OpenCV samples: Can't find required data file: data/haarcascade_frontalface_alt.xml in function 'findFile'
cv2.samples.addSamplesDataSearchPath()
で格納先のパスを検索するようにします。
import os homedir = os.path.expanduser('~') cv2dir = '.local/lib/python3.7/site-packages/cv2/' cv2path = os.path.join(homedir, cvdir) cv2.samples.addSamplesDataSearchPath(cv2path)
OpenCV: Utility functions for OpenCV samples
[4-3] 検出器のパラメータ
検出器のパラメータを調整すること精度を高めることができます。
CascadeClassifier.detectMultiScale()
のパラメータを変更します。主なパラメータは次の通りです。
- scaleFactor:各画像スケールにおいて、画像サイズをどれだけ縮小するかを指定するパラメータ。
- minNeighbors:各候補の矩形が保持されるために必要な隣接数を指定するパラメータ。
- minSize:可能なオブジェクトの最小サイズ.これよりも小さいオブジェクトは無視されます.
OpenCV: cv::CascadeClassifier Class Reference
詳細は以下のサイトなどが参考になります。
- [OpenCV] detectMultiScaleの使いかた | Tech控え帳
- 物体検出(detectMultiScale)をパラメータを変えて試してみる(scaleFactor編) | Workpiles
[4-4] 検出の仕組み
Haar特徴に基づくカスケード分類器で顔検出を行なっています。
公式のチュートリアルや以下のサイトが詳しいです。
- OpenCV: Cascade Classifier
- 【入門者向け解説】openCV顔検出の仕組と実践(detectMultiScale) - Qiita
- Haar Cascadeによる顔検出の原理 | 西住工房
終わりに
冒頭で述べた通り、OpenCVはインストールも比較的容易で簡単に顔検出ができました。しかし、精度は少々物足りません。
OpenCVよりも精度の良いライブラリを探してみることにします。
参考文献
- 【入門者向け解説】openCV顔検出の仕組と実践(detectMultiScale) - Qiita
- 【Python版OpenCV】Haar Cascadeで顔検出、アニメ顔検出、顔にモザイク処理 | 西住工房
- [OpenCV] detectMultiScaleの使いかた | Tech控え帳
- 物体検出(detectMultiScale)をパラメータを変えて試してみる(scaleFactor編) | Workpiles
- Python + OpenCVで顔検出を行う
画像の出典
- ゆうせい モデルの紹介 - ぱくたそ
- Werner HeiberによるPixabayからの画像
- Sanu A SによるPixabayからの画像