前回の記事では@PonDadさんの記事を参考にさせていただきRaspberryPi、カメラ、サーボモーターを用いて、顔追跡を行いました。@PonDadさんありがとうございます。
今回は、ストリーミング画面の中心点と顔の中心点の差から、逆三角関数のアークサインを用いて角度を計算する方法に変更します。
#環境
前回の記事と同じ。
#概要
サーボモータによるカメラを移動について、ストリーミング画面の中心点と顔の中心点の差から逆三角関数のアークサインを用いて角度を計算する方法に変更する。
以下の様に考えれば良いのだと思うのであるが、得られた角度をサーボのpwm.set_pwm()
にセットする数値へ換算するための係数を考えているうちに訳が解らなくなってしまったので、コードを実行しながら試行錯誤した結果*16
としました。
- LOGICOOL ウェブカム C270の画角は60°なので画角の端で+-30°。sin30°は1/2。
- ストリーミング画面の中心点と顔の中心点の差から
math.asin()
を用いて角度を計算 - 得られる角度は単位がラジアン
-
pwm.set_pwm()
へセットする数値は150から600で、約180°動く。
#コード
face_tracking3.py
face_tracking3.py
# -*- coding: UTF-8 -*-
import cv2
import os
import time
import Adafruit_PCA9685
import math
pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm_freq(60)
cascade_path = "haarcascade_frontalface_alt.xml"
cascade = cv2.CascadeClassifier(cascade_path)
cap = cv2.VideoCapture(0)
cap.set(3, 320)
cap.set(4, 240)
color = (255, 255, 255)
pwm.set_pwm(0, 0, 375)
time.sleep(1)
pwm.set_pwm(1, 0, 375)
time.sleep(1)
now_degree_x, now_degree_y, move_degree_x, move_degree_y = 375, 375, 0, 0
while(True):
ret, frame = cap.read()
facerect = cascade.detectMultiScale(frame, scaleFactor=1.2, minNeighbors=2, minSize=(20, 20))
for rect in facerect:
img_x = rect[0]+rect[2]/2
img_y = rect[1]+rect[3]/2
print(img_x, img_y)
move_degree_x = now_degree_x - math.asin((img_x-160)/320)*16
move_degree_y = now_degree_y + math.asin((img_y-120)/320)*16
print('asin: ', math.asin((img_x-160)/320) , math.asin((img_y-120)/320))
print('deg: ', move_degree_x , move_degree_y)
pwm.set_pwm(0, 0, int(move_degree_x))
pwm.set_pwm(1, 0, int(move_degree_y))
#time.sleep(0.1)
now_degree_x = move_degree_x
now_degree_y = move_degree_y
cv2.circle(frame, (int(img_x), int(img_y)), 5, (255,255,255), -1)
cv2.rectangle(frame, tuple(rect[0:2]),tuple(rect[0:2] + rect[2:4]), color, thickness=2)
cv2.imshow("Show FLAME Image", frame)
k = cv2.waitKey(1)& 0xFF
if k == ord('q'):
break
cap.release()
print('cap.release ')
cv2.destroyAllWindows()
#感想
角度の計算時の係数が理論値と全然合わないです。
本当は、係数をもっと大きくすべきだと思うのですが、大きくすると、顔を通り過ぎます。
サーボの移動が完了しないうちに、次のループに入ってしまうからなのでしょうか?
未解明です。