使用MediaPipe来判断脸部朝向(向左或向右)
在正面朝向时,两眼的中心点位于水平线上,因此两眼的连线近似与水平线平行。
当脸部朝左侧时,右眼相对于左眼会有一定的水平偏移,两眼的连线会略微倾斜向左。
当脸部朝右侧时,左眼相对于右眼会有一定的水平偏移,两眼的连线会略微倾斜向右
import cv2
import mediapipe as mp
import math
mp_face_detection = mp.solutions.face_detection
mp_face_mesh = mp.solutions.face_mesh
mp_drawing = mp.solutions.drawing_utils
cap = cv2.VideoCapture(0)
def calculate_eye_angle(left_eye, right_eye):
# 计算左右眼之间的角度
eye_angle = math.degrees(math.atan2(right_eye.y - left_eye.y, right_eye.x - left_eye.x))
return eye_angle
def get_face_direction(landmarks, iw):
left_eye = landmarks.landmark[159] # 左眼最外侧点
right_eye = landmarks.landmark[386] # 右眼最外侧点
eye_angle = calculate_eye_angle(left_eye, right_eye)
if abs(eye_angle) <= 15:
return "向前"
elif eye_angle < 0:
return "向左"
else:
return "向右"
def detect_face_direction(frame, face_detection):
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = face_detection.process(rgb_frame)
if results.detections:
for detection in results.detections:
bboxC = detection.location_data.relative_bounding_box
ih, iw, _ = frame.shape
x, y, w, h = int(bboxC.xmin * iw), int(bboxC.ymin * ih), \
int(bboxC.width * iw), int(bboxC.height * ih)
results_mesh = mp_face_mesh.FaceMesh(min_detection_confidence=0.5, min_tracking_confidence=0.5).process(rgb_frame)
if results_mesh.multi_face_landmarks:
landmarks = results_mesh.multi_face_landmarks[0]
direction = get_face_direction(landmarks, iw)
cv2.putText(frame, f"脸部朝向:{direction}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
return frame
def main():
with mp_face_detection.FaceDetection(min_detection_confidence=0.5) as face_detection:
while cap.isOpened():
ret, frame = cap.read()
if not ret:
continue
frame_with_direction = detect_face_direction(frame, face_detection)
cv2.imshow('脸部朝向', frame_with_direction)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if __name__ == "__main__":
main()
cap.release()
cv2.destroyAllWindows()