iMind Developers Blog

iMind開発者ブログ

OpenCVとdlibによるFace Detection(顔認識)

概要

Face DetectしたかったのでOpenCVとdlibをそれぞれサンプルコードを動かす。

バージョン情報

  • Python 3.7.3
  • dlib==19.17.0
  • OpenCV==3.4.2

インストール

condaで仮想環境作ってOpenCVとdlibを導入する。

pipとかjupyterとかscikit-imageとか他に使いそうなものも一緒に入れておく。

$ conda create -n image-proc pip jupyter matplotlib scikit-image
$ source activate image-proc
$ conda install -n image-proc -c menpo opencv

dlibの導入にcmakeがいるので入れておく。下記はUbuntuの場合。

$ sudo apt install cmake

dlibをpipで入れる。condaでバージョン指定せずに入れるとPython2.7に戻るとか何かしらあった。

$ pip install dlib

OpenCVによる顔認識

haarcascade_frontalface_alt.xml というファイルが必要になる。

condaで入れた場合は share/OpenCV/haarcascades 配下にあるか site-packages/cv2 配下にあるのでcurrent directoryにコピーしておく。

顔検出する例としてscikit-imageのastronautの画像を使う。

import skimage
from matplotlib import pylab as plt

plt.imshow(skimage.data.astronaut())

f:id:imind:20190501004312p:plain

OpenCVのCascadeClassifierを使って顔認識を実行する。

import cv2

# モデルの読込み
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')

# 対象画像データ
img = skimage.data.astronaut()

# 顔認識
faces = face_cascade.detectMultiScale(img)

print(faces)
    #=> [[176  65 100 100]]

戻り値は x座標, y座標, width, height の4つ。複数の顔が検知されることもある。

取得した座標をRectangleで囲って画像を表示する。

for face in faces:
    img = cv2.rectangle(img, tuple(face[0:2]), tuple(face[0:2] + face[2:4]), (255, 0, 0), 3)
plt.imshow(img)

f:id:imind:20190501011028p:plain

正しく顔の位置が抽出できている。

認識できるのは人間の顔のみ。たとえば以下のような犬の画像。

dog = cv2.imread('dog.jpg')
dog = cv2.cvtColor(dog, cv2.COLOR_BGR2RGB)
plt.imshow(dog)

f:id:imind:20190501011834p:plain

これに対して実行しても顔は検出されない。

faces = face_cascade.detectMultiScale(dog)
print(faces)
    #=> ()

パラメータのscaleFactorやminNeighborsを小さくすると検出の条件がゆるくなる。下記はゆるゆるの条件。

img = skimage.data.astronaut()
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
faces = face_cascade.detectMultiScale(img,
            scaleFactor=1.01, minNeighbors=1)
for face in faces:
    top_left = tuple(face[0:2])
    bottom_right = tuple(face[0:2] + face[2:4])
    red = (255, 0, 0)
    img = cv2.rectangle(img, top_left, bottom_right, red, 3)
plt.imshow(img)

f:id:imind:20190501022017p:plain

dlibによる顔認識

続いてdlibでの実行。

import dlib

detector = dlib.get_frontal_face_detector()
img = skimage.data.astronaut()
faces = detector(img, 0)
print(faces)
    #=> rectangles[[(179, 83) (266, 170)]]

dlibのrectangles型で結果が返っている。

tol_cornerでレクタングルの左上の座標、br_cornerで右下の座標が取れる。

for face in faces:
    top_left = face.tl_corner()
    top_left = (top_left.x, top_left.y)
    bottom_right = face.br_corner()
    bottom_right = (bottom_right.x, bottom_right.y)
    img2 = cv2.rectangle(img, top_left, bottom_right, (255, 0, 0), 3)
plt.imshow(img2)

f:id:imind:20190501115643p:plain

改定履歴

Author: Masato Watanabe, Date: 2019-05-01 記事投稿