Raspberry Pi Python版OpenCVによる顔検出

Python版OpenCVで顔検出

2017年9月、Raspberry PiでPython版OpenCVを用いて顔検出するPythonスクリプトを作成しました。

USBカメラから画像を入力して顔検出し、顔検出枠を付加して描画します。また、フレームレートを計測して画面に表示しました。フレームレート計測は、下記を参照してください。

Raspberry Pi Python版OpenCVによるフレームレート算出方法

顔検出

顔検出


PythonとOpenCVのバージョンを確認します。

  • Python : 2.7.13
  • OpenCV : 3.3.0
$ python
Python 2.7.13 (default, Jan 19 2017, 14:48:08)
[GCC 6.3.0 20170124] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> print cv2.__version__
3.3.0
>>> quit()

顔検出スクリプト

顔検出するPythonスクリプトを下記に示します。

$ cat cvface.py
#!/usr/bin/python
# -*- coding: utf-8 -*-

import cv2
import fps

cascade_file = "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml"

cascade = cv2.CascadeClassifier(cascade_file)    # ■ 識別器読み込み

gFrameRate = fps.FrameRate()            # フレームレート初期化

fontcolor = (255,255,255)
fontface  = cv2.FONT_HERSHEY_SIMPLEX
fontthick = 2

cap = cv2.VideoCapture(0)
cap.set( cv2.CAP_PROP_FRAME_WIDTH  , 320 )
cap.set( cv2.CAP_PROP_FRAME_HEIGHT , 240 )

while( cv2.waitKey(1) < 0 ):

    ret, ImgFrame = cap.read()                              # カメラ入力
    ImgGray = cv2.cvtColor(ImgFrame, cv2.COLOR_RGB2GRAY)    # グレースケール画像に変換

    # ■ 顔検出
    FaceList = cascade.detectMultiScale( ImgGray, scaleFactor=1.1, minNeighbors=2, minSize=(20,20))

    for face in FaceList:
        (x, y, w, h) = face
        cv2.rectangle(ImgGray, (x,y), (x+w, y+h), (255,0,0), 2)   # 顔枠表示

    fps = gFrameRate.get()                 # フレームレート取得
    fps_str = '%4d' % fps
    cv2.putText(ImgGray, fps_str, (10,25), fontface, 1.0, fontcolor, fontthick , cv2.LINE_AA)
    cv2.imshow('Face Detect',ImgGray)

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

「cascade = cv2.CascadeClassifier(cascade_file)」で、正面顔検出用の学習済み識別器カスケードを読み込みます。

「cv2.VideoCapture(0)」で、VideoCaptureクラスをインスタンス化して、インスタンス cap を生成します。「cap.set( )」で、画像サイズ CAP_PROP_FRAME_WIDTH(幅)と CAP_PROP_FRAME_HEIGHT(高さ)を設定します。

「ImgFrame = cap.read()」で、キャプチャーデバイスから次のフレームを取得・デコードして、ImgFrameに格納します。

「ImgGray = cv2.cvtColor()」で、グレースケール画像に変換します。

「cascade.detectMultiScale()」で、グレースケール画像から顔検出して、FaceListに検出結果を格納します。

FaceList = cascade.detectMultiScale(
     ImgGray, scaleFactor=1.1, minNeighbors=2, minSize=(20,20))

  • scaleFactor : 各画像スケールにおける縮小量
  • minNeighbors : 信頼性のパラメーターで、物体候補となる矩形の最小近傍矩形数
  • minSize : 物体が取り得る最小サイズ

検出結果 FaceList は、複数の顔検出結果をリスト構造にしたものです。たとえば、3つの顔を検出した場合は次のようになります。

[ [166 24 44 44]
[257 93 51 51]
[180 106 52 52] ]

ひとつのリストは、[x, y, w, h]の値です。顔枠は、(x,y)と(x+w, y+h)を対角線とする矩形を「cv2.rectangle(ImgGray ・・・)」で描画します。

「cv2.imshow( )」で、ウインドウFace DetectにImgGrayの画像を表示します。

顔検出の実行

OpenCVのサンプル画像( /opencv-3.3.0/samples/data/lena.jpg )を使用します。

lena画像

lena画像

lena画像を3つ(100% , 75% , 53%)表示して、そのモニター画像をカメラで撮影して顔を検出します。その結果、3つのlena画像を顔認識することができました。

顔検出

顔検出

フレームレートは、5~10fps程度で動作しました。やはり顔検出は、重たい処理です。

CPU温度警告

CPU温度警告

画面の右上を見ると、見慣れない温度計マークが表示されました。

顔検出処理でCPU負荷が上がり、CPU温度が高くなったという警告らしいです。