概要
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())
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)
正しく顔の位置が抽出できている。
認識できるのは人間の顔のみ。たとえば以下のような犬の画像。
dog = cv2.imread('dog.jpg')
dog = cv2.cvtColor(dog, cv2.COLOR_BGR2RGB)
plt.imshow(dog)
これに対して実行しても顔は検出されない。
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)
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)
改定履歴
Author: Masato Watanabe, Date: 2019-05-01 記事投稿