import streamlit as st import cv2 import numpy as np import dlib from scipy.spatial import distance as dist from imutils import face_utils # Constants EYE_AR_THRESH = 0.3 EYE_AR_CONSEC_FRAMES = 30 YAWN_THRESH = 20 # Global variables COUNTER = 0 # Global COUNTER defined here # Functions def eye_aspect_ratio(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 def final_ear(shape): (lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"] (rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"] leftEye = shape[lStart:lEnd] rightEye = shape[rStart:rEnd] leftEAR = eye_aspect_ratio(leftEye) rightEAR = eye_aspect_ratio(rightEye) ear = (leftEAR + rightEAR) / 2.0 return (ear, leftEye, rightEye) def lip_distance(shape): top_lip = shape[50:53] top_lip = np.concatenate((top_lip, shape[61:64])) low_lip = shape[56:59] low_lip = np.concatenate((low_lip, shape[65:68])) top_mean = np.mean(top_lip, axis=0) low_mean = np.mean(low_lip, axis=0) distance = abs(top_mean[1] - low_mean[1]) return distance def process_frame(frame, detector, predictor): """Process the frame and detect drowsiness and yawning.""" global COUNTER # Declare COUNTER as global here gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) rects = detector.detectMultiScale( gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE ) for (x, y, w, h) in rects: rect = dlib.rectangle(int(x), int(y), int(x + w), int(y + h)) shape = predictor(gray, rect) shape = face_utils.shape_to_np(shape) ear, leftEye, rightEye = final_ear(shape) distance = lip_distance(shape) leftEyeHull = cv2.convexHull(leftEye) rightEyeHull = cv2.convexHull(rightEye) cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1) cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1) lip = shape[48:60] cv2.drawContours(frame, [lip], -1, (0, 255, 0), 1) if ear < EYE_AR_THRESH: COUNTER += 1 if COUNTER >= EYE_AR_CONSEC_FRAMES: cv2.putText(frame, "DROWSINESS", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) else: COUNTER = 0 if distance > YAWN_THRESH: cv2.putText(frame, "YAWN", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) cv2.putText(frame, f"EAR: {ear:.2f}", (300, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.putText(frame, f"YAWN: {distance:.2f}", (300, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) return frame # Load detector and predictor detector = cv2.CascadeClassifier('./haarcascade_frontalface_default.xml') predictor = dlib.shape_predictor('./shape_predictor_68_face_landmarks.dat') # Streamlit UI st.title("Sleep Detection using OpenCV") st.markdown("**Check the box below to start the camera:**") run = st.checkbox("Run Camera") # Video capture if run: cap = cv2.VideoCapture(0) FRAME_WINDOW = st.image([]) while True: ret, frame = cap.read() if not ret: st.error("Failed to open webcam.") break frame = cv2.resize(frame, (450, 300)) frame = process_frame(frame, detector, predictor) # Process frame here FRAME_WINDOW.image(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) else: st.info("Check 'Run Camera' to start detection.")