BraUndress commited on
Commit
643a8d0
·
verified ·
1 Parent(s): 85f151f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +342 -24
app.py CHANGED
@@ -1,7 +1,209 @@
1
- import gradio as gr
 
2
  import numpy as np
 
 
3
  import imageio
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  def dummy(img):
6
  # Assuming img is a dictionary with keys 'composite', 'background', and 'layers'
7
  composite_image = img["composite"]
@@ -12,36 +214,152 @@ def dummy(img):
12
 
13
  return mask
14
 
 
 
 
 
 
 
 
15
  announcement = """
16
  ## Backup Inpaint Mask Maker:
17
- 备用蒙版工具: [Visit Here](https://huggingface.co/spaces/BraUndress/inpaint-mask-maker2)
18
-
19
- ## How to use:
20
- 使用方法: [Learn More](https://telegra.ph/HowToUploadMaskOnBraundress-05-01)
 
21
 
 
 
 
 
 
 
22
  Source: BraUndress
23
  """
24
 
25
- with gr.Blocks() as demo:
26
- # 将公告栏放在一个单独的Column中
27
- with gr.Row():
 
 
 
 
 
 
 
 
28
  with gr.Column():
29
- announcement = gr.Markdown(announcement)
30
-
31
- # 创建一个新的Column来放置ImageMask和按钮
32
- with gr.Column():
 
 
 
 
 
 
 
 
 
 
 
33
  with gr.Row():
34
- img = gr.ImageMask(
35
- sources=["upload"],
36
- layers=True,
37
- transforms=[],
38
- format="png",
39
- label="base image",
40
- show_label=True
41
- )
42
- img2 = gr.Image(label="mask image", show_label=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
- btn = gr.Button("Generate Mask")
45
- btn.click(dummy, inputs=img, outputs=img2)
46
 
47
- demo.launch(debug=True)
 
1
+ from PIL import Image, ImageOps, ImageEnhance
2
+ import mediapipe as mp
3
  import numpy as np
4
+ import cv2
5
+ import gradio as gr
6
  import imageio
7
 
8
+
9
+ class FaceSwapper:
10
+ def __init__(self):
11
+ self.face_mesh = mp.solutions.face_mesh.FaceMesh(
12
+ static_image_mode=True,
13
+ max_num_faces=1,
14
+ refine_landmarks=True,
15
+ min_detection_confidence=0.5
16
+ )
17
+ self.landmarks_a = None
18
+ self.landmarks_b = None
19
+ self.image_a = None
20
+ self.image_b = None
21
+ self.image_a_origin = None
22
+ self.image_b_origin = None
23
+
24
+ def get_face_landmarks(self, image):
25
+ results = self.face_mesh.process(cv2.cvtColor(np.array(image), cv2.COLOR_BGR2RGB))
26
+ if not results.multi_face_landmarks:
27
+ return None
28
+ landmarks = results.multi_face_landmarks[0].landmark
29
+ w, h = image.size
30
+ face_landmarks = [(int(p.x * w), int(p.y * h)) for p in landmarks]
31
+ return face_landmarks
32
+
33
+ def load_images(self, image_a, image_b):
34
+ if image_a:
35
+ if image_a.convert("RGBA") != self.image_a_origin:
36
+ self.image_a = image_a.convert("RGBA")
37
+ self.image_a_origin = image_a.convert("RGBA")
38
+ self.landmarks_a = self.get_face_landmarks(self.image_a)
39
+ if image_b:
40
+ if image_b.convert("RGBA") != self.image_a_origin:
41
+ self.image_b = image_b.convert("RGBA")
42
+ self.image_b_origin = image_b.convert("RGBA")
43
+ self.landmarks_b = self.get_face_landmarks(self.image_b)
44
+ if not self.landmarks_a or not self.landmarks_b:
45
+ return None
46
+
47
+ def overlay_image(self, background, overlay, position):
48
+ x, y = position
49
+
50
+ if background.mode != 'RGBA':
51
+ background = background.convert('RGBA')
52
+ if overlay.mode != 'RGBA':
53
+ overlay = overlay.convert('RGBA')
54
+
55
+ overlay_mask = overlay.split()[3]
56
+
57
+ background.paste(overlay, (x, y), overlay_mask)
58
+ return background
59
+
60
+ def swap_faces(self, scale_factor=1.0, offset_x=0, offset_y=0, rotation_angle=0, margin_left=0.1, margin_right=0.1,
61
+ margin_top=0.1, margin_bottom=0.1, mirror_face_a=False):
62
+ if not self.landmarks_a or not self.image_a or not self.image_b:
63
+ raise ValueError("Image Load Error Or Face Not Deteceted")
64
+
65
+
66
+ min_x_a = min([p[0] for p in self.landmarks_a])
67
+ max_x_a = max([p[0] for p in self.landmarks_a])
68
+ min_y_a = min([p[1] for p in self.landmarks_a])
69
+ max_y_a = max([p[1] for p in self.landmarks_a])
70
+
71
+ width_a = max_x_a - min_x_a
72
+ height_a = max_y_a - min_y_a
73
+
74
+
75
+ face_a = self.image_a.crop((
76
+ int(min_x_a - width_a * margin_left),
77
+ int(min_y_a - height_a * 0.85 * margin_top),
78
+ int(max_x_a + width_a * margin_right),
79
+ int(max_y_a + height_a * margin_bottom)
80
+ ))
81
+
82
+ if mirror_face_a:
83
+ face_a = ImageOps.mirror(face_a)
84
+
85
+
86
+ if not self.landmarks_b:
87
+
88
+ width_b, height_b = self.image_b.size
89
+ width_a, height_a = self.image_a.size
90
+ center_x_b = width_b // 2
91
+ center_y_b = height_b // 5
92
+
93
+ scale_w = width_b / width_a * scale_factor
94
+ scale_h = height_b / height_a * scale_factor
95
+ else:
96
+
97
+ min_x_b = min([p[0] for p in self.landmarks_b])
98
+ max_x_b = max([p[0] for p in self.landmarks_b])
99
+ min_y_b = min([p[1] for p in self.landmarks_b])
100
+ max_y_b = max([p[1] for p in self.landmarks_b])
101
+ width_b = max_x_b - min_x_b
102
+ height_b = max_y_b - min_y_b
103
+ center_x_b = min_x_b + width_b // 2
104
+ center_y_b = min_y_b + height_b // 2
105
+
106
+ scale_w = width_b / face_a.width * 1.4 * scale_factor
107
+ scale_h = height_b / face_a.height * 1.4 * scale_factor
108
+
109
+ scale = min(scale_w, scale_h)
110
+ new_width = int(face_a.width * scale)
111
+ new_height = int(face_a.height * scale)
112
+ face_a_resized = face_a.resize((new_width, new_height), Image.LANCZOS)
113
+
114
+ face_a_rotated = face_a_resized.rotate(rotation_angle, expand=True)
115
+
116
+ final_offset_x = center_x_b - face_a_rotated.width // 2 + offset_x
117
+ final_offset_y = center_y_b - face_a_rotated.height // 2 + offset_y
118
+
119
+ result_image = self.overlay_image(self.image_b.copy(), face_a_rotated, (final_offset_x, final_offset_y))
120
+
121
+ return result_image
122
+
123
+ def adjust_colors(self, is_select_image_a, saturation, temperature, contrast, brightness):
124
+ image = self.image_a_origin if is_select_image_a else self.image_b_origin
125
+ if not image:
126
+ raise ValueError("Selected image is not loaded.")
127
+
128
+ # Convert to RGB if necessary
129
+ if image.mode != 'RGB':
130
+ image = image.convert('RGB')
131
+
132
+ # Adjust brightness
133
+ enhancer = ImageEnhance.Brightness(image)
134
+ image = enhancer.enhance(brightness)
135
+
136
+ # Adjust contrast
137
+ enhancer = ImageEnhance.Contrast(image)
138
+ image = enhancer.enhance(contrast)
139
+
140
+ # Adjust saturation
141
+ enhancer = ImageEnhance.Color(image)
142
+ image = enhancer.enhance(saturation)
143
+
144
+ # Adjust temperature by modifying color balance
145
+ r, g, b = image.split() # Handling three channels only
146
+ r = r.point(lambda i: i + temperature * 10)
147
+ b = b.point(lambda i: i - temperature * 10)
148
+ image = Image.merge("RGB", (r, g, b)) # Re-merge as RGB
149
+
150
+ if is_select_image_a:
151
+ self.image_a = image
152
+ else:
153
+ self.image_b = image
154
+
155
+ return image
156
+
157
+
158
+
159
+ # Function to swap faces
160
+ def process(image_a, image_b, scale_factor, offset_x, offset_y, rotation_angle, margin_left, margin_right, margin_top,
161
+ margin_bottom, mirror_face_a):
162
+ try:
163
+ face_swapper = FaceSwapper()
164
+ face_swapper.load_images(image_a, image_b)
165
+ if face_swapper.image_a and face_swapper.image_b:
166
+ result = face_swapper.swap_faces(
167
+ scale_factor=scale_factor,
168
+ offset_x=offset_x,
169
+ offset_y=offset_y,
170
+ rotation_angle=rotation_angle,
171
+ margin_left=margin_left,
172
+ margin_right=margin_right,
173
+ margin_top=margin_top,
174
+ margin_bottom=margin_bottom,
175
+ mirror_face_a=mirror_face_a
176
+ )
177
+ return result
178
+ except Exception as e:
179
+ return str(e)
180
+
181
+
182
+ def adujst_color_process(image_a, image_b, scale_factor, offset_x, offset_y, rotation_angle, margin_left, margin_right, margin_top,
183
+ margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b):
184
+ try:
185
+ face_swapper = FaceSwapper()
186
+ face_swapper.load_images(image_a, image_b)
187
+ face_swapper.adjust_colors(True, saturation, temperature, contrast, brightness)
188
+ face_swapper.adjust_colors(False, saturation_b, temperature_b, contrast_b, brightness_b)
189
+ if face_swapper.image_a and face_swapper.image_b:
190
+ result = face_swapper.swap_faces(
191
+ scale_factor=scale_factor,
192
+ offset_x=offset_x,
193
+ offset_y=offset_y,
194
+ rotation_angle=rotation_angle,
195
+ margin_left=margin_left,
196
+ margin_right=margin_right,
197
+ margin_top=margin_top,
198
+ margin_bottom=margin_bottom,
199
+ mirror_face_a=mirror_face_a
200
+ )
201
+ return result
202
+ except Exception as e:
203
+ return str(e)
204
+
205
+
206
+ # Function for image masking (demonstrative)
207
  def dummy(img):
208
  # Assuming img is a dictionary with keys 'composite', 'background', and 'layers'
209
  composite_image = img["composite"]
 
214
 
215
  return mask
216
 
217
+
218
+ # Function to update the image in Tab 1
219
+ def update_image(image):
220
+ return image
221
+
222
+
223
+ # Announcement text for tab 1
224
  announcement = """
225
  ## Backup Inpaint Mask Maker:
226
+ 备用蒙版工具: [Visit Here](https://huggingface.co/spaces/BraUndress/inpaint-mask-maker2)
227
+ ## How to Use:
228
+ 使用方法: [Learn More](https://telegra.ph/HowToUploadMaskOnBraundress-05-01)
229
+ Source: BraUndress
230
+ """
231
 
232
+ # Announcement text for tab 2
233
+ announcement_2 = """
234
+ ## Backup Inpaint Mask Maker:
235
+ 备用蒙版工具: [Visit Here](https://huggingface.co/spaces/BraUndress/inpaint-mask-maker2)
236
+ ## How to Use:
237
+ 使用方法: [Learn More](https://telegra.ph/100-Similarity-Face-Swapped-with-Braundress-Mask-Upload-Mode-07-23)
238
  Source: BraUndress
239
  """
240
 
241
+ # Create Gradio interface with Tabs
242
+ with gr.Blocks() as app:
243
+ tab1 = gr.Tab("Inpaint Mask Maker")
244
+ tab2 = gr.Tab("Face Swap")
245
+
246
+ with tab1:
247
+ with gr.Row():
248
+ with gr.Column():
249
+ announcement = gr.Markdown(announcement)
250
+
251
+
252
  with gr.Column():
253
+ with gr.Row():
254
+ img = gr.ImageMask(
255
+ sources=["upload", "clipboard"],
256
+ transforms=[],
257
+ layers=False,
258
+ format="png",
259
+ label="base image",
260
+ show_label=True
261
+ )
262
+ img2 = gr.Image(label="mask image", show_label=True)
263
+
264
+ btn = gr.Button("Generate Mask")
265
+ btn.click(dummy, inputs=img, outputs=img2)
266
+
267
+ with tab2:
268
  with gr.Row():
269
+ with gr.Column():
270
+ announcement_2 = gr.Markdown(announcement_2)
271
+ with gr.Row():
272
+ img_input_a = gr.Image(type="pil", label="Input Face Image A(输入人脸图片)", height=300)
273
+ img_input_b = gr.Image(type="pil", label="Input Face Swapped Image B(输入换脸图片)", height=300)
274
+ with gr.Row():
275
+ scale_factor = gr.Slider(0.1, 3.5, 1, 0.1, label="Face Scale Factor(人脸放大)")
276
+ offset_x = gr.Slider(-200, 200, 0, 1, label="Face Offset X(人脸水平横移)")
277
+ offset_y = gr.Slider(-200, 200, 0, 1, label="Face Offset Y(人脸垂直横移)")
278
+ rotation_angle = gr.Slider(-180, 180, 0, 1, label="Face Rotation Angle(人脸旋转)")
279
+ margin_left = gr.Slider(0, 1, 0.1, 0.01, label="Face Margin Left(人脸左边缘扩展)")
280
+ margin_right = gr.Slider(0, 1, 0.1, 0.01, label="Face Margin Right(人脸右边缘扩展)")
281
+ margin_top = gr.Slider(0, 1, 0.1, 0.01, label="Face Margin Top(人脸上边缘扩展)")
282
+ margin_bottom = gr.Slider(0, 1, 0, 0.01, label="Face Margin Bottom(人脸下边缘扩展)")
283
+ mirror_face_a = gr.Checkbox(label="Mirror Face A(人脸镜像)")
284
+ # btn_process = gr.Button("Swap Faces")
285
+ with gr.Row():
286
+ image_select = gr.Radio(['Image A'], value='Image A', label="Adjust Color For Image A(图片A调整颜色)")
287
+ saturation = gr.Slider(0, 2.0, 1.0, 0.1, label="Saturation(饱和度)")
288
+ temperature = gr.Slider(-10, 10, 0, 0.1, label="Color Temperature(色温)")
289
+ contrast = gr.Slider(0, 2.0, 1.0, 0.1, label="Contrast(对比度)")
290
+ brightness = gr.Slider(0, 2.0, 1.0, 0.1, label="Brightness(亮度)")
291
+ with gr.Row():
292
+ image_select_b = gr.Radio(['Image B'], value='Image B', label="Adjust Color For Image B(图片B调整颜色)")
293
+ saturation_b = gr.Slider(0, 2.0, 1.0, 0.1, label="Saturation(饱和度)")
294
+ temperature_b = gr.Slider(-10, 10, 0, 0.1, label="Color Temperature(色温)")
295
+ contrast_b = gr.Slider(0, 2.0, 1.0, 0.1, label="Contrast(对比度)")
296
+ brightness_b = gr.Slider(0, 2.0, 1.0, 0.1, label="Brightness(亮度)")
297
+ result_image = gr.Image(type="pil", label="Result Image", height=600)
298
+ # btn_process.click(process, inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle, margin_left, margin_right, margin_top, margin_bottom, mirror_face_a], outputs=result_image)
299
+ scale_factor.release(adujst_color_process,
300
+ inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle,
301
+ margin_left, margin_right, margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b],
302
+ outputs=result_image)
303
+ offset_x.release(adujst_color_process, inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle,
304
+ margin_left, margin_right, margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b],
305
+ outputs=result_image)
306
+ offset_y.release(adujst_color_process, inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle,
307
+ margin_left, margin_right, margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b],
308
+ outputs=result_image)
309
+ rotation_angle.release(adujst_color_process,
310
+ inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle,
311
+ margin_left, margin_right, margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b],
312
+ outputs=result_image)
313
+ margin_left.release(adujst_color_process, inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle,
314
+ margin_left, margin_right, margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b],
315
+ outputs=result_image)
316
+ margin_right.release(adujst_color_process,
317
+ inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle,
318
+ margin_left, margin_right, margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b],
319
+ outputs=result_image)
320
+ margin_top.release(adujst_color_process, inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle,
321
+ margin_left, margin_right, margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b],
322
+ outputs=result_image)
323
+ margin_bottom.release(adujst_color_process,
324
+ inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle,
325
+ margin_left, margin_right, margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b],
326
+ outputs=result_image)
327
+ img_input_a.change(adujst_color_process, inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle,
328
+ margin_left, margin_right, margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b],
329
+ outputs=result_image)
330
+ img_input_b.change(adujst_color_process, inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle,
331
+ margin_left, margin_right, margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b],
332
+ outputs=result_image)
333
+ mirror_face_a.change(adujst_color_process,
334
+ inputs=[img_input_a, img_input_b, scale_factor, offset_x, offset_y, rotation_angle,
335
+ margin_left, margin_right, margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b],
336
+ outputs=result_image)
337
+ saturation.release(adujst_color_process,
338
+ inputs=[img_input_a, img_input_b,scale_factor, offset_x, offset_y, rotation_angle, margin_left, margin_right,
339
+ margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b], outputs=result_image)
340
+ temperature.release(adujst_color_process,
341
+ inputs=[img_input_a, img_input_b,scale_factor, offset_x, offset_y, rotation_angle, margin_left, margin_right,
342
+ margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b], outputs=result_image)
343
+ contrast.release(adujst_color_process,
344
+ inputs=[img_input_a, img_input_b,scale_factor, offset_x, offset_y, rotation_angle, margin_left, margin_right,
345
+ margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b], outputs=result_image)
346
+ brightness.release(adujst_color_process,
347
+ inputs=[img_input_a, img_input_b,scale_factor, offset_x, offset_y, rotation_angle, margin_left, margin_right,
348
+ margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b], outputs=result_image)
349
+ saturation_b.release(adujst_color_process,
350
+ inputs=[img_input_a, img_input_b,scale_factor, offset_x, offset_y, rotation_angle, margin_left, margin_right,
351
+ margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b], outputs=result_image)
352
+ temperature_b.release(adujst_color_process,
353
+ inputs=[img_input_a, img_input_b,scale_factor, offset_x, offset_y, rotation_angle, margin_left, margin_right,
354
+ margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b], outputs=result_image)
355
+ contrast_b.release(adujst_color_process,
356
+ inputs=[img_input_a, img_input_b,scale_factor, offset_x, offset_y, rotation_angle, margin_left, margin_right,
357
+ margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b], outputs=result_image)
358
+ brightness_b.release(adujst_color_process,
359
+ inputs=[img_input_a, img_input_b,scale_factor, offset_x, offset_y, rotation_angle, margin_left, margin_right,
360
+ margin_top, margin_bottom, mirror_face_a, saturation, temperature, contrast, brightness, saturation_b, temperature_b, contrast_b, brightness_b], outputs=result_image)
361
 
362
+ btn_send_to_tab1 = gr.Button("Send To Mask Maker(发送给蒙版制作页面)")
363
+ btn_send_to_tab1.click(update_image, inputs=result_image, outputs=img)
364
 
365
+ app.launch()