#はじめに
Aliexpressからカメラのパン/チルト雲台が届いたので、OpenCVで顔検出しサーボで顔をトラッキングするシステムを作成してみることにした。
#用意するもの
##Raspberry Pi 1 Model B
2014年の古いラズパイです。能力がぜんぜん足りず8秒ほど遅延してしまう結果となりました。最新なら問題なくリアルタイム処理できそうです。
##サーボ駆動カメラ雲台
Aliexpressで購入。ST90サーボ2個つきでUS$5.89でした。
##16ch サーボドライバ
NXP社のPCA9685を使用した16×12-bit PWM制御基板です。I2Cで通信&制御できます。Aliexpressで購入。Adafruitのドライバが使用できます。
##USBカメラ
手持ちのドライブレコーダを使用しました。USBで接続するとPCモードになり、ドライバ無しでUSBカメラとして機能しました。
##3.5inch LCD
ラズパイ用として販売されている3.5inch LCD、タッチパネル付きです。26ピンコネクタが付いており、ラズパイのGPIOピンに差せばモニタ兼タッチパネルとして動作してくれます。ラズパイとはSPI通信しています。
#下準備1 - まずは顔認識してみる
RaspberryPiとOpenCVで顔認識してパフォーマンスも改善してみる
こちらを参考にしています。
takusenoさま、ありがとうございました。
##Setup
OpenCVのライブラリをインストールします。下記shellにて実行しました。
sudo apt-get install libopencv-dev
sudo apt-get install python-opencv
wget http://eclecti.cc/files/2008/03/haarcascade_frontalface_alt.xml
##OpenCVで顔認識してみる
USBCAMを接続します。接続するだけです。
##実行
下記Pythonコードを保存します。
import cv2.cv as cv
import cv2
cv.NamedWindow("camera", 1)
capture = cv2.VideoCapture(0)
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
while True:
_, img = capture.read()
img = cv2.resize(img, (320, 240))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=3,
minSize=(30, 30),
flags=cv.CV_HAAR_SCALE_IMAGE
)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv2.imshow("camera", img)
if cv.WaitKey(10) > 0:
break
cv.DestroyAllWindows()
##実行します。
LCD上でターミナルを起動し、下記実行します。
sudo python usbcam.py
認識してくれました。緑枠が認識された顔です。
#下準備2 - サーボ駆動してみる
##接続
ラズパイとPCA9685基板の接続は下記のとおり。
Raspberry Pi | -- | PCA9685 |
---|---|---|
PIN3(SDA) | -- | SCA |
PIN4(+5V) | -- | VCC |
PIN5(SDL) | -- | SCL |
PIN6(GND) | -- | GND |
注意:PCA9685の"V+"ではなく**"VCC"**に接続すること。"VCC"はIC用の電源。"V+"はサーボ駆動用電源、そのためこちらは電流の取れる電源を別途供給必要。 | ||
###その他設定動作確認は下記先人の偉業を参考にしました | ||
Raspberry Pi 3でPCA9685を使う | ||
@ttyokoyamaさま、ありがとうございます! |
##サンプルプログラム
下記実行し、サーボが動作することを確認します。ch0が水平、ch1が垂直用のサーボで、3秒ごとに移動します。
こちらはUSBカメラからの画像を表示する必要がない為、sshにてリモートから実行しても問題なく動作します。
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import Adafruit_PCA9685
GPIO.setmode(GPIO.BOARD)
pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm_freq(60)
sw1 = 0
sw2 = 0
try:
while True:
time.sleep(3)
if sw1 == 1:
pwm.set_pwm(1, 0, 600)
sw1 = 0
else:
pwm.set_pwm(1, 0, 375)
sw1 = 1
if sw2 == 1:
pwm.set_pwm(0, 0, 600)
sw2 = 0
else:
pwm.set_pwm(0, 0, 375)
sw2 = 1
except KeyboardInterrupt:
pass
#顔認識とサーボ駆動を連携してみる
##i2C配線の取り出し
###下調べ
i2Cの信号ピンは3番5番ピンなのですが、LCDのコネクタで塞がっています。
3.5 Inch 480x320 TFT Display with Touch Screen for Raspberry Pi
接続を調べてみると、i2Cで仕様する3番5番ピンはNCとなっていましたので、遠慮無く当該のPINに接続することにします。
###信号の取り出し
PCBとLCDは両面テープでやっつけられているだけのようです。
フレキシブルケーブルを痛めないよう注意しながら、両面テープを剥し、分離させます。
コネクタのハンダ付け部分に4本のUEW線をハンダ付けします。UEW線はφ0.2mmのものを使用しています。UEW線はポリウレタンで被覆されており、ハンダ付けする箇所のみポリウレタンが溶けハンダ付けされます。このような箇所にハンダ付けするにぴったりな配線です。
メスコネクタにUEW線をハンダ付けします。ピン番号も書いておきます。4番ピンは+5V線のため、不用意なショートを防ぐため、メスコネクタを使用しておきました。
液晶が表示されること、i2Cを経由してサーボが動作することを確認してHWの改造は終了です。
##顔認識させてサーボを動作させる
いよいよ本番です。顔認識した位置にサーボで雲台を向けてみます。
pwm.set_pwmにセットする値と角度の関係は
150~650 : 0 ~ 180deg
とのことです。画角等に応じてpwm.set_pwmに渡す引数を変更ください。
LCD上でターミナルを起動し、下記実行します。
sudo python sercam.py
import cv2.cv as cv
import cv2
#servo
import RPi.GPIO as GPIO
import time
import Adafruit_PCA9685
pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm_freq(60)
GPIO.setmode(GPIO.BOARD)
cv.NamedWindow("camera", 1)
capture = cv2.VideoCapture(0)
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
while True:
_, img = capture.read()
img = cv2.resize(img, (320, 240))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=3,
minSize=(30, 30),
flags=cv.CV_HAAR_SCALE_IMAGE
)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
#pulse = 150~650 : 0 ~ 180deg
pwm.set_pwm(0, 0, 400 - (x+w)/2) # h
pwm.set_pwm(1, 0, 400 - (y+h)/2) # v
cv2.imshow("camera", img)
if cv.WaitKey(10) > 0:
break
cv.DestroyAllWindows()
#動いたぞ!
Googleから顔写真を探してきて、写真をモニタ上で移動してみた。実際には写真の位置を移動させてから8秒ほどタイムラグが有ったすえに検出、サーボ動作している。反応が悪いが昔のラズパイだということで納得はしている。
#Special thanks!
参考にしたサイトです。ありがとうございます!
Raspberry Pi 3でPCA9685を使う
RaspberryPiとOpenCVで顔認識してパフォーマンスも改善してみる
3.5 Inch 480x320 TFT Display with Touch Screen for Raspberry Pi
2018/01/28 Ikeda