Spaces:
Sleeping
Sleeping
| import argparse | |
| from scipy.spatial import distance as dist | |
| from imutils import face_utils | |
| import numpy as np | |
| import imutils | |
| import time | |
| import dlib | |
| import cv2 | |
| import matplotlib.pyplot as plt | |
| from keras.preprocessing.image import img_to_array | |
| from keras.models import load_model | |
| def eye_brow_distance(leye, reye): | |
| global points | |
| distq = dist.euclidean(leye, reye) | |
| points.append(int(distq)) | |
| return distq | |
| def emotion_finder(faces, frame): | |
| global emotion_classifier | |
| EMOTIONS = ["angry", "disgust", "scared", "happy", "sad", "surprised", "neutral"] | |
| x, y, w, h = face_utils.rect_to_bb(faces) | |
| frame = frame[y:y + h, x:x + w] | |
| roi = cv2.resize(frame, (64, 64)) | |
| roi = roi.astype("float") / 255.0 | |
| roi = img_to_array(roi) | |
| roi = np.expand_dims(roi, axis=0) | |
| preds = emotion_classifier.predict(roi)[0] | |
| emotion_probability = np.max(preds) | |
| label = EMOTIONS[preds.argmax()] | |
| return label | |
| def normalize_values(points, disp): | |
| normalized_value = abs(disp - np.min(points)) / abs(np.max(points) - np.min(points)) | |
| stress_value = np.exp(-(normalized_value)) | |
| return stress_value | |
| def stress(video_path, duration): | |
| global points, emotion_classifier | |
| detector = dlib.get_frontal_face_detector() | |
| predictor = dlib.shape_predictor("stress_detection/models/data") | |
| emotion_classifier = load_model("stress_detection/models/_mini_XCEPTION.102-0.66.hdf5", compile=False) | |
| cap = cv2.VideoCapture(video_path) | |
| points = [] | |
| stress_labels = [] | |
| start_time = time.time() | |
| while True: | |
| current_time = time.time() | |
| if current_time - start_time >= duration: | |
| break | |
| ret, frame = cap.read() | |
| if not ret: | |
| break | |
| frame = cv2.flip(frame, 1) | |
| frame = imutils.resize(frame, width=500, height=500) | |
| (lBegin, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eyebrow"] | |
| (rBegin, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eyebrow"] | |
| gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) | |
| try: | |
| detections = detector(gray, 0) | |
| for detection in detections: | |
| emotion = emotion_finder(detection, gray) | |
| shape = predictor(gray, detection) | |
| shape = face_utils.shape_to_np(shape) | |
| leyebrow = shape[lBegin:lEnd] | |
| reyebrow = shape[rBegin:rEnd] | |
| distq = eye_brow_distance(leyebrow[-1], reyebrow[0]) | |
| stress_value = normalize_values(points, distq) | |
| # Determine stress label for this frame | |
| if emotion in ['scared', 'sad', 'angry'] and stress_value >= 0.75: | |
| stress_label = 'stressed' | |
| else: | |
| stress_label = 'not stressed' | |
| # Store stress label in list | |
| stress_labels.append(stress_label) | |
| except Exception as e: | |
| print(f'Error: {e}') | |
| key = cv2.waitKey(1) & 0xFF | |
| if key == ord('q'): | |
| break | |
| cap.release() | |
| # Count occurrences of 'stressed' and 'not stressed' | |
| stressed_count = stress_labels.count('stressed') | |
| not_stressed_count = stress_labels.count('not stressed') | |
| # Determine which label occurred more frequently | |
| if stressed_count > not_stressed_count: | |
| most_frequent_label = 'stressed' | |
| else: | |
| most_frequent_label = 'not stressed' | |
| return stressed_count, not_stressed_count, most_frequent_label | |
| def main(): | |
| # Argument parsing | |
| parser = argparse.ArgumentParser(description='Stress Detection from Video') | |
| parser.add_argument('--video', type=str, required=True, default='output.mp4', help='Path to the input video file') | |
| parser.add_argument('--duration', type=int, default=30, help='Duration for analysis in seconds') | |
| args = parser.parse_args() | |
| # Call the stress function and get the results | |
| stressed_count, not_stressed_count, most_frequent_label = stress(args.video, args.duration) | |
| # Display the result | |
| print(f"Stressed frames: {stressed_count}") | |
| print(f"Not stressed frames: {not_stressed_count}") | |
| print(f"Most frequent state: {most_frequent_label}") | |
| if __name__ == '__main__': | |
| main() | |