mtalamon commited on
Commit
1bc2204
1 Parent(s): e9be744

Upload 5 files

Browse files
Files changed (6) hide show
  1. .gitattributes +1 -0
  2. anklers.png +0 -0
  3. app.py +16 -0
  4. hat.png +3 -0
  5. prototype.py +114 -0
  6. utils.py +8 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip 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
 
 
33
  *.zip 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
+ hat.png filter=lfs diff=lfs merge=lfs -text
anklers.png ADDED
app.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from src.prototype import activate
3
+ import gradio
4
+
5
+
6
+
7
+ iface = gradio.Interface(
8
+ fn= activate,
9
+ inputs=gradio.components.Image(type="numpy"),
10
+ outputs=gradio.components.Image(type="numpy"),
11
+ title="Hatting Face",
12
+ description="Upload the picture of your choice :)"
13
+ )
14
+ iface.launch()
15
+
16
+
hat.png ADDED

Git LFS Details

  • SHA256: 41523fd01c98351940aebd99c1acae78dc781e9e67d89c5868c23c8543e5a45c
  • Pointer size: 132 Bytes
  • Size of remote file: 4.72 MB
prototype.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import os
4
+ import mediapipe
5
+
6
+ from src.utils import extract_point, compute_distance
7
+
8
+
9
+
10
+ class ImageProcessor:
11
+ def __init__(self, picture, folder_path , model):
12
+ self.image = picture
13
+ self.height , self.width = self.image.shape[:2]
14
+ self.folder_path = folder_path
15
+ self.model = model
16
+
17
+ def detect_and_overlay(self, write = False, output = None):
18
+
19
+ detections = self.model.process(self.image).detections
20
+
21
+ if not detections:
22
+ self.image = cv2.putText(self.image, "Unable to detect faces :(", (int(self.width//10), int(self.height//2)), fontFace = cv2.FONT_HERSHEY_SIMPLEX, fontScale = 3, color = (0,0,0),thickness = 7)
23
+ self.image = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB)
24
+ return self.image
25
+
26
+ for i, elem in enumerate(detections):
27
+ print(i)
28
+ x, y, w, h = self.get_bounding_box(elem)
29
+ gadget_path, nose_path = self.select_gadgets(i)
30
+
31
+
32
+ if nose_path:
33
+ nose = extract_point(self, elem.location_data.relative_keypoints[2])
34
+ eye = extract_point(self, elem.location_data.relative_keypoints[0])
35
+ cv2.circle(self.image, (int(nose[0]), int(nose[1])), int(compute_distance(nose, eye)/2), (255,0,0), -1)
36
+
37
+
38
+ try:
39
+ roi_x1, roi_y1, roi_x2, roi_y2 = self.calculate_roi_head(x, y, w, h)
40
+ gadget = self.read_and_resize_gadget(gadget_path, roi_x2 - roi_x1, roi_y2 - roi_y1)
41
+ self.overlay_gadget(gadget, roi_x1, roi_y1, roi_x2, roi_y2)
42
+ except:
43
+ continue
44
+
45
+ # self.image = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB)
46
+
47
+ if write:
48
+ self.display_result(output)
49
+
50
+ return self.image
51
+
52
+
53
+
54
+ def get_bounding_box(self, elem):
55
+ bbox = elem.location_data.relative_bounding_box
56
+ x = int(bbox.xmin * self.width)
57
+ y = int(bbox.ymin * self.height)
58
+ w = int(bbox.width * self.width)
59
+ h = int(bbox.height * self.height)
60
+ return x, y, w, h
61
+
62
+ def calculate_roi_head(self, x, y, w, h):
63
+ roi_height = 60
64
+ roi_width = int(w * 2)
65
+ roi_x1 = int(x + (w - roi_width) // 2)
66
+ vertical_offset = 20
67
+ roi_y1 = int(max(y - roi_height // 2 - vertical_offset, 0))
68
+ roi_y2 = roi_y1 + roi_height
69
+ roi_x2 = roi_x1 + roi_width
70
+
71
+ return roi_x1, roi_y1, roi_x2, roi_y2
72
+
73
+
74
+ def select_gadgets(self, index):
75
+ if index == 0:
76
+ gadget = "anklers.png"
77
+ nose = True
78
+
79
+ else:
80
+ gadget = "hat.png"
81
+ nose = False
82
+
83
+ return gadget, nose
84
+
85
+ def read_and_resize_gadget(self, gadget_path, width, height):
86
+ gadget = cv2.imread(gadget_path, cv2.IMREAD_UNCHANGED)
87
+ gadget_resized = cv2.resize(gadget, (width, height))
88
+ return gadget_resized
89
+
90
+ def overlay_gadget(self, gadget, x1, y1, x2, y2):
91
+ alpha_gadget = gadget[:, :, 3] / 255.0
92
+ alpha_gadget_resized = np.stack([alpha_gadget] * 3, axis=-1)
93
+ gadget_bgr = gadget[:, :, :3]
94
+ gadget_bgr = cv2.cvtColor(gadget_bgr, cv2.COLOR_BGR2RGB)
95
+
96
+ roi = self.image[y1:y2, x1:x2]
97
+
98
+ roi = cv2.resize(roi, (gadget.shape[1], gadget.shape[0]))
99
+
100
+ overlay = (1 - alpha_gadget_resized) * roi + alpha_gadget_resized * gadget_bgr
101
+ self.image[y1:y2, x1:x2] = overlay
102
+
103
+ def display_result(self, output):
104
+ if not output:
105
+ output = "image"
106
+ cv2.imwrite( os.path.join("results", "{}.png".format(output)), self.image )
107
+
108
+
109
+
110
+ def activate(image):
111
+ folder_path = 'gadgets/'
112
+ model = mediapipe.solutions.face_detection.FaceDetection(model_selection=1, min_detection_confidence=0.8)
113
+ processor = ImageProcessor(image, folder_path, model)
114
+ return processor.detect_and_overlay()
utils.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import math
2
+
3
+ def extract_point(obj, pt):
4
+ return obj.width*pt.x,obj.height* pt.y
5
+
6
+ def compute_distance(pt1, pt2):
7
+
8
+ return math.sqrt((pt1[0]- pt2[0])**2 + (pt1[1]- pt2[1])**2)