Spaces:
Sleeping
Sleeping
| import numpy as np | |
| from scipy.spatial import distance as dist | |
| from imutils import face_utils | |
| (lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"] | |
| (rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"] | |
| def euclidean_distance(point1, point2): | |
| return np.linalg.norm(point1 - point2) | |
| def eyebrow(landmarks,sizes): | |
| eyebrow_dist=[] | |
| for landmark,size in zip(landmarks,sizes): | |
| if landmark is not None: | |
| right_eyebrow_inner = landmark[21] | |
| left_eyebrow_inner = landmark[22] | |
| eyebrow_distance = euclidean_distance(right_eyebrow_inner, left_eyebrow_inner) | |
| normalized_eyebrow_distance = eyebrow_distance / size[0] | |
| else: | |
| normalized_eyebrow_distance=None | |
| eyebrow_dist.append(normalized_eyebrow_distance) | |
| return eyebrow_dist | |
| def eye_aspect_ratio(eye): | |
| A = dist.euclidean(eye[1], eye[5]) # Vertical distance 1 | |
| B = dist.euclidean(eye[2], eye[4]) # Vertical distance 2 | |
| C = dist.euclidean(eye[0], eye[3]) # Horizontal distance | |
| ear = (A + B) / (2.0 * C) # EAR formula | |
| return ear | |
| def euclidean_distance(p1, p2): | |
| return np.linalg.norm(p1 - p2) | |
| # Function to detect smiles based on mouth aspect ratio | |
| def detect_smiles(landmarks_list, face_sizes, fps=30, consecutive_frames=2): | |
| smile_ratios = [] # Store the smile ratios for plotting | |
| smiles = [] | |
| smile_durations = [] # To store the duration of each smile | |
| total_smiles = 0 | |
| smile_in_progress = False | |
| smile_start_frame = None | |
| avg_dynamic_threshold=[] | |
| for frame_idx, (landmarks, face_size) in enumerate(zip(landmarks_list, face_sizes)): | |
| if landmarks is not None: | |
| # Use NumPy array indices for the relevant mouth landmarks | |
| left_corner = np.array(landmarks[48]) | |
| right_corner = np.array(landmarks[54]) | |
| top_lip = np.array(landmarks[51]) | |
| bottom_lip = np.array(landmarks[57]) | |
| mouth_width = euclidean_distance(left_corner, right_corner) | |
| mouth_height = euclidean_distance(top_lip, bottom_lip) | |
| face_width, face_height = face_size # face_size is (width, height) | |
| if face_width > 0 and face_height > 0: | |
| normalized_mouth_width = mouth_width / face_width | |
| normalized_mouth_height = mouth_height / face_height | |
| else: | |
| normalized_mouth_width = 0 | |
| normalized_mouth_height = 0 | |
| smile_ratios.append(normalized_mouth_width) | |
| dynamic_threshold = 0.2 + (0.05 * face_width / 100) | |
| avg_dynamic_threshold.append(dynamic_threshold) | |
| # print(dynamic_threshold) | |
| # Check if the smile meets the threshold | |
| if (normalized_mouth_width > dynamic_threshold) and (normalized_mouth_height > 0.06): | |
| smiles.append(True) | |
| if not smile_in_progress: | |
| smile_in_progress = True | |
| smile_start_frame = frame_idx # Record the start of the smile | |
| else: | |
| smiles.append(False) | |
| if smile_in_progress and (frame_idx - smile_start_frame >= consecutive_frames): | |
| smile_in_progress = False | |
| smile_end_frame = frame_idx | |
| smile_duration = (smile_end_frame - smile_start_frame) / fps # Calculate smile duration | |
| smile_durations.append(smile_duration) | |
| total_smiles += 1 # Increment total smile count | |
| else: | |
| smiles.append(None) | |
| try: | |
| avg_thr=sum(avg_dynamic_threshold)/len(avg_dynamic_threshold) | |
| except: | |
| avg_thr=0 | |
| return smiles, smile_ratios, total_smiles, smile_durations,avg_thr | |
| # Function to detect blinks based on the eye aspect ratio (EAR) | |
| import numpy as np | |
| # Function to detect blinks based on the eye aspect ratio (EAR) | |
| def detect_blinks(landmarks_list, face_sizes, ear_threshold=0.24, consecutive_frames=2): | |
| ear_ratios = [] # Store EAR for plotting | |
| blinks = [] | |
| # Variables to monitor consecutive low EAR values | |
| blink_count = 0 | |
| consec_low_ear = 0 | |
| for landmarks, face in zip(landmarks_list, face_sizes): | |
| if landmarks is not None: | |
| left_eye = landmarks[36:42] # Points 36-41 (inclusive) for the left eye | |
| right_eye = landmarks[42:48] | |
| def eye_aspect_ratio(eye): | |
| A = euclidean_distance(eye[1], eye[5]) | |
| B = euclidean_distance(eye[2], eye[4]) | |
| C = euclidean_distance(eye[0], eye[3]) | |
| ear = (A + B) / (2.0 * C) | |
| return ear | |
| left_ear = eye_aspect_ratio(left_eye) | |
| right_ear = eye_aspect_ratio(right_eye) | |
| avg_ear = (left_ear + right_ear) / 2.0 | |
| ear_ratios.append(avg_ear) | |
| if avg_ear < ear_threshold: | |
| consec_low_ear += 1 | |
| else: | |
| # If low EAR is detected for enough consecutive frames, count as a blink | |
| if consec_low_ear >= consecutive_frames: | |
| blink_count += 1 | |
| consec_low_ear = 0 # Reset the consecutive low EAR counter | |
| else: | |
| blinks.append(None) | |
| return blink_count, ear_ratios | |
| # Function to detect yawns based on the vertical distance between top and bottom lips | |
| # Function to detect yawns based on the vertical distance between top and bottom lips | |
| def detect_yawns(landmarks_list, face_sizes, fps=30, consecutive_frames=3): | |
| yawn_ratios = [] # Store the yawn ratios for plotting | |
| yawns = [] | |
| yawn_durations = [] # To store the duration of each yawn | |
| total_yawns = 0 | |
| yawn_in_progress = False | |
| yawn_start_frame = None | |
| for frame_idx, (landmarks, face_size) in enumerate(zip(landmarks_list, face_sizes)): | |
| if landmarks is not None: | |
| top_lip = np.array(landmarks[51]) | |
| bottom_lip = np.array(landmarks[57]) | |
| mouth_height = euclidean_distance(top_lip, bottom_lip) | |
| face_width, face_height = face_size # face_size is (width, height) | |
| if face_height > 0: | |
| normalized_mouth_height = mouth_height / face_height | |
| else: | |
| normalized_mouth_height = 0 | |
| yawn_ratios.append(normalized_mouth_height) | |
| # Check if the yawn meets the threshold | |
| if normalized_mouth_height > 0.24: | |
| yawns.append(True) | |
| if not yawn_in_progress: | |
| yawn_in_progress = True | |
| yawn_start_frame = frame_idx # Record the start of the yawn | |
| else: | |
| yawns.append(False) | |
| if yawn_in_progress and (frame_idx - yawn_start_frame >= consecutive_frames): | |
| yawn_in_progress = False | |
| yawn_end_frame = frame_idx | |
| yawn_duration = (yawn_end_frame - yawn_start_frame) / fps # Calculate yawn duration | |
| yawn_durations.append(yawn_duration) | |
| total_yawns += 1 # Increment total yawn count | |
| else: | |
| yawns.append(None) | |
| return yawns, yawn_ratios, total_yawns, yawn_durations | |