| import streamlit as st |
| import cv2 |
| import numpy as np |
| import dlib |
| from scipy.spatial import distance as dist |
| from imutils import face_utils |
|
|
| |
| EYE_AR_THRESH = 0.3 |
| EYE_AR_CONSEC_FRAMES = 30 |
| YAWN_THRESH = 20 |
|
|
| |
| COUNTER = 0 |
|
|
| |
| 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 |
|
|
| |
| detector = cv2.CascadeClassifier('./haarcascade_frontalface_default.xml') |
| predictor = dlib.shape_predictor('./shape_predictor_68_face_landmarks.dat') |
|
|
|
|
| |
| st.title("Sleep Detection using OpenCV") |
| st.markdown("**Check the box below to start the camera:**") |
|
|
| FRAME_WINDOW = st.image([]) |
| run = st.checkbox("Run Camera", key="run_camera") |
|
|
| |
| if "cap" not in st.session_state: |
| st.session_state.cap = None |
|
|
| if run: |
| if st.session_state.cap is None: |
| st.session_state.cap = cv2.VideoCapture(0) |
| st.success("Camera Started!") |
|
|
| while run: |
| ret, frame = st.session_state.cap.read() |
| if not ret: |
| st.error("Failed to open webcam.") |
| break |
|
|
| frame = cv2.resize(frame, (450, 300)) |
| 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) |
|
|
| FRAME_WINDOW.image(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) |
|
|
| st.session_state.cap.release() |
| st.session_state.cap = None |
| FRAME_WINDOW.image([]) |
| st.checkbox("Run Camera", value=False, key="run_camera") |
| else: |
| if st.session_state.cap is not None: |
| st.session_state.cap.release() |
| st.session_state.cap = None |
| FRAME_WINDOW.image([]) |
| st.info("Check 'Run Camera' to start detection.") |