Update app.py with potential fix

#1
by AdamOswald1 - opened
Files changed (1) hide show
  1. app.py +169 -84
app.py CHANGED
@@ -2,7 +2,13 @@ import gradio
2
  from huggingface_hub import Repository
3
  import os
4
 
5
- from utils.utils import norm_crop, estimate_norm, inverse_estimate_norm, transform_landmark_points, get_lm
 
 
 
 
 
 
6
  from networks.layers import AdaIN, AdaptiveAttention
7
  from tensorflow_addons.layers import InstanceNormalization
8
  import numpy as np
@@ -13,42 +19,77 @@ from tensorflow.keras.models import load_model
13
  from options.swap_options import SwapOptions
14
 
15
 
16
-
17
- token = os.environ['model_fetch']
18
 
19
  opt = SwapOptions().parse()
20
 
21
- retina_repo = Repository(local_dir="retina_model", clone_from="felixrosberg/retinaface_resnet50",
22
- private=True, use_auth_token=token, git_user="felixrosberg")
 
 
 
 
 
23
 
24
  from retina_model.models import *
25
 
26
- RetinaFace = load_model("retina_model/retinaface_res50.h5",
27
- custom_objects={"FPN": FPN,
28
- "SSH": SSH,
29
- "BboxHead": BboxHead,
30
- "LandmarkHead": LandmarkHead,
31
- "ClassHead": ClassHead})
32
-
33
- arc_repo = Repository(local_dir="arcface_model", clone_from="felixrosberg/arcface_tf",
34
- private=True, use_auth_token=token)
 
 
 
 
 
 
 
 
35
  ArcFace = load_model("arcface_model/arc_res50.h5")
36
  ArcFaceE = load_model("arcface_model/arc_res50e.h5")
37
 
38
- g_repo = Repository(local_dir="g_model_c_hq", clone_from="felixrosberg/affa_config_c_hq",
39
- private=True, use_auth_token=token)
40
- G = load_model("g_model_c_hq/generator_t_28.h5", custom_objects={"AdaIN": AdaIN,
41
- "AdaptiveAttention": AdaptiveAttention,
42
- "InstanceNormalization": InstanceNormalization})
43
-
44
- r_repo = Repository(local_dir="reconstruction_attack", clone_from="felixrosberg/reconstruction_attack",
45
- private=True, use_auth_token=token)
46
- R = load_model("reconstruction_attack/reconstructor_42.h5", custom_objects={"AdaIN": AdaIN,
47
- "AdaptiveAttention": AdaptiveAttention,
48
- "InstanceNormalization": InstanceNormalization})
49
-
50
- permuter_repo = Repository(local_dir="identity_permuter", clone_from="felixrosberg/identitypermuter",
51
- private=True, use_auth_token=token, git_user="felixrosberg")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  from identity_permuter.id_permuter import identity_permuter
54
 
@@ -71,7 +112,11 @@ def run_inference(target, source, slider, adv_slider, settings):
71
  source_h, source_w, _ = source.shape
72
  source_lm = get_lm(source_a, source_w, source_h)
73
  source_aligned = norm_crop(source, source_lm, image_size=256)
74
- source_z = ArcFace.predict(np.expand_dims(tf.image.resize(source_aligned, [112, 112]) / 255.0, axis=0))
 
 
 
 
75
  else:
76
  source_z = None
77
 
@@ -82,22 +127,31 @@ def run_inference(target, source, slider, adv_slider, settings):
82
 
83
  detection_scale = im_w // 640 if im_w > 640 else 1
84
 
85
- faces = RetinaFace(np.expand_dims(cv2.resize(im,
86
- (im_w // detection_scale,
87
- im_h // detection_scale)), axis=0)).numpy()
 
 
 
88
 
89
  total_img = im / 255.0
90
  for annotation in faces:
91
- lm_align = np.array([[annotation[4] * im_w, annotation[5] * im_h],
92
- [annotation[6] * im_w, annotation[7] * im_h],
93
- [annotation[8] * im_w, annotation[9] * im_h],
94
- [annotation[10] * im_w, annotation[11] * im_h],
95
- [annotation[12] * im_w, annotation[13] * im_h]],
96
- dtype=np.float32)
 
 
 
 
97
 
98
  # align the detected face
99
  M, pose_index = estimate_norm(lm_align, 256, "arcface", shrink_factor=1.0)
100
- im_aligned = (cv2.warpAffine(im, M, (256, 256), borderValue=0.0) - 127.5) / 127.5
 
 
101
 
102
  if "adversarial defense" in settings:
103
  eps = adv_slider / 200
@@ -125,54 +179,76 @@ def run_inference(target, source, slider, adv_slider, settings):
125
 
126
  slider_weight = slider / 100
127
 
128
- target_z = ArcFace.predict(np.expand_dims(tf.image.resize(im_aligned, [112, 112]) * 0.5 + 0.5, axis=0))
 
 
 
 
129
  source_z = IDP.predict(target_z)
130
 
131
  source_z = slider_weight * source_z + (1 - slider_weight) * target_z
132
 
133
  if "reconstruction attack" in settings:
134
- source_z = ArcFaceE.predict(np.expand_dims(tf.image.resize(im_aligned, [112, 112]) * 0.5 + 0.5, axis=0))
 
 
 
 
135
 
136
  # face swap
137
  if "reconstruction attack" not in settings:
138
- changed_face_cage = G.predict([np.expand_dims(im_aligned, axis=0),
139
- source_z])
 
140
  changed_face = changed_face_cage[0] * 0.5 + 0.5
141
 
142
  # get inverse transformation landmarks
143
  transformed_lmk = transform_landmark_points(M, lm_align)
144
 
145
  # warp image back
146
- iM, _ = inverse_estimate_norm(lm_align, transformed_lmk, 256, "arcface", shrink_factor=1.0)
147
- iim_aligned = cv2.warpAffine(changed_face, iM, im_shape, borderValue=0.0)
 
 
 
 
148
 
149
  # blend swapped face with target image
150
- blend_mask = cv2.warpAffine(blend_mask_base, iM, im_shape, borderValue=0.0)
 
 
151
  blend_mask = np.expand_dims(blend_mask, axis=-1)
152
- total_img = (iim_aligned * blend_mask + total_img * (1 - blend_mask))
153
  else:
154
- changed_face_cage = R.predict([np.expand_dims(im_aligned, axis=0),
155
- source_z])
 
156
  changed_face = changed_face_cage[0] * 0.5 + 0.5
157
 
158
  # get inverse transformation landmarks
159
  transformed_lmk = transform_landmark_points(M, lm_align)
160
 
161
  # warp image back
162
- iM, _ = inverse_estimate_norm(lm_align, transformed_lmk, 256, "arcface", shrink_factor=1.0)
163
- iim_aligned = cv2.warpAffine(changed_face, iM, im_shape, borderValue=0.0)
 
 
 
 
164
 
165
  # blend swapped face with target image
166
- blend_mask = cv2.warpAffine(blend_mask_base, iM, im_shape, borderValue=0.0)
 
 
167
  blend_mask = np.expand_dims(blend_mask, axis=-1)
168
- total_img = (iim_aligned * blend_mask + total_img * (1 - blend_mask))
169
 
170
  if "compare" in settings:
171
  total_img = np.concatenate((im / 255.0, total_img), axis=1)
172
 
173
  total_img = np.clip(total_img, 0, 1)
174
  total_img *= 255.0
175
- total_img = total_img.astype('uint8')
176
 
177
  return total_img
178
  except Exception as e:
@@ -180,38 +256,47 @@ def run_inference(target, source, slider, adv_slider, settings):
180
  return None
181
 
182
 
183
- description = "Performs subject agnostic identity transfer from a source face to all target faces. \n\n" \
184
- "Implementation and demo of FaceDancer, accepted to WACV 2023. \n\n" \
185
- "Pre-print: https://arxiv.org/abs/2210.10473 \n\n" \
186
- "Code: https://github.com/felixrosberg/FaceDancer \n\n" \
187
- "\n\n" \
188
- "Options:\n\n" \
189
- "-Compare returns the target image concatenated with the results.\n\n" \
190
- "-Anonymize will ignore the source image and perform an identity permutation of target faces.\n\n" \
191
- "-Reconstruction attack will attempt to invert the face swap or the anonymization.\n\n" \
192
- "-Adversarial defense will add a permutation noise that disrupts the reconstruction attack.\n\n" \
193
- "NOTE: There is no guarantees with the anonymization process currently.\n\n" \
194
- "NOTE: source image with too high resolution may not work properly!"
195
- examples = [["assets/rick.jpg", "assets/musk.jpg", 100, 10, ["compare"]],
196
- ["assets/musk.jpg", "assets/musk.jpg", 100, 10, ["anonymize"]]]
 
 
 
 
197
  article = """
198
  Demo is based of recent research from my Ph.D work. Results expects to be published in the coming months.
199
  """
200
 
201
- iface = gradio.Interface(run_inference,
202
- [gradio.inputs.Image(shape=None, label='Target'),
203
- gradio.inputs.Image(shape=None, label='Source'),
204
- gradio.inputs.Slider(0, 100, default=100, label="Anonymization ratio (%)"),
205
- gradio.inputs.Slider(0, 100, default=100, label="Adversarial defense ratio (%)"),
206
- gradio.inputs.CheckboxGroup(["compare",
207
- "anonymize",
208
- "reconstruction attack",
209
- "adversarial defense"],
210
- label='Options')],
211
- gradio.outputs.Image(),
212
- title="Face Swap",
213
- description=description,
214
- examples=examples,
215
- article=article,
216
- layout="vertical")
 
 
 
 
 
217
  iface.launch()
 
2
  from huggingface_hub import Repository
3
  import os
4
 
5
+ from utils.utils import (
6
+ norm_crop,
7
+ estimate_norm,
8
+ inverse_estimate_norm,
9
+ transform_landmark_points,
10
+ get_lm,
11
+ )
12
  from networks.layers import AdaIN, AdaptiveAttention
13
  from tensorflow_addons.layers import InstanceNormalization
14
  import numpy as np
 
19
  from options.swap_options import SwapOptions
20
 
21
 
22
+ token = os.environ["model_fetch"]
 
23
 
24
  opt = SwapOptions().parse()
25
 
26
+ retina_repo = Repository(
27
+ local_dir="retina_model",
28
+ clone_from="felixrosberg/retinaface_resnet50",
29
+ private=True,
30
+ use_auth_token=token,
31
+ git_user="felixrosberg",
32
+ )
33
 
34
  from retina_model.models import *
35
 
36
+ RetinaFace = load_model(
37
+ "retina_model/retinaface_res50.h5",
38
+ custom_objects={
39
+ "FPN": FPN,
40
+ "SSH": SSH,
41
+ "BboxHead": BboxHead,
42
+ "LandmarkHead": LandmarkHead,
43
+ "ClassHead": ClassHead,
44
+ },
45
+ )
46
+
47
+ arc_repo = Repository(
48
+ local_dir="arcface_model",
49
+ clone_from="felixrosberg/arcface_tf",
50
+ private=True,
51
+ use_auth_token=token,
52
+ )
53
  ArcFace = load_model("arcface_model/arc_res50.h5")
54
  ArcFaceE = load_model("arcface_model/arc_res50e.h5")
55
 
56
+ g_repo = Repository(
57
+ local_dir="g_model_c_hq",
58
+ clone_from="felixrosberg/affa_config_c_hq",
59
+ private=True,
60
+ use_auth_token=token,
61
+ )
62
+ G = load_model(
63
+ "g_model_c_hq/generator_t_28.h5",
64
+ custom_objects={
65
+ "AdaIN": AdaIN,
66
+ "AdaptiveAttention": AdaptiveAttention,
67
+ "InstanceNormalization": InstanceNormalization,
68
+ },
69
+ )
70
+
71
+ r_repo = Repository(
72
+ local_dir="reconstruction_attack",
73
+ clone_from="felixrosberg/reconstruction_attack",
74
+ private=True,
75
+ use_auth_token=token,
76
+ )
77
+ R = load_model(
78
+ "reconstruction_attack/reconstructor_42.h5",
79
+ custom_objects={
80
+ "AdaIN": AdaIN,
81
+ "AdaptiveAttention": AdaptiveAttention,
82
+ "InstanceNormalization": InstanceNormalization,
83
+ },
84
+ )
85
+
86
+ permuter_repo = Repository(
87
+ local_dir="identity_permuter",
88
+ clone_from="felixrosberg/identitypermuter",
89
+ private=True,
90
+ use_auth_token=token,
91
+ git_user="felixrosberg",
92
+ )
93
 
94
  from identity_permuter.id_permuter import identity_permuter
95
 
 
112
  source_h, source_w, _ = source.shape
113
  source_lm = get_lm(source_a, source_w, source_h)
114
  source_aligned = norm_crop(source, source_lm, image_size=256)
115
+ source_z = ArcFace.predict(
116
+ np.expand_dims(
117
+ tf.image.resize(source_aligned, [112, 112]) / 255.0, axis=0
118
+ )
119
+ )
120
  else:
121
  source_z = None
122
 
 
127
 
128
  detection_scale = im_w // 640 if im_w > 640 else 1
129
 
130
+ faces = RetinaFace(
131
+ np.expand_dims(
132
+ cv2.resize(im, (im_w // detection_scale, im_h // detection_scale)),
133
+ axis=0,
134
+ )
135
+ ).numpy()
136
 
137
  total_img = im / 255.0
138
  for annotation in faces:
139
+ lm_align = np.array(
140
+ [
141
+ [annotation[4] * im_w, annotation[5] * im_h],
142
+ [annotation[6] * im_w, annotation[7] * im_h],
143
+ [annotation[8] * im_w, annotation[9] * im_h],
144
+ [annotation[10] * im_w, annotation[11] * im_h],
145
+ [annotation[12] * im_w, annotation[13] * im_h],
146
+ ],
147
+ dtype=np.float32,
148
+ )
149
 
150
  # align the detected face
151
  M, pose_index = estimate_norm(lm_align, 256, "arcface", shrink_factor=1.0)
152
+ im_aligned = (
153
+ cv2.warpAffine(im, M, (256, 256), borderValue=0.0) - 127.5
154
+ ) / 127.5
155
 
156
  if "adversarial defense" in settings:
157
  eps = adv_slider / 200
 
179
 
180
  slider_weight = slider / 100
181
 
182
+ target_z = ArcFace.predict(
183
+ np.expand_dims(
184
+ tf.image.resize(im_aligned, [112, 112]) * 0.5 + 0.5, axis=0
185
+ )
186
+ )
187
  source_z = IDP.predict(target_z)
188
 
189
  source_z = slider_weight * source_z + (1 - slider_weight) * target_z
190
 
191
  if "reconstruction attack" in settings:
192
+ source_z = ArcFaceE.predict(
193
+ np.expand_dims(
194
+ tf.image.resize(im_aligned, [112, 112]) * 0.5 + 0.5, axis=0
195
+ )
196
+ )
197
 
198
  # face swap
199
  if "reconstruction attack" not in settings:
200
+ changed_face_cage = G.predict(
201
+ [np.expand_dims(im_aligned, axis=0), source_z]
202
+ )
203
  changed_face = changed_face_cage[0] * 0.5 + 0.5
204
 
205
  # get inverse transformation landmarks
206
  transformed_lmk = transform_landmark_points(M, lm_align)
207
 
208
  # warp image back
209
+ iM, _ = inverse_estimate_norm(
210
+ lm_align, transformed_lmk, 256, "arcface", shrink_factor=1.0
211
+ )
212
+ iim_aligned = cv2.warpAffine(
213
+ changed_face, iM, im_shape, borderValue=0.0
214
+ )
215
 
216
  # blend swapped face with target image
217
+ blend_mask = cv2.warpAffine(
218
+ blend_mask_base, iM, im_shape, borderValue=0.0
219
+ )
220
  blend_mask = np.expand_dims(blend_mask, axis=-1)
221
+ total_img = iim_aligned * blend_mask + total_img * (1 - blend_mask)
222
  else:
223
+ changed_face_cage = R.predict(
224
+ [np.expand_dims(im_aligned, axis=0), source_z]
225
+ )
226
  changed_face = changed_face_cage[0] * 0.5 + 0.5
227
 
228
  # get inverse transformation landmarks
229
  transformed_lmk = transform_landmark_points(M, lm_align)
230
 
231
  # warp image back
232
+ iM, _ = inverse_estimate_norm(
233
+ lm_align, transformed_lmk, 256, "arcface", shrink_factor=1.0
234
+ )
235
+ iim_aligned = cv2.warpAffine(
236
+ changed_face, iM, im_shape, borderValue=0.0
237
+ )
238
 
239
  # blend swapped face with target image
240
+ blend_mask = cv2.warpAffine(
241
+ blend_mask_base, iM, im_shape, borderValue=0.0
242
+ )
243
  blend_mask = np.expand_dims(blend_mask, axis=-1)
244
+ total_img = iim_aligned * blend_mask + total_img * (1 - blend_mask)
245
 
246
  if "compare" in settings:
247
  total_img = np.concatenate((im / 255.0, total_img), axis=1)
248
 
249
  total_img = np.clip(total_img, 0, 1)
250
  total_img *= 255.0
251
+ total_img = total_img.astype("uint8")
252
 
253
  return total_img
254
  except Exception as e:
 
256
  return None
257
 
258
 
259
+ description = (
260
+ "Performs subject agnostic identity transfer from a source face to all target faces. \n\n"
261
+ "Implementation and demo of FaceDancer, accepted to WACV 2023. \n\n"
262
+ "Pre-print: https://arxiv.org/abs/2210.10473 \n\n"
263
+ "Code: https://github.com/felixrosberg/FaceDancer \n\n"
264
+ "\n\n"
265
+ "Options:\n\n"
266
+ "-Compare returns the target image concatenated with the results.\n\n"
267
+ "-Anonymize will ignore the source image and perform an identity permutation of target faces.\n\n"
268
+ "-Reconstruction attack will attempt to invert the face swap or the anonymization.\n\n"
269
+ "-Adversarial defense will add a permutation noise that disrupts the reconstruction attack.\n\n"
270
+ "NOTE: There is no guarantees with the anonymization process currently.\n\n"
271
+ "NOTE: source image with too high resolution may not work properly!"
272
+ )
273
+ examples = [
274
+ ["assets/rick.jpg", "assets/musk.jpg", 100, 10, ["compare"]],
275
+ ["assets/musk.jpg", "assets/musk.jpg", 100, 10, ["anonymize"]],
276
+ ]
277
  article = """
278
  Demo is based of recent research from my Ph.D work. Results expects to be published in the coming months.
279
  """
280
 
281
+ iface = gradio.Interface(
282
+ run_inference,
283
+ [
284
+ gradio.inputs.Image(shape=None, label="Target"),
285
+ gradio.inputs.Image(shape=None, label="Source"),
286
+ gradio.inputs.Slider(0, 100, default=100, label="Anonymization ratio (%)"),
287
+ gradio.inputs.Slider(
288
+ 0, 100, default=100, label="Adversarial defense ratio (%)"
289
+ ),
290
+ gradio.inputs.CheckboxGroup(
291
+ ["compare", "anonymize", "reconstruction attack", "adversarial defense"],
292
+ label="Options",
293
+ ),
294
+ ],
295
+ gradio.outputs.Image(),
296
+ title="Face Swap",
297
+ description=description,
298
+ examples=examples,
299
+ article=article,
300
+ layout="vertical",
301
+ )
302
  iface.launch()