前回、カラートラッキング物体追尾カメラを作成しました。↓
今回はOpen CVの顔認識を使って、それを追従するカメラをRaspberry Piで作りたいと思います。
前回同様、Open CVのコードにつきましては先人の方々の作品を参考にさせて頂きました。(いかんせんOpen CVは、初学者にとって理解するのに時間がかかる。身をもって体験した。。)
顔認識だけなら、意外とすんなり出来るのですが(ライブラリのおかげで)、それに「カメラ追従」が加わるとちょっと何言ってるか分からなくなります。なんとなくは分かるんですが、理解できた!とは決してならないですね。。継続して勉強が必要ですね。
それでは、内容をまとめていこうかと思います。
初めに
システムの概要
※Open CVはインストール済みということが前提で進めます。インストールについては冒頭に張っているリンクの過去記事でまとめています。
おおまかな動作の流れとしては、下記のような感じのものを作ります。
raspberry pi4 ⇒ i2c ⇒ pca9685 ⇒ サーボモーター
pythonプログラムを作成し、カメラの顔認証に合わせたカメラ軸の位置をOpen CVとPCA96852ライブラリで決めてサーボモータドライバへ伝え、サーボモーターを駆動させます。
ちなみにカメラは、ラズパイ純正のカメラモジュールでも、USBカメラでも両方OKです。
カスケード分類器の準備
顔認証させるには、カメラに映った人間の顔を「人間の顔」と判別させるために、多くの人間の顔のデータを機械学習させて、それと比較させる必要があります。この比較できるデータをカスケード分類機と呼びます。
Open CVにはあらかじめこのデータが準備されているので、簡単なテストならばとりあえず人間の顔については機械学習させる必要はありません。データさえ手に入ればOKです。したがって、まずはそのデータをDLしておきます。
データはgit hubに公開されているので、下記コマンドで手に入れます。
1 |
git clone https://github.com/opencv/opencv.git |
opencv-master 名のディレクトリがDLされるので、その配下にある「haarcascade_frontalface_alt.xml」へのパスを覚えておきます。
opencv-master /data/haarcascades/ haarcascade_frontalface_alt.xml
このパスは後ほど作成するプログラムで使用します。
顔認証のみのプログラム
python
以下、RaspBerry Pi &Python開発ブログさまのサイトを参考にさせていただきました。顔認証のみのプログラムになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import numpy as np import cv2 # 学習済みモデルを読み込む faceCascade = cv2.CascadeClassifier('/home/pi/face/model/opencv-master/data/haarcascades/haarcascade_frontalface_default.xml') # カメラで動画を撮影する カメラ1台の場合は引数に0 or -1を設定する cap = cv2.VideoCapture(0) cap.set(3,640) # 横幅を設定 cap.set(4,480) # 縦幅を設定 while True: # フレーム毎にキャプチャする ret, img = cap.read() # 顔検出の負荷軽減のために、キャプチャした画像をモノクロにする gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 顔検出のパラメータの設定 faces = faceCascade.detectMultiScale( gray, scaleFactor=1.2, minNeighbors=5, minSize=(20, 20) ) # 顔検出時に四角い枠を表示 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] # imshow関数で結果を表示する cv2.imshow('video',img) # ESCが押されたら終了する k = cv2.waitKey(30) & 0xff if k == 27: break cap.release() cv2.destroyAllWindows() |
カスケード分類機へのパスは、ご使用の環境に合わせて適宜変更してください。
こんな感じで、しっかり顔認証ができています。↓
続いて、これにカメラ追従を付け足したいと思います。
顔認証+カメラ追従のプログラム
Python
以下、上記のプログラムを参考にカメラ追従のプログラムを追加した、顔認証+カメラ追従のプログラムになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
import numpy as np import cv2 import time import Adafruit_PCA9685 import math pwm = Adafruit_PCA9685.PCA9685() pwm.set_pwm_freq(60) faceCascade = cv2.CascadeClassifier('/home/pi/haarcascades/haarcascade_frontalface_default.xml') def move(x_move, y_move): pwm.set_pwm(0, 0, x_move) pwm.set_pwm(1, 0, y_move) #X,Yのサーボで稼働させる範囲。適当によさげな範囲を指定。 X_MIN = 150 X_HOME = 375 X_MAX = 600 Y_MIN = 150 Y_HOME = 375 Y_MAX = 600 #カメラの位置初期化 move(X_HOME, Y_HOME) #カメラ準備 cap = cv2.VideoCapture(0) # デフォルト画面サイズ横幅 #W = cap.get(cv2.CAP_PROP_FRAME_WIDTH) cap.set(3,320) # 横幅を設定 cap.set(4,320) # 縦幅を設定 #初期位置 now_degree_x, now_degree_y, move_degree_x, move_degree_y = X_HOME, Y_HOME, 0, 0 while(True): #画面取得 ret, img = cap.read() # 顔検出の負荷軽減のために、キャプチャした画像をモノクロにする gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 顔検出のパラメータの設定 faces = faceCascade.detectMultiScale( gray, scaleFactor=1.2, minNeighbors=5, minSize=(20, 20) ) 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] img_x = int(x+w/2) img_y = int(y+h/2) move_degree_x = now_degree_x - (img_x-160)*0.1 move_degree_y = now_degree_y + (img_y-160)*0.1 move_degree_x = math.floor(move_degree_x) move_degree_y = math.floor(move_degree_y) #実際にカメラを動かすところ move(move_degree_x, move_degree_y) now_degree_x = move_degree_x now_degree_y = move_degree_y #画面への描写 cv2.imshow('video', img) k = cv2.waitKey(1) if k == ord('q'): break #else: #break cap.release() cv2.destroyAllWindows() |
少し分かりずらいですが、一応顔を認識して顔の動きに応じてカメラが追従してくれています。↓