Spaces:
Sleeping
Sleeping
Upload 65 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +1 -0
- app.py +690 -0
- constants.py +62 -0
- requirements.txt +5 -0
- stickers/.DS_Store +0 -0
- stickers/animal face/.DS_Store +0 -0
- stickers/animal face/None.png +0 -0
- stickers/animal face/blowing.png +0 -0
- stickers/animal face/cool.png +0 -0
- stickers/animal face/cry.png +0 -0
- stickers/animal face/evil.png +0 -0
- stickers/animal face/laughing.png +0 -0
- stickers/animal face/logy.png +0 -0
- stickers/animal face/love.png +0 -0
- stickers/animal face/mysterious.png +0 -0
- stickers/ears/.DS_Store +0 -0
- stickers/ears/None.png +0 -0
- stickers/ears/bent.png +0 -0
- stickers/ears/bunny.png +0 -0
- stickers/ears/bunny2.png +0 -0
- stickers/ears/carrot.png +0 -0
- stickers/ears/fluffy.png +0 -0
- stickers/ears/fox.png +0 -0
- stickers/ears/tiger.png +0 -0
- stickers/ears/white.png +0 -0
- stickers/glasses/.DS_Store +0 -0
- stickers/glasses/None.png +0 -0
- stickers/glasses/blue.png +0 -0
- stickers/glasses/cool.png +0 -0
- stickers/glasses/gray.png +0 -0
- stickers/glasses/heart.png +0 -0
- stickers/glasses/pink.png +0 -0
- stickers/glasses/rainbow.png +0 -0
- stickers/glasses/reading.png +0 -0
- stickers/glasses/round.png +0 -0
- stickers/hats/.DS_Store +0 -0
- stickers/hats/Christmas.png +0 -0
- stickers/hats/None.png +0 -0
- stickers/hats/chef.png +0 -0
- stickers/hats/green.png +0 -0
- stickers/hats/mexican.png +0 -0
- stickers/hats/party.png +0 -0
- stickers/hats/santa.png +0 -0
- stickers/hats/top.png +0 -0
- stickers/hats/witch.png +0 -0
- stickers/headbands/.DS_Store +0 -0
- stickers/headbands/None.png +0 -0
- stickers/headbands/blue.png +0 -0
- stickers/headbands/bow.png +0 -0
- stickers/headbands/cat.png +0 -0
.gitattributes
CHANGED
@@ -34,3 +34,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
shape_predictor_81_face_landmarks.dat filter=lfs diff=lfs merge=lfs -text
|
|
|
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
shape_predictor_81_face_landmarks.dat filter=lfs diff=lfs merge=lfs -text
|
37 |
+
stickers/noses/clown.png filter=lfs diff=lfs merge=lfs -text
|
app.py
ADDED
@@ -0,0 +1,690 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import cv2
|
3 |
+
import numpy as np
|
4 |
+
from PIL import Image
|
5 |
+
import dlib
|
6 |
+
import os
|
7 |
+
import math
|
8 |
+
|
9 |
+
from constants import *
|
10 |
+
|
11 |
+
MAX_EXPECTED_FACES=7
|
12 |
+
# get a list of faces in the image
|
13 |
+
def face_detecting(image):
|
14 |
+
detector = dlib.get_frontal_face_detector()
|
15 |
+
faces = detector(image, 1)
|
16 |
+
return faces
|
17 |
+
|
18 |
+
# show all the faces in rectangles in the image
|
19 |
+
def face_showing(image, faces):
|
20 |
+
for face in faces:
|
21 |
+
cv2.rectangle(image, (face.left(), face.top()), (face.right(), face.bottom()), (255, 255, 255), 2)
|
22 |
+
return image
|
23 |
+
|
24 |
+
# highlight the selected face in the image, using index to select the face
|
25 |
+
def face_selecting(image, faces, index):
|
26 |
+
face = faces[index]
|
27 |
+
cv2.rectangle(image, (face.left(), face.top()), (face.right(), face.bottom()), (255, 255, 255), 2)
|
28 |
+
return image
|
29 |
+
|
30 |
+
# get the landmarks of the face
|
31 |
+
def face_landmarking(image, face):
|
32 |
+
predictor = dlib.shape_predictor('shape_predictor_81_face_landmarks.dat')
|
33 |
+
landmarks = predictor(image, face)
|
34 |
+
return landmarks
|
35 |
+
|
36 |
+
|
37 |
+
# Function to overlay a transparent image onto another image
|
38 |
+
def overlay_transparent(background, overlay, x, y):
|
39 |
+
bg_height, bg_width = background.shape[:2]
|
40 |
+
if x >= bg_width or y >= bg_height:
|
41 |
+
return background
|
42 |
+
|
43 |
+
h, w = overlay.shape[:2]
|
44 |
+
if x + w > bg_width:
|
45 |
+
w = bg_width - x
|
46 |
+
overlay = overlay[:, :w]
|
47 |
+
|
48 |
+
if y + h > bg_height:
|
49 |
+
h = bg_height - y
|
50 |
+
overlay = overlay[:h]
|
51 |
+
|
52 |
+
if overlay.shape[2] < 4:
|
53 |
+
overlay = np.concatenate([overlay, np.ones((overlay.shape[0], overlay.shape[1], 1), dtype=overlay.dtype) * 255], axis=2)
|
54 |
+
|
55 |
+
overlay_img = overlay[..., :3]
|
56 |
+
mask = overlay[..., 3:] / 255.0
|
57 |
+
|
58 |
+
background[y:y+h, x:x+w] = (1.0 - mask) * background[y:y+h, x:x+w] + mask * overlay_img
|
59 |
+
|
60 |
+
return background
|
61 |
+
|
62 |
+
|
63 |
+
def calculate_eye_angle(landmarks, left_eye_indices, right_eye_indices):
|
64 |
+
|
65 |
+
# Calculate the center point of the left eye
|
66 |
+
left_eye_center = (
|
67 |
+
sum([landmarks.part(i).x for i in left_eye_indices]) // len(left_eye_indices),
|
68 |
+
sum([landmarks.part(i).y for i in left_eye_indices]) // len(left_eye_indices)
|
69 |
+
)
|
70 |
+
|
71 |
+
# Calculate the center point of the right eye
|
72 |
+
right_eye_center = (
|
73 |
+
sum([landmarks.part(i).x for i in right_eye_indices]) // len(right_eye_indices),
|
74 |
+
sum([landmarks.part(i).y for i in right_eye_indices]) // len(right_eye_indices)
|
75 |
+
)
|
76 |
+
|
77 |
+
# Calculate the differences in the x and y coordinates between the centers of the eyes
|
78 |
+
dx = right_eye_center[0] - left_eye_center[0]
|
79 |
+
dy = right_eye_center[1] - left_eye_center[1]
|
80 |
+
|
81 |
+
# Calculate the angle using the arctangent of the differences
|
82 |
+
angle = math.degrees(math.atan2(dy, dx))
|
83 |
+
|
84 |
+
return angle
|
85 |
+
|
86 |
+
|
87 |
+
# Function to add ear stickers
|
88 |
+
def add_ears_sticker(img_bgr, sticker_path, faces):
|
89 |
+
ears_pil = Image.open(sticker_path)
|
90 |
+
|
91 |
+
# Check the color mode and convert to RGBA
|
92 |
+
ears_rgba = ears_pil.convert('RGBA')
|
93 |
+
|
94 |
+
# Convert the ears_rgba to BGRA
|
95 |
+
r, g, b, a = ears_rgba.split()
|
96 |
+
ears_bgra = Image.merge("RGBA", (b, g, r, a))
|
97 |
+
|
98 |
+
|
99 |
+
# A copy of the original image
|
100 |
+
img_with_stickers = img_bgr.copy()
|
101 |
+
|
102 |
+
for face in faces:
|
103 |
+
landmarks = face_landmarking(img_bgr, face)
|
104 |
+
|
105 |
+
# the landmarks 68 to 80 are for the forehead
|
106 |
+
forehead = [landmarks.part(i) for i in range(68, 81)]
|
107 |
+
|
108 |
+
# The landmarks 36 to 41 are for the left eye, and 42 to 47 are for the right eye
|
109 |
+
left_eye = [landmarks.part(i) for i in range(36, 42)]
|
110 |
+
right_eye = [landmarks.part(i) for i in range(42, 48)]
|
111 |
+
|
112 |
+
# Calculate the center point between the eyes
|
113 |
+
left_eye_center = ((left_eye[0].x + left_eye[3].x) // 2, (left_eye[0].y + left_eye[3].y) // 2)
|
114 |
+
right_eye_center = ((right_eye[0].x + right_eye[3].x) // 2, (right_eye[0].y + right_eye[3].y) // 2)
|
115 |
+
|
116 |
+
# Calculate the angle of tilt
|
117 |
+
dx = right_eye_center[0] - left_eye_center[0]
|
118 |
+
dy = right_eye_center[1] - left_eye_center[1]
|
119 |
+
angle = math.degrees(math.atan2(dy, dx))
|
120 |
+
|
121 |
+
|
122 |
+
# Calculate the bounding box for the ears based on the eye landmarks
|
123 |
+
ears_width = int(abs(forehead[0].x - forehead[-1].x) * 2.1)
|
124 |
+
ears_height = int(ears_width * ears_bgra.height / ears_bgra.width)
|
125 |
+
|
126 |
+
# Resize the ears image
|
127 |
+
resized_ears_pil = ears_bgra.resize((ears_width, ears_height))
|
128 |
+
rotated_ears = resized_ears_pil.rotate(-angle, expand=True, resample=Image.BICUBIC)
|
129 |
+
|
130 |
+
# Calculate the position for the ears
|
131 |
+
y1 = min([point.y for point in forehead]) - int(0.7 * ears_height)
|
132 |
+
x1 = forehead[0].x - int(0.2 * ears_width)
|
133 |
+
|
134 |
+
# Convert PIL image to NumPy array
|
135 |
+
# ears_np = np.array(resized_ears_pil)
|
136 |
+
ears_np = np.array(rotated_ears)
|
137 |
+
|
138 |
+
# Overlay the ears on the image
|
139 |
+
img_with_stickers = overlay_transparent(img_with_stickers, ears_np, x1, y1)
|
140 |
+
|
141 |
+
return img_with_stickers
|
142 |
+
|
143 |
+
# Function to add hats stickers
|
144 |
+
def add_hats_sticker(img_bgr, sticker_path, faces):
|
145 |
+
hat_pil = Image.open(sticker_path)
|
146 |
+
|
147 |
+
# Check the color mode and convert to RGBA
|
148 |
+
hat_rgba = hat_pil.convert('RGBA')
|
149 |
+
|
150 |
+
# Convert the hat_rgba to BGRA
|
151 |
+
r, g, b, a = hat_rgba.split()
|
152 |
+
hat_bgra = Image.merge("RGBA", (b, g, r, a))
|
153 |
+
|
154 |
+
# A copy of the original image
|
155 |
+
img_with_stickers = img_bgr.copy()
|
156 |
+
|
157 |
+
for face in faces:
|
158 |
+
landmarks = face_landmarking(img_bgr, face)
|
159 |
+
|
160 |
+
# The landmarks 36 to 41 are for the left eye, and 42 to 47 are for the right eye
|
161 |
+
left_eye = [landmarks.part(i) for i in range(36, 42)]
|
162 |
+
right_eye = [landmarks.part(i) for i in range(42, 48)]
|
163 |
+
|
164 |
+
forehead = [landmarks.part(i) for i in range(68, 81)]
|
165 |
+
|
166 |
+
# Calculate the center point between the eyes
|
167 |
+
left_eye_center = ((left_eye[0].x + left_eye[3].x) // 2, (left_eye[0].y + left_eye[3].y) // 2)
|
168 |
+
right_eye_center = ((right_eye[0].x + right_eye[3].x) // 2, (right_eye[0].y + right_eye[3].y) // 2)
|
169 |
+
eye_center_x = (left_eye_center[0] + right_eye_center[0]) // 2
|
170 |
+
eye_center_y = (left_eye_center[1] + right_eye_center[1]) // 2
|
171 |
+
|
172 |
+
# Calculate the angle of tilt
|
173 |
+
dx = right_eye_center[0] - left_eye_center[0]
|
174 |
+
dy = right_eye_center[1] - left_eye_center[1]
|
175 |
+
angle = math.degrees(math.atan2(dy, dx))
|
176 |
+
|
177 |
+
# Calculate the size of the hat based on the width between the eyes
|
178 |
+
hat_width = int(abs(left_eye[0].x - right_eye[3].x) * 1.75)
|
179 |
+
hat_height = int(hat_width * hat_bgra.height / hat_bgra.width)
|
180 |
+
|
181 |
+
# Resize and rotate the hat image
|
182 |
+
resized_hat = hat_bgra.resize((hat_width, hat_height))
|
183 |
+
rotated_hat = resized_hat.rotate(-0.8*angle, expand=True, resample=Image.BICUBIC)
|
184 |
+
|
185 |
+
|
186 |
+
# Calculate the position for the hat
|
187 |
+
y1 = eye_center_y - hat_height - int(0.3 * hat_height)
|
188 |
+
# x1 = eye_center_x - (hat_width // 2) # Centering the hat on the midpoint between the eyes
|
189 |
+
# x1 = eye_center_x - (hat_width // 2) - int(0.03 * hat_width) # Moving the hat a bit further to the left
|
190 |
+
x1 = forehead[0].x - int(0.2 * hat_width)
|
191 |
+
# Convert PIL image to NumPy array
|
192 |
+
hat_np = np.array(rotated_hat)
|
193 |
+
|
194 |
+
# Overlay the hat on the image
|
195 |
+
img_with_stickers = overlay_transparent(img_with_stickers, hat_np, x1, y1)
|
196 |
+
|
197 |
+
return img_with_stickers
|
198 |
+
|
199 |
+
def add_headbands_sticker(img_bgr, sticker_path, faces):
|
200 |
+
headband_pil = Image.open(sticker_path)
|
201 |
+
|
202 |
+
# Check the color mode and convert to RGBA
|
203 |
+
headband_rgba = headband_pil.convert('RGBA')
|
204 |
+
|
205 |
+
# Convert the headband_rgba to BGRA
|
206 |
+
r, g, b, a = headband_rgba.split()
|
207 |
+
headband_bgra = Image.merge("RGBA", (b, g, r, a))
|
208 |
+
|
209 |
+
# A copy of the original image
|
210 |
+
img_with_stickers = img_bgr.copy()
|
211 |
+
|
212 |
+
for face in faces:
|
213 |
+
landmarks = face_landmarking(img_bgr, face)
|
214 |
+
|
215 |
+
# Determine the forehead region using landmarks
|
216 |
+
# Assuming the headband will be placed between the temples
|
217 |
+
left_temple = landmarks.part(0)
|
218 |
+
right_temple = landmarks.part(16)
|
219 |
+
|
220 |
+
# Calculate the width of the headband based on the temples
|
221 |
+
headband_width = int(abs(left_temple.x - right_temple.x) * 1.6)
|
222 |
+
headband_height = int(headband_width * headband_bgra.height / headband_bgra.width)
|
223 |
+
|
224 |
+
# Resize the headband image
|
225 |
+
resized_headband = headband_bgra.resize((headband_width, headband_height))
|
226 |
+
|
227 |
+
# Calculate the angle of tilt using the eyes as reference
|
228 |
+
left_eye_indices = range(36, 42)
|
229 |
+
right_eye_indices = range(42, 48)
|
230 |
+
angle = calculate_eye_angle(landmarks, left_eye_indices, right_eye_indices)
|
231 |
+
|
232 |
+
# Rotate the headband image
|
233 |
+
rotated_headband = resized_headband.rotate(-angle, expand=True, resample=Image.BICUBIC)
|
234 |
+
|
235 |
+
# Calculate the position for the headband
|
236 |
+
x1 = (left_temple.x + right_temple.x) // 2 - (headband_width // 2)
|
237 |
+
y1 = left_temple.y - (headband_height // 2)
|
238 |
+
|
239 |
+
# Convert PIL image to NumPy array
|
240 |
+
headband_np = np.array(rotated_headband)
|
241 |
+
|
242 |
+
# Overlay the headband on the image
|
243 |
+
img_with_stickers = overlay_transparent(img_with_stickers, headband_np, x1, y1)
|
244 |
+
|
245 |
+
return img_with_stickers
|
246 |
+
|
247 |
+
|
248 |
+
# Function to add glasses stickers
|
249 |
+
def add_glasses_sticker(img_bgr, sticker_path, faces):
|
250 |
+
glasses_pil = Image.open(sticker_path)
|
251 |
+
|
252 |
+
# Check the color mode and convert to RGBA
|
253 |
+
glasses_rgba = glasses_pil.convert('RGBA')
|
254 |
+
|
255 |
+
# Convert the glasses_rgba to BGRA
|
256 |
+
r, g, b, a = glasses_rgba.split()
|
257 |
+
glasses_bgra = Image.merge("RGBA", (b, g, r, a))
|
258 |
+
|
259 |
+
# A copy of the original image
|
260 |
+
img_with_stickers = img_bgr.copy()
|
261 |
+
|
262 |
+
for face in faces:
|
263 |
+
landmarks = face_landmarking(img_bgr, face)
|
264 |
+
|
265 |
+
# the landmarks 36 to 41 are for the left eye, and 42 to 47 are for the right eye
|
266 |
+
left_eye = [landmarks.part(i) for i in range(36, 42)]
|
267 |
+
right_eye = [landmarks.part(i) for i in range(42, 48)]
|
268 |
+
|
269 |
+
# Calculate the center points of the eyes
|
270 |
+
left_eye_center = (sum([p.x for p in left_eye]) // len(left_eye), sum([p.y for p in left_eye]) // len(left_eye))
|
271 |
+
right_eye_center = (sum([p.x for p in right_eye]) // len(right_eye), sum([p.y for p in right_eye]) // len(right_eye))
|
272 |
+
|
273 |
+
# Calculate the angle of tilt
|
274 |
+
dx = right_eye_center[0] - left_eye_center[0]
|
275 |
+
dy = right_eye_center[1] - left_eye_center[1]
|
276 |
+
angle = math.degrees(math.atan2(dy, dx)) # Angle in degrees
|
277 |
+
|
278 |
+
# Calculate the bounding box for the glasses based on the eye landmarks
|
279 |
+
glasses_width = int(abs(left_eye_center[0] - right_eye_center[0]) * 2)
|
280 |
+
glasses_height = int(glasses_width * glasses_bgra.height / glasses_bgra.width)
|
281 |
+
|
282 |
+
# Resize and rotate the glasses image
|
283 |
+
resized_glasses = glasses_bgra.resize((glasses_width, glasses_height))
|
284 |
+
rotated_glasses = resized_glasses.rotate(-0.8*angle, expand=True, resample=Image.BICUBIC) # Negative angle to correct orientation
|
285 |
+
|
286 |
+
# Calculate the position for the glasses, adjusting for the rotation
|
287 |
+
x1 = left_eye_center[0] - int(0.25 * glasses_width)
|
288 |
+
y1 = min(left_eye_center[1], right_eye_center[1]) - int(0.45 * glasses_height)
|
289 |
+
|
290 |
+
# Convert PIL image to NumPy array
|
291 |
+
glasses_np = np.array(rotated_glasses)
|
292 |
+
|
293 |
+
# Overlay the glasses on the image
|
294 |
+
img_with_stickers = overlay_transparent(img_with_stickers, glasses_np, x1, y1)
|
295 |
+
|
296 |
+
return img_with_stickers
|
297 |
+
|
298 |
+
|
299 |
+
|
300 |
+
def add_noses_sticker(img_bgr, sticker_path, faces):
|
301 |
+
nose_pil = Image.open(sticker_path)
|
302 |
+
|
303 |
+
# Check the color mode and convert to RGBA
|
304 |
+
nose_rgba = nose_pil.convert('RGBA')
|
305 |
+
|
306 |
+
# Convert the nose_rgba to BGRA
|
307 |
+
r, g, b, a = nose_rgba.split()
|
308 |
+
nose_bgra = Image.merge("RGBA", (b, g, r, a))
|
309 |
+
|
310 |
+
# A copy of the original image
|
311 |
+
img_with_stickers = img_bgr.copy()
|
312 |
+
|
313 |
+
for face in faces:
|
314 |
+
landmarks = face_landmarking(img_bgr, face)
|
315 |
+
|
316 |
+
# Assuming that the landmarks 27 to 35 are for the nose area
|
317 |
+
nose_area = [landmarks.part(i) for i in range(27, 36)]
|
318 |
+
|
319 |
+
# Calculate the bounding box for the nose based on the nose landmarks
|
320 |
+
nose_width = int(abs(nose_area[0].x - nose_area[-1].x) * 2.1)
|
321 |
+
nose_height = int(nose_width * nose_bgra.height / nose_bgra.width)
|
322 |
+
|
323 |
+
# the landmarks 31 and 35 are the leftmost and rightmost points of the nose area
|
324 |
+
nose_left = landmarks.part(31)
|
325 |
+
nose_right = landmarks.part(35)
|
326 |
+
|
327 |
+
# Calculate the center point of the nose
|
328 |
+
nose_center_x = (nose_left.x + nose_right.x) // 2
|
329 |
+
|
330 |
+
nose_top = landmarks.part(27) # Use 28 if it's more accurate
|
331 |
+
nose_bottom = landmarks.part(33)
|
332 |
+
|
333 |
+
# Calculate the midpoint of the vertical length of the nose
|
334 |
+
nose_center_y = (nose_top.y + nose_bottom.y) // 2
|
335 |
+
|
336 |
+
# Calculate the angle of tilt using the eyes as reference
|
337 |
+
left_eye_indices = range(36, 42)
|
338 |
+
right_eye_indices = range(42, 48)
|
339 |
+
angle = calculate_eye_angle(landmarks, left_eye_indices, right_eye_indices)
|
340 |
+
|
341 |
+
# Resize the nose image
|
342 |
+
resized_nose_pil = nose_bgra.resize((nose_width, nose_height))
|
343 |
+
|
344 |
+
rotated_nose = resized_nose_pil.rotate(-angle, expand=True, resample=Image.BICUBIC)
|
345 |
+
|
346 |
+
|
347 |
+
# the position for the nose
|
348 |
+
x1 = nose_center_x - (nose_width // 2)
|
349 |
+
y1 = nose_center_y - (nose_height // 2)+ int(0.1 * nose_height) # Adding a slight downward offset
|
350 |
+
# Convert PIL image to NumPy array
|
351 |
+
nose_np = np.array(rotated_nose)
|
352 |
+
|
353 |
+
# Overlay the nose on the image
|
354 |
+
img_with_stickers = overlay_transparent(img_with_stickers, nose_np, x1, y1)
|
355 |
+
|
356 |
+
return img_with_stickers
|
357 |
+
|
358 |
+
def add_animal_faces_sticker(img_bgr, sticker_path, faces):
|
359 |
+
animal_face_pil = Image.open(sticker_path)
|
360 |
+
|
361 |
+
# Check the color mode and convert to RGBA
|
362 |
+
animal_face_rgba = animal_face_pil.convert('RGBA')
|
363 |
+
|
364 |
+
# Convert the animal_face_rgba to BGRA
|
365 |
+
r, g, b, a = animal_face_rgba.split()
|
366 |
+
animal_face_bgra = Image.merge("RGBA", (b, g, r, a))
|
367 |
+
|
368 |
+
# A copy of the original image
|
369 |
+
img_with_stickers = img_bgr.copy()
|
370 |
+
|
371 |
+
for face in faces:
|
372 |
+
landmarks = face_landmarking(img_bgr, face)
|
373 |
+
|
374 |
+
# Find the top of the forehead using landmarks above the eyes
|
375 |
+
# Assuming landmarks 19 to 24 represent the eyebrows
|
376 |
+
forehead_top = min(landmarks.part(i).y for i in range(68, 81))
|
377 |
+
|
378 |
+
# Calculate the center point between the eyes as an anchor
|
379 |
+
left_eye = [landmarks.part(i) for i in range(36, 42)]
|
380 |
+
right_eye = [landmarks.part(i) for i in range(42, 48)]
|
381 |
+
eye_center_x = (left_eye[0].x + right_eye[3].x) // 2
|
382 |
+
eye_center_y = (left_eye[3].y + right_eye[0].y) // 2
|
383 |
+
|
384 |
+
# Calculate the size of the animal face sticker based on the width between the temples
|
385 |
+
head_width = int(abs(landmarks.part(0).x - landmarks.part(16).x)*1.4)
|
386 |
+
head_height = int(head_width * animal_face_bgra.height *1.2 / animal_face_bgra.width)
|
387 |
+
|
388 |
+
|
389 |
+
# Calculate the angle of tilt using the eyes as reference
|
390 |
+
left_eye_indices = range(36, 42)
|
391 |
+
right_eye_indices = range(42, 48)
|
392 |
+
angle = calculate_eye_angle(landmarks, left_eye_indices, right_eye_indices)
|
393 |
+
|
394 |
+
# Resize the animal face sticker
|
395 |
+
resized_animal_face = animal_face_bgra.resize((head_width, head_height))
|
396 |
+
|
397 |
+
rotated_animal_face = resized_animal_face.rotate(-angle, expand=True, resample=Image.BICUBIC)
|
398 |
+
|
399 |
+
|
400 |
+
# Calculate the position for the animal face sticker
|
401 |
+
x1 = eye_center_x - (head_width // 2)
|
402 |
+
y1 = forehead_top - int(0.18 * head_height)
|
403 |
+
|
404 |
+
# Convert PIL image to NumPy array
|
405 |
+
animal_face_np = np.array(rotated_animal_face)
|
406 |
+
|
407 |
+
# Overlay the animal face on the image
|
408 |
+
img_with_stickers = overlay_transparent(img_with_stickers, animal_face_np, x1, y1)
|
409 |
+
|
410 |
+
return img_with_stickers
|
411 |
+
|
412 |
+
|
413 |
+
# Function to process the image
|
414 |
+
def process_image(image, sticker_choice):
|
415 |
+
if sticker_choice:
|
416 |
+
# add .png to the sticker_choice
|
417 |
+
sticker_name = sticker_choice + '.png'
|
418 |
+
# find sticker's category
|
419 |
+
sticker_category = STICKER_TO_CATEGORY[sticker_name]
|
420 |
+
# Path to the single sticker
|
421 |
+
sticker_path = os.path.join('stickers',sticker_category, sticker_name)
|
422 |
+
|
423 |
+
# Convert PIL image to OpenCV format BGR
|
424 |
+
image_bgr = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
|
425 |
+
|
426 |
+
# Detect faces
|
427 |
+
faces = face_detecting(image_bgr)
|
428 |
+
# print(sticker_category)
|
429 |
+
if sticker_category == 'ears':
|
430 |
+
img_with_stickers = add_ears_sticker(image_bgr, sticker_path, faces)
|
431 |
+
elif sticker_category == 'glasses':
|
432 |
+
img_with_stickers = add_glasses_sticker(image_bgr, sticker_path, faces)
|
433 |
+
elif sticker_category == 'noses':
|
434 |
+
img_with_stickers = add_noses_sticker(image_bgr, sticker_path, faces)
|
435 |
+
elif sticker_category == 'headbands':
|
436 |
+
img_with_stickers = add_ears_sticker(image_bgr, sticker_path, faces)
|
437 |
+
else:
|
438 |
+
img_with_stickers = add_glasses_sticker(image_bgr, sticker_path, faces)
|
439 |
+
# Convert back to PIL image
|
440 |
+
img_with_stickers_pil = Image.fromarray(cv2.cvtColor(img_with_stickers, cv2.COLOR_BGR2RGB))
|
441 |
+
return img_with_stickers_pil
|
442 |
+
else:
|
443 |
+
return image
|
444 |
+
|
445 |
+
def process_image_with_selections(image_input):
|
446 |
+
# Convert PIL image to OpenCV format BGR
|
447 |
+
image_bgr = cv2.cvtColor(np.array(image_input), cv2.COLOR_RGB2BGR)
|
448 |
+
|
449 |
+
# Detect faces
|
450 |
+
faces = face_detecting(image_bgr)
|
451 |
+
|
452 |
+
# A copy of the original image to apply stickers on
|
453 |
+
img_with_stickers = image_bgr.copy()
|
454 |
+
|
455 |
+
for category, sticker_name in sticker_selections.items():
|
456 |
+
if sticker_name: # Check if a sticker was selected in this category
|
457 |
+
# the sticker file path
|
458 |
+
sticker_path = os.path.join('stickers', category, sticker_name + '.png')
|
459 |
+
|
460 |
+
# Apply the selected sticker based on its category
|
461 |
+
if category == 'ears':
|
462 |
+
img_with_stickers = add_ears_sticker(img_with_stickers, sticker_path, faces)
|
463 |
+
elif category == 'glasses':
|
464 |
+
img_with_stickers = add_glasses_sticker(img_with_stickers, sticker_path, faces)
|
465 |
+
elif category == 'noses':
|
466 |
+
img_with_stickers = add_noses_sticker(img_with_stickers, sticker_path, faces)
|
467 |
+
elif category == 'headbands':
|
468 |
+
img_with_stickers = add_hats_sticker(img_with_stickers, sticker_path, faces)
|
469 |
+
elif category == 'hats':
|
470 |
+
img_with_stickers = add_hats_sticker(img_with_stickers, sticker_path, faces)
|
471 |
+
elif category == 'animal face':
|
472 |
+
img_with_stickers = add_animal_faces_sticker(img_with_stickers, sticker_path, faces)
|
473 |
+
else:
|
474 |
+
img_with_stickers = img_with_stickers
|
475 |
+
# Convert back to PIL image
|
476 |
+
img_with_stickers_pil = Image.fromarray(cv2.cvtColor(img_with_stickers, cv2.COLOR_BGR2RGB))
|
477 |
+
|
478 |
+
print("Selected stickers:")
|
479 |
+
for category, selection in sticker_selections.items():
|
480 |
+
print(f"{category}: {selection}")
|
481 |
+
|
482 |
+
return img_with_stickers_pil
|
483 |
+
|
484 |
+
# This dictionary will hold the user's sticker selections
|
485 |
+
sticker_selections = {}
|
486 |
+
|
487 |
+
# Function to update sticker selections
|
488 |
+
def update_selections(category, selection):
|
489 |
+
# sticker_selections[category] = selection
|
490 |
+
sticker_selections[category] = None if selection == "None" else selection
|
491 |
+
return ""
|
492 |
+
|
493 |
+
# Function to load an example image
|
494 |
+
def load_example_image(image_path):
|
495 |
+
return gr.Image.from_file(image_path)
|
496 |
+
|
497 |
+
from PIL import Image
|
498 |
+
|
499 |
+
def resize_image(image, target_width, target_height):
|
500 |
+
# Maintain aspect ratio
|
501 |
+
original_width, original_height = image.size
|
502 |
+
ratio = min(target_width/original_width, target_height/original_height)
|
503 |
+
new_width = int(original_width * ratio)
|
504 |
+
new_height = int(original_height * ratio)
|
505 |
+
# Use Image.LANCZOS for high-quality downsampling
|
506 |
+
resized_image = image.resize((new_width, new_height), Image.LANCZOS)
|
507 |
+
return resized_image
|
508 |
+
|
509 |
+
def get_face_crops(image_bgr, faces, target_width=500, target_height=130):
|
510 |
+
face_crops = []
|
511 |
+
for face in faces:
|
512 |
+
x, y, w, h = face.left(), face.top(), face.width(), face.height()
|
513 |
+
face_crop = image_bgr[y:y+h, x:x+w]
|
514 |
+
face_pil = Image.fromarray(cv2.cvtColor(face_crop, cv2.COLOR_BGR2RGB))
|
515 |
+
# Resize image to fit the display while maintaining aspect ratio
|
516 |
+
resized_face = resize_image(face_pil, target_width, target_height)
|
517 |
+
face_crops.append(resized_face)
|
518 |
+
return face_crops
|
519 |
+
|
520 |
+
|
521 |
+
def get_face_crops2(image_bgr, faces):
|
522 |
+
# Convert color space from BGR to RGB since OpenCV uses BGR by default
|
523 |
+
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
|
524 |
+
face_crops = []
|
525 |
+
for face in faces:
|
526 |
+
# Extract the region of interest (the face) from the original image
|
527 |
+
x, y, w, h = face.left(), face.top(), face.width(), face.height()
|
528 |
+
face_crop = image_rgb[y:y+h, x:x+w]
|
529 |
+
face_pil = Image.fromarray(face_crop)
|
530 |
+
face_crops.append(face_pil)
|
531 |
+
return face_crops
|
532 |
+
|
533 |
+
# Function to process uploaded images and display face crops
|
534 |
+
def process_and_show_faces(image_input):
|
535 |
+
# Convert PIL image to OpenCV format BGR
|
536 |
+
image_bgr = cv2.cvtColor(np.array(image_input), cv2.COLOR_RGB2BGR)
|
537 |
+
# Detect faces
|
538 |
+
faces = face_detecting(image_bgr)
|
539 |
+
# Get individual face crops
|
540 |
+
face_crops = get_face_crops(image_bgr, faces)
|
541 |
+
# Return face crops to display them in the interface
|
542 |
+
return face_crops
|
543 |
+
|
544 |
+
|
545 |
+
face_outputs = []
|
546 |
+
for i in range(MAX_EXPECTED_FACES):
|
547 |
+
face_output = gr.Image(label=f"Face {i+1}")
|
548 |
+
face_outputs.append(face_output)
|
549 |
+
|
550 |
+
# This list will hold the Checkbox components for each face
|
551 |
+
checkboxes = []
|
552 |
+
|
553 |
+
def process_selected_faces(image_input, selected_face_indices):
|
554 |
+
# Convert PIL image to OpenCV format BGR
|
555 |
+
image_bgr = cv2.cvtColor(np.array(image_input), cv2.COLOR_RGB2BGR)
|
556 |
+
|
557 |
+
# Detect all faces
|
558 |
+
all_faces = face_detecting(image_bgr)
|
559 |
+
|
560 |
+
# Filter faces to get only those selected
|
561 |
+
faces = [all_faces[i] for i in selected_face_indices]
|
562 |
+
|
563 |
+
img_with_stickers = image_bgr.copy()
|
564 |
+
|
565 |
+
for category, sticker_name in sticker_selections.items():
|
566 |
+
if sticker_name: # Check if a sticker was selected in this category
|
567 |
+
# the sticker file path
|
568 |
+
sticker_path = os.path.join('stickers', category, sticker_name + '.png')
|
569 |
+
|
570 |
+
# Apply the selected sticker based on its category
|
571 |
+
if category == 'ears':
|
572 |
+
img_with_stickers = add_ears_sticker(img_with_stickers, sticker_path, faces)
|
573 |
+
elif category == 'glasses':
|
574 |
+
img_with_stickers = add_glasses_sticker(img_with_stickers, sticker_path, faces)
|
575 |
+
elif category == 'noses':
|
576 |
+
img_with_stickers = add_noses_sticker(img_with_stickers, sticker_path, faces)
|
577 |
+
elif category == 'headbands':
|
578 |
+
img_with_stickers = add_hats_sticker(img_with_stickers, sticker_path, faces)
|
579 |
+
elif category == 'hats':
|
580 |
+
img_with_stickers = add_hats_sticker(img_with_stickers, sticker_path, faces)
|
581 |
+
elif category == 'animal face':
|
582 |
+
img_with_stickers = add_animal_faces_sticker(img_with_stickers, sticker_path, faces)
|
583 |
+
else:
|
584 |
+
img_with_stickers = img_with_stickers
|
585 |
+
# Convert back to PIL image
|
586 |
+
img_with_stickers_pil = Image.fromarray(cv2.cvtColor(img_with_stickers, cv2.COLOR_BGR2RGB))
|
587 |
+
|
588 |
+
print("Selected stickers:")
|
589 |
+
for category, selection in sticker_selections.items():
|
590 |
+
print(f"{category}: {selection}")
|
591 |
+
|
592 |
+
return img_with_stickers_pil
|
593 |
+
|
594 |
+
def handle_face_selection(image_input, *checkbox_states):
|
595 |
+
selected_face_indices = [i for i, checked in enumerate(checkbox_states) if checked]
|
596 |
+
print("selected_face_indices:",selected_face_indices)
|
597 |
+
return process_selected_faces(image_input, selected_face_indices)
|
598 |
+
|
599 |
+
def update_interface_with_faces(image_input):
|
600 |
+
image_bgr = cv2.cvtColor(np.array(image_input), cv2.COLOR_RGB2BGR)
|
601 |
+
faces = face_detecting(image_bgr)
|
602 |
+
face_crops = get_face_crops(image_bgr, faces)
|
603 |
+
return [(face, f"Face {i+1}") for i, face in enumerate(face_crops)]
|
604 |
+
|
605 |
+
def detect_and_display_faces(image_input):
|
606 |
+
image_bgr = cv2.cvtColor(np.array(image_input), cv2.COLOR_RGB2BGR)
|
607 |
+
faces = face_detecting(image_bgr)
|
608 |
+
face_crops = get_face_crops(image_bgr, faces)
|
609 |
+
if not face_crops:
|
610 |
+
# Return empty images and unchecked boxes if no faces are detected
|
611 |
+
return [None] * MAX_EXPECTED_FACES + [False] * MAX_EXPECTED_FACES
|
612 |
+
# Return face crops and True for each checkbox to indicate they should be checked
|
613 |
+
# Pad the list with None and False if fewer faces than MAX_EXPECTED_FACES are detected
|
614 |
+
output = face_crops + [None] * (MAX_EXPECTED_FACES - len(face_crops))
|
615 |
+
output += [True] * len(face_crops) + [False] * (MAX_EXPECTED_FACES - len(face_crops))
|
616 |
+
return output
|
617 |
+
|
618 |
+
|
619 |
+
css = """
|
620 |
+
#category {
|
621 |
+
padding-left: 100px;
|
622 |
+
font-size: 20px;
|
623 |
+
font-weight: bold;
|
624 |
+
margin-top: 20px;
|
625 |
+
}
|
626 |
+
|
627 |
+
#sticker {
|
628 |
+
height: 130px;
|
629 |
+
width: 30px;
|
630 |
+
padding: 10px;
|
631 |
+
}
|
632 |
+
.radio {
|
633 |
+
display: flex;
|
634 |
+
justify-content: space-around;
|
635 |
+
}
|
636 |
+
"""
|
637 |
+
|
638 |
+
# Create the Gradio interface
|
639 |
+
with gr.Blocks(css=css) as demo:
|
640 |
+
|
641 |
+
with gr.Row():
|
642 |
+
with gr.Column():
|
643 |
+
image_input = gr.Image(type="pil", label="Original Image")
|
644 |
+
with gr.Column():
|
645 |
+
output_image = gr.Image(label="Image with Stickers")
|
646 |
+
# Prepare the checkboxes and image placeholders
|
647 |
+
detect_faces_btn = gr.Button("Detect Faces")
|
648 |
+
|
649 |
+
with gr.Row():
|
650 |
+
face_checkboxes = [gr.Checkbox(label=f"Face {i+1}") for i in range(7)]
|
651 |
+
|
652 |
+
with gr.Row():
|
653 |
+
face_images = [gr.Image(height=150, width=100, min_width=30, interactive=False, show_download_button=False) for i in range(7)]
|
654 |
+
|
655 |
+
detect_faces_btn.click(
|
656 |
+
detect_and_display_faces,
|
657 |
+
inputs=[image_input],
|
658 |
+
outputs=face_images + face_checkboxes
|
659 |
+
)
|
660 |
+
|
661 |
+
process_button = gr.Button("Apply Stickers To Selected Faces")
|
662 |
+
|
663 |
+
process_button.click(
|
664 |
+
handle_face_selection,
|
665 |
+
inputs=[image_input] + face_checkboxes,
|
666 |
+
outputs=output_image
|
667 |
+
)
|
668 |
+
|
669 |
+
# Iterate over each category to create a row for the category
|
670 |
+
for category, stickers in STICKER_PATHS.items():
|
671 |
+
with gr.Row():
|
672 |
+
with gr.Column(scale=1, elem_id="category_row"):
|
673 |
+
gr.Markdown(f"## {category}", elem_id="category")
|
674 |
+
with gr.Column(scale=10):
|
675 |
+
# Iterate over stickers in sets of 10
|
676 |
+
for i in range(0, len(stickers), 10):
|
677 |
+
with gr.Row():
|
678 |
+
for sticker_path in stickers[i:i+10]:
|
679 |
+
gr.Image(value=sticker_path, min_width=50, interactive=False, show_download_button=False, container=False, elem_id="sticker")
|
680 |
+
with gr.Row():
|
681 |
+
# radio = gr.Radio(label=' ', choices=[stickers[i].split('/')[-1].replace('.png', '') for i in range(len(stickers))], container=False, min_width=50)
|
682 |
+
choices = [sticker.split('/')[-1].replace('.png', '') for sticker in stickers]
|
683 |
+
radio = gr.Radio(label='', choices=choices, value="None", container=False, min_width=50, elem_classes="radio")
|
684 |
+
radio.change(lambda selection, cat=category: update_selections(cat, selection), inputs=[radio], outputs=[])
|
685 |
+
|
686 |
+
|
687 |
+
|
688 |
+
demo.launch()
|
689 |
+
|
690 |
+
|
constants.py
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Sticker's paths for each category
|
2 |
+
STICKER_PATHS = {'hats': ['./stickers/hats/None.png', './stickers/hats/santa.png', './stickers/hats/top.png', './stickers/hats/party.png', './stickers/hats/witch.png', './stickers/hats/green.png', './stickers/hats/chef.png', './stickers/hats/Christmas.png', './stickers/hats/mexican.png'],
|
3 |
+
'animal face': ['./stickers/animal face/None.png', './stickers/animal face/laughing.png', './stickers/animal face/cool.png', './stickers/animal face/love.png', './stickers/animal face/cry.png', './stickers/animal face/evil.png', './stickers/animal face/blowing.png', './stickers/animal face/logy.png', './stickers/animal face/mysterious.png'],
|
4 |
+
'ears': ['./stickers/ears/None.png', './stickers/ears/bunny.png', './stickers/ears/fox.png', './stickers/ears/fluffy.png', './stickers/ears/carrot.png', './stickers/ears/tiger.png', './stickers/ears/white.png', './stickers/ears/bent.png', './stickers/ears/bunny2.png'],
|
5 |
+
'glasses': ['./stickers/glasses/None.png', './stickers/glasses/heart.png', './stickers/glasses/round.png', './stickers/glasses/pink.png', './stickers/glasses/cool.png', './stickers/glasses/gray.png', './stickers/glasses/blue.png', './stickers/glasses/rainbow.png', './stickers/glasses/reading.png'],
|
6 |
+
'noses': ['./stickers/noses/None.png', './stickers/noses/clown.png', './stickers/noses/pig.png', './stickers/noses/dog1.png', './stickers/noses/dog2.png', './stickers/noses/dog3.png', './stickers/noses/dog4.png', './stickers/noses/dog5.png', './stickers/noses/dog6.png'],
|
7 |
+
'headbands': ['./stickers/headbands/None.png', './stickers/headbands/deer.png', './stickers/headbands/blue.png', './stickers/headbands/bow.png', './stickers/headbands/flower.png', './stickers/headbands/devil.png', './stickers/headbands/cat.png', './stickers/headbands/christmas.png', './stickers/headbands/green.png']}
|
8 |
+
|
9 |
+
|
10 |
+
|
11 |
+
|
12 |
+
# Creating a new dictionary with sticker name as key and category as value
|
13 |
+
STICKER_TO_CATEGORY = {
|
14 |
+
'santa.png': 'hats',
|
15 |
+
'top.png': 'hats',
|
16 |
+
'party.png': 'hats',
|
17 |
+
'mexican.png': 'hats',
|
18 |
+
'witch.png': 'hats',
|
19 |
+
'green.png': 'hats',
|
20 |
+
'chef.png': 'hats',
|
21 |
+
'Christmas.png': 'hats',
|
22 |
+
'laughing.png': 'animal face',
|
23 |
+
'cool.png': 'animal face',
|
24 |
+
'love.png': 'animal face',
|
25 |
+
'cry.png': 'animal face',
|
26 |
+
'evil.png': 'animal face',
|
27 |
+
'blowing.png': 'animal face',
|
28 |
+
'logy.png': 'animal face',
|
29 |
+
'mysterious.png': 'animal face',
|
30 |
+
'bunny.png': 'ears',
|
31 |
+
'fox.png': 'ears',
|
32 |
+
'fluffy.png': 'ears',
|
33 |
+
'carrot.png': 'ears',
|
34 |
+
'tiger.png': 'ears',
|
35 |
+
'white.png': 'ears',
|
36 |
+
'bent.png': 'ears',
|
37 |
+
'bunny2.png': 'ears',
|
38 |
+
'heart.png': 'glasses',
|
39 |
+
'round.png': 'glasses',
|
40 |
+
'pink.png': 'glasses',
|
41 |
+
'cool.png': 'glasses',
|
42 |
+
'gray.png': 'glasses',
|
43 |
+
'blue.png': 'glasses',
|
44 |
+
'rainbow.png': 'glasses',
|
45 |
+
'reading.png': 'glasses',
|
46 |
+
'dog1.png': 'noses',
|
47 |
+
'pig.png': 'noses',
|
48 |
+
'clown.png': 'noses',
|
49 |
+
'dog2.png': 'noses',
|
50 |
+
'dog3.png': 'noses',
|
51 |
+
'dog4.png': 'noses',
|
52 |
+
'dog5.png': 'noses',
|
53 |
+
'dog6.png': 'noses',
|
54 |
+
'devil.png': 'headbands',
|
55 |
+
'cat.png': 'headbands',
|
56 |
+
'christmas.png': 'headbands',
|
57 |
+
'blue.png': 'headbands',
|
58 |
+
'bow.png': 'headbands',
|
59 |
+
'deer.png': 'headbands',
|
60 |
+
'flower.png': 'headbands',
|
61 |
+
'green.png': 'headbands',
|
62 |
+
}
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
opencv-python
|
2 |
+
dlib
|
3 |
+
matplotlib
|
4 |
+
numpy
|
5 |
+
gradio
|
stickers/.DS_Store
ADDED
Binary file (10.2 kB). View file
|
|
stickers/animal face/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
stickers/animal face/None.png
ADDED
![]() |
stickers/animal face/blowing.png
ADDED
![]() |
stickers/animal face/cool.png
ADDED
![]() |
stickers/animal face/cry.png
ADDED
![]() |
stickers/animal face/evil.png
ADDED
![]() |
stickers/animal face/laughing.png
ADDED
![]() |
stickers/animal face/logy.png
ADDED
![]() |
stickers/animal face/love.png
ADDED
![]() |
stickers/animal face/mysterious.png
ADDED
![]() |
stickers/ears/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
stickers/ears/None.png
ADDED
![]() |
stickers/ears/bent.png
ADDED
![]() |
stickers/ears/bunny.png
ADDED
![]() |
stickers/ears/bunny2.png
ADDED
![]() |
stickers/ears/carrot.png
ADDED
![]() |
stickers/ears/fluffy.png
ADDED
![]() |
stickers/ears/fox.png
ADDED
![]() |
stickers/ears/tiger.png
ADDED
![]() |
stickers/ears/white.png
ADDED
![]() |
stickers/glasses/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
stickers/glasses/None.png
ADDED
![]() |
stickers/glasses/blue.png
ADDED
![]() |
stickers/glasses/cool.png
ADDED
![]() |
stickers/glasses/gray.png
ADDED
![]() |
stickers/glasses/heart.png
ADDED
![]() |
stickers/glasses/pink.png
ADDED
![]() |
stickers/glasses/rainbow.png
ADDED
![]() |
stickers/glasses/reading.png
ADDED
![]() |
stickers/glasses/round.png
ADDED
![]() |
stickers/hats/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
stickers/hats/Christmas.png
ADDED
![]() |
stickers/hats/None.png
ADDED
![]() |
stickers/hats/chef.png
ADDED
![]() |
stickers/hats/green.png
ADDED
![]() |
stickers/hats/mexican.png
ADDED
![]() |
stickers/hats/party.png
ADDED
![]() |
stickers/hats/santa.png
ADDED
![]() |
stickers/hats/top.png
ADDED
![]() |
stickers/hats/witch.png
ADDED
![]() |
stickers/headbands/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
stickers/headbands/None.png
ADDED
![]() |
stickers/headbands/blue.png
ADDED
![]() |
stickers/headbands/bow.png
ADDED
![]() |
stickers/headbands/cat.png
ADDED
![]() |