Reputation: 13
I am trying to find the EAR eye aspect ratio for the below code. which is generated 468 facial_landmarks.
import time
import cv2
import numpy as np
from PIL import Image
from fdlite import FaceDetection, FaceLandmark, face_detection_to_roi
from fdlite.render import Colors, landmarks_to_render_data, render_to_image
EAR_THRESHOLD = 0.2 # Adjust this threshold as needed
def initialize_camera(camera_index=0):
"""
Initialize the video capture from the specified camera index.
Args:
- camera_index (int): Index of the camera to capture video from (default is 0 for the default camera).
Returns:
- cv2.VideoCapture: Video capture object.
"""
cap = cv2.VideoCapture(camera_index)
if not cap.isOpened():
raise ValueError("Failed to initialize the camera.")
return cap
def resize_frame(frame, scale_factor=0.5):
"""
Resize the frame to improve performance.
Args:
- frame (numpy.ndarray): Input frame.
- scale_factor (float): Scaling factor (default is 0.5).
Returns:
- numpy.ndarray: Resized frame.
"""
return cv2.resize(frame, None, fx=scale_factor, fy=scale_factor)
def convert_to_rgb(frame):
"""
Convert the frame from OpenCV's BGR format to RGB (PIL format).
Args:
- frame (numpy.ndarray): Input frame in BGR format.
Returns:
- numpy.ndarray: Frame in RGB format.
"""
return cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
def detect_faces(frame, face_detector):
"""
Detect faces in the frame.
Args:
- frame (numpy.ndarray): Input frame.
- face_detector: Face detection model.
Returns:
- list: List of face detections.
"""
return face_detector(frame)
def detect_landmarks(frame, face_roi, landmark_detector):
"""
Detect landmarks in the face region of interest (ROI).
Args:
- frame (numpy.ndarray): Input frame.
- face_roi (tuple): Region of interest (ROI) containing the face.
- landmark_detector: Landmark detection model.
Returns:
- list: List of facial landmarks.
"""
return landmark_detector(frame, face_roi)
def render_landmarks(frame, landmarks):
"""
Render facial landmarks on the frame.
Args:
- frame (numpy.ndarray): Input frame.
- landmarks (list): List of facial landmarks.
Returns:
- numpy.ndarray: Frame with landmarks rendered.
"""
render_data = landmarks_to_render_data(landmarks, [], landmark_color=Colors.PINK, thickness=3)
pil_frame = Image.fromarray(frame)
return render_to_image(render_data, pil_frame)
def display_frame_with_landmarks(frame, fps):
"""
Display the frame with landmarks and FPS information.
Args:
- frame (numpy.ndarray): Frame with landmarks rendered.
- fps (float): Frames per second.
"""
# Convert the frame to a numpy array before applying OpenCV functions
frame_np = np.array(frame)
# Apply OpenCV functions to the numpy array
cv2.putText(frame_np, f"FPS: {fps:.2f}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
# Display the frame with landmarks and FPS
cv2.imshow("Face Landmarks Detection", frame_np)
def calculate_ear(eye_landmarks):
"""
Calculate the eye aspect ratio (EAR) using the eye landmarks.
Args:
- eye_landmarks (list): List of landmarks for one eye.
Returns:
- float: Eye aspect ratio (EAR).
"""
if len(eye_landmarks) != 6:
return None # Return None if the expected number of landmarks is not found
try:
# Extract relevant points for the eye (assuming the landmarks are in the format Landmark(x, y, z))
# For left eye: 0, 1, 2, 3, 4, 5
# For right eye: 0, 1, 2, 3, 4, 5
v_dist1 = np.linalg.norm(
np.array([eye_landmarks[1].x, eye_landmarks[1].y]) - np.array([eye_landmarks[5].x, eye_landmarks[5].y]))
v_dist2 = np.linalg.norm(
np.array([eye_landmarks[2].x, eye_landmarks[2].y]) - np.array([eye_landmarks[4].x, eye_landmarks[4].y]))
h_dist = np.linalg.norm(
np.array([eye_landmarks[0].x, eye_landmarks[0].y]) - np.array([eye_landmarks[3].x, eye_landmarks[3].y]))
# Prevent division by zero
if h_dist == 0:
return None
ear = (v_dist1 + v_dist2) / (2.0 * h_dist)
return ear
except Exception as e:
print("Error calculating EAR:", e)
return None
def detect_drowsiness(left_eye_landmarks, right_eye_landmarks):
"""
Detect drowsiness based on eye aspect ratio (EAR).
Args:
- left_eye_landmarks (list): List of landmarks for the left eye.
- right_eye_landmarks (list): List of landmarks for the right eye.
Returns:
- bool: True if drowsiness is detected, False otherwise.
"""
left_ear = calculate_ear(left_eye_landmarks)
right_ear = calculate_ear(right_eye_landmarks)
avg_ear = (left_ear + right_ear) / 2.0
print('avg_ear', avg_ear)
if avg_ear < EAR_THRESHOLD:
return True
else:
return False
def main():
# Initialize detection models
detect_faces_model = FaceDetection()
detect_landmarks_model = FaceLandmark()
# Initialize camera
cap = initialize_camera()
# Initialize variables for FPS calculation
frame_count = 0
start_time = time.time()
# Variables for drowsiness detection
CONSECUTIVE_FRAMES_THRESHOLD = 20
closed_eye_frames = 0
while True:
# Read a frame from the video capture
ret, frame = cap.read()
if not ret:
print("Error: Failed to capture frame.")
break
frame_count += 1
# Resize frame for performance
resized_frame = resize_frame(frame)
# Convert frame to RGB format
rgb_frame = convert_to_rgb(resized_frame)
# Detect faces
face_detections = detect_faces(rgb_frame, detect_faces_model)
if face_detections:
# Get ROI for the first face found
face_roi = face_detection_to_roi(face_detections[0], (resized_frame.shape[1], resized_frame.shape[0]))
# Detect face landmarks
landmarks = detect_landmarks(rgb_frame, face_roi, detect_landmarks_model)
# Render landmarks on the frame
frame_with_landmarks = render_landmarks(resized_frame, landmarks)
# Calculate FPS
elapsed_time = time.time() - start_time
fps = frame_count / elapsed_time
# Display frame with landmarks and FPS
display_frame_with_landmarks(frame_with_landmarks, fps)
# Detect drowsiness
left_eye_landmarks = landmarks[0:6] # Assuming the first 6 landmarks correspond to the left eye
right_eye_landmarks = landmarks[6:12] # Assuming the next 6 landmarks correspond to the right eye
if detect_drowsiness(left_eye_landmarks, right_eye_landmarks):
print("Drowsiness detected!")
else:
# Display the original frame if no face is detected
cv2.putText(resized_frame, "No Face Detected", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.imshow("Face Landmarks Detection", resized_frame)
# Check for key press to exit
key = cv2.waitKey(1)
if key == ord('q'):
break
# Release the video capture and close all OpenCV windows
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
The landmarks i got from as result id 3D array as like this Landmark(x=0.6211224, y=0.46492937, z=-0.013669399), Landmark(x=0.66713226, y=0.4619585, z=0.0010283475) for the below line of code
# Detect face landmarks landmarks = detect_landmarks(rgb_frame, face_roi, detect_landmarks_model)
i tried by changing the EAR_THRESHOLD by not working and i am not able to find the where the issue is happening , Kindly help me to find the eye aspect ratio to detect that person is closed his/her eyes.
Upvotes: 0
Views: 51