import cv2
import dlib
from scipy.spatial import distance
import time
# Load dlib's face detector and facial landmark predictor
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
# Define the indexes of the facial landmarks for the left and right eye
LEFT_EYE = [36, 37, 38, 39, 40, 41]
RIGHT_EYE = [42, 43, 44, 45, 46, 47]
# Eye aspect ratio threshold and consecutive frame count for detecting drowsiness
EYE_ASPECT_RATIO_THRESHOLD = 0.20 # Lowered threshold for more sensitivity
EYE_ASPECT_RATIO_CONSEC_FRAMES = 10 # Reduced to detect drowsiness faster
# Initialize the counter for drowsiness detection
COUNTER = 0
ALERT = False
# Function to calculate the Eye Aspect Ratio (EAR)
def eye_aspect_ratio(eye):
# Compute the euclidean distances between the vertical eye landmarks
A = distance.euclidean(eye[1], eye[5])
B = distance.euclidean(eye[2], eye[4])
# Compute the euclidean distance between the horizontal eye landmarks
C = distance.euclidean(eye[0], eye[3])
# Return the eye aspect ratio
ear = (A + B) / (2.0 * C)
return ear
# Initialize the video stream (camera)
cap = cv2.VideoCapture(0)
while True:
# Capture frame from the camera
ret, frame = cap.read()
# Convert the frame to grayscale for face detection
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Detect faces in the grayscale frame
faces = detector(gray)
for face in faces:
# Get the landmarks for the face
landmarks = predictor(gray, face)
# Get the left and right eye landmarks
left_eye = [(landmarks.part(i).x, landmarks.part(i).y) for i in LEFT_EYE]
right_eye = [(landmarks.part(i).x, landmarks.part(i).y) for i in RIGHT_EYE]
# Calculate the EAR for both eyes
left_ear = eye_aspect_ratio(left_eye)
right_ear = eye_aspect_ratio(right_eye)
# Calculate the average EAR for both eyes
ear = (left_ear + right_ear) / 2.0
# Debugging: Print EAR values
print(f"Left EAR: {left_ear:.2f} Right EAR: {right_ear:.2f} Average EAR: {ear:.2f}")
# Check if EAR is below the threshold, indicating drowsiness
if ear < EYE_ASPECT_RATIO_THRESHOLD:
COUNTER += 1
if COUNTER >= EYE_ASPECT_RATIO_CONSEC_FRAMES:
# Drowsiness detected
if not ALERT:
ALERT = True
print("Drowsiness Detected!")
cv2.putText(frame, "Drowsiness Detected!", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,
0, 255), 2)
else:
COUNTER = 0
ALERT = False
cv2.putText(frame, "Awake", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# Draw the eye contours for visualization
for (x, y) in left_eye + right_eye:
cv2.circle(frame, (x, y), 1, (0, 255, 0), -1)
# Display the resulting frame with status
if ALERT:
# Display "Drowsiness Detected!" when drowsiness is detected
cv2.putText(frame, "Drowsiness Detected!", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0,
255), 3)
else:
# Display "Awake" when the driver is awake
cv2.putText(frame, "Awake", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 3)
# Show the live camera feed with the message
cv2.imshow("Driver Status", frame)
# Exit the loop if 'q' key is pressed
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Release the video capture and close any open windows
cap.release()
cv2.destroyAllWindows()