import cv2 import cvzone import numpy as np import os import gradio as gr # Load the YuNet model model_path = 'face_detection_yunet_2023mar.onnx' face_detector = cv2.FaceDetectorYN.create(model_path, "", (320, 320)) # Initialize the glass number num = 1 overlay = cv2.imread(f'glasses/glass{num}.png', cv2.IMREAD_UNCHANGED) # Count glasses files def count_files_in_directory(directory): file_count = 0 for root, dirs, files in os.walk(directory): file_count += len(files) return file_count directory_path = 'glasses' total_glass_num = count_files_in_directory(directory_path) # Change glasses def change_glasses(): global num, overlay num += 1 if num > total_glass_num: num = 1 overlay = cv2.imread(f'glasses/glass{num}.png', cv2.IMREAD_UNCHANGED) return overlay # Process frame for overlay def process_frame(frame): global overlay height, width = frame.shape[:2] face_detector.setInputSize((width, height)) # Detect faces _, faces = face_detector.detect(frame) if faces is not None: for face in faces: # Extract bounding box and facial landmarks x, y, w, h = face[:4].astype(int) face_landmarks = face[4:14].reshape(5, 2).astype(int) # Adjust if needed # Get the nose and eye positions nose_x, nose_y = face_landmarks[2] left_eye_x, left_eye_y = face_landmarks[0] right_eye_x, right_eye_y = face_landmarks[1] # Calculate eye center and rotation angle eye_center_x = (left_eye_x + right_eye_x) // 2 eye_center_y = (left_eye_y + right_eye_y) // 2 delta_x = right_eye_x - left_eye_x delta_y = right_eye_y - left_eye_y angle = np.degrees(np.arctan2(delta_y, delta_x)) # Resize and rotate the overlay overlay_resize = cv2.resize(overlay, (int(w * 1.15), int(h * 0.8))) overlay_center = (overlay_resize.shape[1] // 2, overlay_resize.shape[0] // 2) rotation_matrix = cv2.getRotationMatrix2D(overlay_center, angle, 1.0) overlay_rotated = cv2.warpAffine( overlay_resize, rotation_matrix, (overlay_resize.shape[1], overlay_resize.shape[0]), flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0, 0) ) # Calculate position for overlay overlay_x = max(0, eye_center_x - overlay_rotated.shape[1] // 2) overlay_y = max(0, eye_center_y - overlay_rotated.shape[0] // 2) # Overlay the glasses using cvzone try: frame = cvzone.overlayPNG(frame, overlay_rotated, [overlay_x, overlay_y]) except Exception as e: print(f"Error overlaying glasses: {e}") return frame # Gradio webcam input def webcam_input(frame): frame = process_frame(frame) return frame # Gradio Interface with gr.Blocks() as demo: with gr.Row(): with gr.Column(): input_img = gr.Image(label="Input", sources="webcam", streaming=True) next_button = gr.Button("Next Glasses") input_img.stream(webcam_input, [input_img], [input_img], stream_every=0.1, concurrency_limit=30) next_button.click(change_glasses, [], []) if __name__ == "__main__": demo.launch(share=True)