カメラで顔認識

・ここでは、べゼリーに内蔵したカメラで人間の顔を認識させてみます。

・顔の認識にはオープンソースの画像処理ライブラリ「Open CV(Open Source Computer Vision Library)」を使います。

準備

・まずはPython3にOpen CVをインストールする必要があります。pythonやRaspbianのバージョンによっては巧くいかないかもしれません。不幸にもエラーがでてしまった場合は、済みませんが当方では対応しきれませんので、頑張ってググってみてください。なお、あくまでPython2ではなくPython3にインストールしなければならないので注意が必要です。

・筆者の環境の場合は以下のコマンドでインストールができておりますが、恐縮ながら動作保証はできません。

$ sudo apt-get install libhdf5-dev libhdf5-serial-dev libhdf5-100
$ sudo apt-get install libqtgui4 libqtwebkit4 libqt4-test python3-pyqt5
$ sudo apt-get install libatlas-base-dev
$ sudo apt-get install libjasper-dev
$ sudo pip3 --default-timeout=1000 install opencv-python

・「ラズパイカメラ」をクリアした状態(ラズパイカメラを接続し、HDMIディスプレイが接続された状態)にしておいてください。

サンプルプログラム sample_face1.py

・パソコンからの遠隔操作だと動画が表示されないことがあるので、ラズパイに直接つなげたキーボードとディスプレイで実行してください。(回避手段はありますが、ここでは説明しません)

$ python3 sample_face1.py

・ディスプレイに表示されているカメラ画像の中に顔(のようなもの)が収まると、赤い四角が表示され、ディスプレイに「顔を発見」と表示されるはずです。顔が画面からはみ出ていたり、傾いていたり、遠すぎると反応しません。
・終了したいときはキーボードの「q」ボタンを押してください。

ソースコード
#!/usr/bin/env python3
# -- coding: utf-8 --
# Bezelie Sample Code : Face Recognition Test
 import picamera                        # カメラ用モジュール
 import picamera.array                  # カメラ用モジュール
 import cv2                             # Open CVモジュール    
 import bezelie                         # べゼリー専用サーボ制御モジュール

 cascade_path =  "haarcascade_frontalface_alt.xml" # 顔認識xml
 cascade = cv2.CascadeClassifier(cascade_path)

# サーボの準備
 bez = bezelie.Control()               # べゼリー操作インスタンスの生成
 bez.moveCenter()                      # サーボをセンタリング
 
#メインループ
 def main():
   with picamera.PiCamera() as camera:                         # Open Pi-Camera as camera
     with picamera.array.PiRGBArray(camera) as stream:         # Open Video Stream from Pi-Camera as stream
       camera.resolution = (640, 480)                          # Display Resolution
       camera.hflip = True                                     # Vertical Flip 
       camera.vflip = True                                     # Horizontal Flip
       while True:
         camera.capture(stream, 'bgr', use_video_port=True)    # Capture the Video Stream
         gray = cv2.cvtColor(stream.array, cv2.COLOR_BGR2GRAY) # Convert BGR to Grayscale
         facerect = cascade.detectMultiScale(gray,             # Find face from gray
           scaleFactor=1.9,                                    # 1.1 - 1.9 :the bigger the quicker & less acurate 
           minNeighbors=3,                                     # 3 - 6 : the smaller the more easy to detect
           minSize=(80,120),                                  # Minimam face size 
           maxSize=(640,480))                                  # Maximam face size
         if len(facerect) > 0:
           for rect in facerect:
             cv2.rectangle(stream.array,                       # Draw a red rectangle at face place 
               tuple(rect[0:2]),                               # Upper Left
               tuple(rect[0:2]+rect[2:4]),                     # Lower Right
               (0,0,255), thickness=2)                         # Color and thickness
           print ("顔を発見")
         cv2.imshow('frame', stream.array)                     # Display the stream
         bez.movePitch (1, 0)
         if cv2.waitKey(1) & 0xFF == ord('q'):                 # Quit operation
           break
         stream.seek(0)                                        # Reset the stream
         stream.truncate()
       cv2.destroyAllWindows()
 
if name == "main":
   main()
解説

・9~10行目:顔認識のための分類器を読み込んでいます。
・24行目:カメラの画像をRGBでキャプチャーしています。
・25行目:RGB動画をグレースケールに変換しています。
・26~30行目:顔を認識しています。
・31~37行目:顔が見つかった場合の処理です。

応用

・27~30行目が顔を認識するためのパラメータです。いろいろ数値をいじってみましょう。例えばminSizeは顔として認識する最低のサイズですので、これを小さくすると、遠くの顔も認識されるようになります。そのかわり、壁に貼ってある写真など、顔じゃないものを誤認識する確率が上がってしまうかもしれません。


応用プログラム demo_face1.py

顔認識プログラムを改造したものが以下のプログラムになります。ランダムで向きを変え、顔を認識したら喋ります。セリフリスト「data_faceDialogJ.csv」を書き換えることでセリフを変えることもできますので、店頭やブースや受付に置いたりすると、客寄せになるのではないかと思います。

python3 demo_face1.py