Spaces:
Build error
Build error
| import numpy as np | |
| import cv2 | |
| import mediapipe as mp | |
| LEFT_EYE = [33, 133] | |
| RIGHT_EYE = [362, 263] | |
| NOSE = 1 | |
| mp_face_mesh = mp.solutions.face_mesh | |
| def get_lip_engagement(landmarks): | |
| TOP_LIP = 13 | |
| BOTTOM_LIP = 14 | |
| LIP_LEFT = 78 | |
| LIP_RIGHT = 308 | |
| top_lip = landmarks[TOP_LIP] | |
| bottom_lip = landmarks[BOTTOM_LIP] | |
| left_corner = landmarks[LIP_LEFT] | |
| right_corner = landmarks[LIP_RIGHT] | |
| lip_opening = abs(top_lip[1] - bottom_lip[1]) | |
| lip_width = abs(right_corner[0] - left_corner[0]) | |
| # print(f"[DEBUG] lip_opening: {lip_opening:.3f}, lip_width: {lip_width:.3f}") | |
| # Example, adjust as per your actual values! | |
| # This logic: high opening OR high width = Engaged (smile/mouth open) | |
| # very small both = Not Engaged, everything else = Partially Engaged | |
| if lip_opening > 0.01 or lip_width > 0.18: | |
| return "Engaged" | |
| elif lip_opening < 0.002 or lip_width < 0.04: | |
| return "Not Engaged" | |
| else: | |
| return "Partially Engaged" | |
| def track_microexpressions(frame, face_mesh, calibration_ref=None): | |
| if calibration_ref is None: | |
| calibration_ref = {} | |
| h, w, _ = frame.shape | |
| frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) | |
| results = face_mesh.process(frame_rgb) | |
| micro = { | |
| "eye_away": False, | |
| "head_turn": False, | |
| } | |
| face_bbox = None | |
| multiple_faces = False | |
| if results.multi_face_landmarks: | |
| if len(results.multi_face_landmarks) > 1: | |
| multiple_faces = True | |
| lm = results.multi_face_landmarks[0].landmark | |
| xs = [p.x for p in lm] | |
| ys = [p.y for p in lm] | |
| xmin, xmax = min(xs)*w, max(xs)*w | |
| ymin, ymax = min(ys)*h, max(ys)*h | |
| face_bbox = [int(xmin), int(ymin), int(xmax), int(ymax)] | |
| eye_x = (lm[LEFT_EYE[0]].x + lm[RIGHT_EYE[0]].x) / 2 | |
| nose_x = lm[NOSE].x | |
| margin = 0.07 | |
| eye_left_th = calibration_ref.get('eye_left', 0.30) | |
| eye_right_th = calibration_ref.get('eye_right', 0.70) | |
| if eye_x < (eye_left_th - margin) or eye_x > (eye_right_th + margin): | |
| micro["eye_away"] = True | |
| if nose_x < (eye_left_th - margin) or nose_x > (eye_right_th + margin): | |
| micro["head_turn"] = True | |
| return micro, face_bbox, multiple_faces | |