MediaPipeの動作テスト
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

101 lines
3.5 KiB

import cv2
import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision
YAW_THRESHOLD = 13
PITCH_THRESHOLD = 5
def get_aoi(yaw, pitch):
ret = ''
if yaw > YAW_THRESHOLD:
ret += 'Left '
elif yaw > -YAW_THRESHOLD:
ret += 'Center '
else:
ret += 'Right '
if pitch > PITCH_THRESHOLD:
ret += 'Lower'
elif pitch > -PITCH_THRESHOLD:
ret += 'Center'
else:
ret += 'Upper'
return ret
areas = ['left upper', 'center', 'right upper', 'left lower', 'right lower']
# 1. クラスのセットアップ (FaceLandmarkerに変更)
BaseOptions = python.BaseOptions
FaceLandmarker = vision.FaceLandmarker
FaceLandmarkerOptions = vision.FaceLandmarkerOptions
VisionRunningMode = vision.RunningMode
# 2. 顔ランドマーカーの設定
# 変換行列(顔の向きデータ)を出力するようにフラグを立てます
options = FaceLandmarkerOptions(
base_options=BaseOptions(model_asset_path='face_landmarker.task'),
running_mode=VisionRunningMode.VIDEO,
output_facial_transformation_matrixes=True, # 顔の向き取得に必須
num_faces=1 # 検出する顔の最大数
)
cap = cv2.VideoCapture(0)
# FaceLandmarkerのインスタンスを生成
with FaceLandmarker.create_from_options(options) as landmarker:
while cap.isOpened():
success, frame = cap.read()
if not success:
break
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame_timestamp_ms = int(cap.get(cv2.CAP_PROP_POS_MSEC))
# 稀にタイムスタンプが0や重複になるのを防ぐ安全策
if frame_timestamp_ms == 0:
frame_timestamp_ms = 1
mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=rgb_frame)
# 3. 検出の実行
result = landmarker.detect_for_video(mp_image, frame_timestamp_ms)
# 4. 変換行列から顔の向き(オイラー角)を計算
if result.facial_transformation_matrixes:
for matrix in result.facial_transformation_matrixes:
# 4x4の変換行列から、左上の3x3の回転行列のみを抽出
rot_mat = matrix[:3, :3]
# OpenCVを使って回転行列をオイラー角(度数法)に分解
angles, _, _, _, _, _ = cv2.RQDecomp3x3(rot_mat)
# ピッチ(上下), ヨー(左右), ロール(傾き)の取得
# ※カメラや座標系によって軸の順番は変わる場合があります
pitch = angles[0]
yaw = angles[1]
roll = angles[2]
# オイラー角からAOIを推定
estimate_aoi = get_aoi(yaw, pitch)
text_aoi = f"Estimated AOI: {estimate_aoi}"
# 画面上に角度を描画
text_pitch = f"Pitch (Up/Down): {pitch:.1f}"
text_yaw = f"Yaw (Left/Right): {yaw:.1f}"
text_roll = f"Roll (Tilt): {roll:.1f}"
cv2.putText(frame, text_aoi, (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(frame, text_pitch, (20, 70), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2)
cv2.putText(frame, text_yaw, (20, 100), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2)
cv2.putText(frame, text_roll, (20, 130), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2)
cv2.imshow('Area of Interest Estimation', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()