カタカタブログ

SIerで働くITエンジニアがカタカタした記録を残す技術ブログ。Java, Oracle Database, Linuxが中心です。たまに数学やデータ分析なども。

PythonとOpenCV 3でPCのビデオカメラでリアルタイム顔認識してみた

はじめに

Pythonを最近触り始めているので、いまさらながらOpenCV3を使ってPCのWebカメラから顔認識をやってみる。
環境はMac上でanacondaでPython 3.6環境を作っているので、その上で検証する。

環境は以下の通り。

  • Mac: Sierra - バージョン10.12.6
  • Python: 3.6
  • OpenCV: 3.3.0

OpenCV 3インストール

まずはcondaでインストールしようとしたが、普通にsearchすると2系が出て来る。

$ conda search opencv
Fetching package metadata .............
opencv                       2.4.8                np17py27_2  defaults

調べたところ、3系はcondaの場合はここから入れられるようだったので、-cオプションを付けてインストールしてみる。
https://anaconda.org/menpo/opencv3

$ conda install -c menpo opencv3
Fetching package metadata ...............
Solving package specifications: .

UnsatisfiableError: The following specifications were found to be in conflict:
  - opencv3 -> python 2.7*
  - python 3.6*
Use "conda info <package>" to see the dependencies for each package.

エラー。
さらに調べたところ、menpoのopencvは、現在(2017/10/22)Python3.6に対応したものにまだなっていないらしい。
また、以下の場所からでも3.6対応済みのopencv3が入れられるようだったので、こちらから入れてみる。

$ conda install -c conda-forge opencv 

今度は正常に終了した。

$ conda list opencv
# packages in environment at /anaconda:
#

opencv                    3.3.0           py36_blas_openblas_200  [blas_openblas]  conda-forge

OpenCV3がインストールできた。

OpenCVの顔認識チュートリアルをやってみる

チュートリアルがここにあるので、ここのサンプルコードをそのまま動かしてみる。
https://docs.opencv.org/trunk/d6/d00/tutorial_py_root.html
顔認識のチュートリアルはこちら。
https://docs.opencv.org/trunk/d7/d8b/tutorial_py_face_detection.html

顔認識のためにはOpenCVで標準で付属している識別器を使う。Haar 特徴量にもとづくCascade 識別器ということで、haarcascadesフォルダ以下にxmlファイルとして容易されているのが、mac上のcondaで導入した場合は以下のパスにファイルがあった。

/anaconda/share/OpenCV/haarcascades

チュートリアルで使う以下の二つをプロジェクトフォルダにコピーしておく。顔認識用と、目を認識するための識別器となっている。

haarcascade_frontalface_default.xml
haarcascade_aarcascade_eye.xml

まずサンプル通りのコードを静的なファイルに対して実行する。
画像処理のサンプルデータとしておなじみのlena画像ファイルをプロジェクトフォルダにコピーしておき、それに対して実行した。

import numpy as np
import cv2
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
img = cv2.imread('lena.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
    cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
    roi_gray = gray[y:y+h, x:x+w]
    roi_color = img[y:y+h, x:x+w]
    eyes = eye_cascade.detectMultiScale(roi_gray)
    for (ex,ey,ew,eh) in eyes:
        cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
        cv2.imshow('img',img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

実行するとこのように、顔と目が認識されていることが分かる!
f:id:osn_th:20171022100304p:plain

PCのビデオカメラでリアルタイム顔認識をやってみる

続いて、静的な画像ファイルではなく、PC本体のカメラから動的に顔認識を行ってみる。

基本的なコードは先ほどのものをベースに、ビデオキャプチャを行うcv2.VideoCaptureで画像を取得し、キーボードのqが押されるまでカメラから取得した画像に対して先ほどの顔と目の認識を行い続ける。

import numpy as np
import cv2
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
cap = cv2.VideoCapture(0)
while(True):
    ret, img = cap.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    for (x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
        roi_gray = gray[y:y+h, x:x+w]
        roi_color = img[y:y+h, x:x+w]
        eyes = eye_cascade.detectMultiScale(roi_gray)
        for (ex,ey,ew,eh) in eyes:
            cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
            cv2.imshow('img', img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

これを実行するとカメラが起動するので、自分の顔に対して正しく認識がうまくいくことを確認できる。
以下は、私がジョン・F・ケネディ博物館に行ったときにおみやげで買ってきた、アメリカ歴代大統領の顔写真のシートである。わかりづらいが、シートを直接持ってPCのカメラに写しているところ。

f:id:osn_th:20171022100312p:plain
中央のケネディ大統領は問題なく顔と目が認識でき、それ以外の大統領も全てではないが、いくつかの顔認識がうまくいっている(ちょっと外しているものもあるが)。さすがに目は小さくて取れなかったよう。

まとめ

PythonからOpenCV3の顔認識を試してみた。かなり簡単に実装でき、カメラからの動的な画像に対しても処理できているので、Raspberry Piのカメラとかでリアルタイムにやることとかも色々できそう。

以上!