import cv2 as cv import numpy as np import gradio as gr import os from FaceMeshModule import FaceMeshGenerator from utils import DrawingUtils PASSWORD_FILE = "blink_password.txt" class BlinkCounter: def __init__(self, ear_threshold=0.3, consec_frames=4): self.generator = FaceMeshGenerator() self.RIGHT_EYE_EAR = [33, 159, 158, 133, 153, 145] self.LEFT_EYE_EAR = [362, 380, 374, 263, 386, 385] self.ear_threshold = ear_threshold self.consec_frames = consec_frames self.blink_counter = 0 self.frame_counter = 0 def eye_aspect_ratio(self, eye, landmarks): A = np.linalg.norm(np.array(landmarks[eye[1]]) - np.array(landmarks[eye[5]])) B = np.linalg.norm(np.array(landmarks[eye[2]]) - np.array(landmarks[eye[4]])) C = np.linalg.norm(np.array(landmarks[eye[0]]) - np.array(landmarks[eye[3]])) return (A + B) / (2.0 * C) def update(self, frame): frame, landmarks = self.generator.create_face_mesh(frame, draw=False) if landmarks: right_ear = self.eye_aspect_ratio(self.RIGHT_EYE_EAR, landmarks) left_ear = self.eye_aspect_ratio(self.LEFT_EYE_EAR, landmarks) ear = (right_ear + left_ear) / 2 if ear < self.ear_threshold: self.frame_counter += 1 else: if self.frame_counter >= self.consec_frames: self.blink_counter += 1 self.frame_counter = 0 DrawingUtils.draw_text_with_bg( frame, f"Blinks: {self.blink_counter}", (30, 60), font_scale=1, thickness=2 ) return frame, self.blink_counter blink_system = BlinkCounter() def process_frame(frame): frame = cv.cvtColor(frame, cv.COLOR_RGB2BGR) output, count = blink_system.update(frame) output = cv.cvtColor(output, cv.COLOR_BGR2RGB) return output, f"Blink Count: {count}" demo = gr.Interface( fn=process_frame, inputs=gr.Image(sources=["webcam"], type="numpy"), outputs=[ gr.Image(type="numpy", label="Output Frame"), gr.Text(label="Blink Count") ] , title="Eye Blink Password Authentication (MediaPipe)", description="Blink-based authentication using MediaPipe & OpenCV" ) demo.launch(share=True)