Spaces:
Sleeping
Sleeping
File size: 4,222 Bytes
b7940d5 bcdca57 b7940d5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
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("Heartandstress/models/data")
emotion_classifier = load_model("Heartandstress/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()
|