File size: 2,905 Bytes
aea6c92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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(action):
    global num, overlay
    if action == 'next':
        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))
    _, faces = face_detector.detect(frame)

    if faces is not None:
        for face in faces:
            x, y, w, h = face[:4].astype(int)
            face_landmarks = face[4:14].reshape(5, 2).astype(int)  # Facial landmarks

            # Get the nose position (assuming landmark index 2 is the nose)
            nose_x, nose_y = face_landmarks[2].astype(int)

            # Resize the overlay
            overlay_resize = cv2.resize(overlay, (int(w * 1.15), int(h * 0.8)))

            # Ensure the frame is a NumPy array and writable
            frame = np.array(frame)

            # Calculate the position to center the glasses on the nose
            overlay_x = nose_x - overlay_resize.shape[1] // 2
            overlay_y = y  # Adjust this if needed for better vertical alignment

            # Overlay the glasses
            try:
                frame = cvzone.overlayPNG(frame, overlay_resize, [overlay_x, overlay_y])
            except Exception as e:
                print(f"Error overlaying glasses: {e}")

    return frame

# # Display the frame
# def display_frame():
#     cap = cv2.VideoCapture(0)
#     while True:
#         ret, frame = cap.read()
#         if not ret:
#             break

#         frame = process_frame(frame)
#         cv2.imshow('SnapLens', frame)

#         k = cv2.waitKey(10)
#         if k == ord('q'):
#             break

#     cap.release()
#     cv2.destroyAllWindows()

# display_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)
    input_img.stream(webcam_input, [input_img], [input_img], time_limit=15, stream_every=0.1, concurrency_limit=30)
if __name__ == "__main__":
    demo.launch(share=True)