1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

続 Raspberry Pi とPython3とOpen CVで顔追跡カメラ(三角関数利用編)

Last updated at Posted at 2018-01-08

前回の記事では@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()

#感想

角度の計算時の係数が理論値と全然合わないです。
本当は、係数をもっと大きくすべきだと思うのですが、大きくすると、顔を通り過ぎます。
サーボの移動が完了しないうちに、次のループに入ってしまうからなのでしょうか?
未解明です。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?