driver / utils /ear_utils.py
Guru-25's picture
new
b8b61aa
import cv2
import numpy as np
import mediapipe as mp
from scipy.spatial import distance as dist
def eye_aspect_ratio(eye_landmarks, landmarks, image_shape):
eye = [
landmarks[eye_landmarks[0]], # P1 (left)
landmarks[eye_landmarks[1]], # P2 (top-left)
landmarks[eye_landmarks[2]], # P3 (top-right)
landmarks[eye_landmarks[3]], # P4 (right)
landmarks[eye_landmarks[4]], # P5 (bottom-right)
landmarks[eye_landmarks[5]] # P6 (bottom-left)
]
eye = [(int(p.x * image_shape[1]), int(p.y * image_shape[0])) for p in eye]
A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])
C = dist.euclidean(eye[0], eye[3])
ear = (A + B) / (2.0 * C)
return ear, eye
class BlinkDetector:
def __init__(self):
self.mp_face_mesh = mp.solutions.face_mesh
self.face_mesh = self.mp_face_mesh.FaceMesh(
max_num_faces=1,
refine_landmarks=True, # Required for iris landmarks
min_detection_confidence=0.5,
min_tracking_confidence=0.5
)
self.EAR_THRESHOLD = 0.25
self.EAR_CONSEC_FRAMES = 3
def detect_blinks(self, frame):
image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = self.face_mesh.process(image_rgb)
if not results.multi_face_landmarks:
return None, None, None, None, None, None
landmarks = results.multi_face_landmarks[0].landmark
h, w = frame.shape[:2]
LEFT_EYE = [33, 160, 158, 133, 153, 144]
RIGHT_EYE = [362, 385, 387, 263, 373, 380]
LEFT_IRIS = 473 # Left iris center
RIGHT_IRIS = 468 # Right iris center
left_ear, left_eye_points = eye_aspect_ratio(LEFT_EYE, landmarks, (h, w))
right_ear, right_eye_points = eye_aspect_ratio(RIGHT_EYE, landmarks, (h, w))
avg_ear = (left_ear + right_ear) / 2.0
nose_tip = landmarks[1]
head_pose = (nose_tip.x - 0.5) * 2
# Iris coordinates
left_iris = (int(landmarks[LEFT_IRIS].x * w), int(landmarks[LEFT_IRIS].y * h))
right_iris = (int(landmarks[RIGHT_IRIS].x * w), int(landmarks[RIGHT_IRIS].y * h))
return avg_ear, left_eye_points, right_eye_points, head_pose, left_iris, right_iris
def __del__(self):
self.face_mesh.close()