felixrosberg commited on
Commit
5ba0d7c
·
1 Parent(s): 78ea43a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +226 -4
app.py CHANGED
@@ -12,8 +12,230 @@ token = os.environ['model_fetch']
12
 
13
  anonymizer_repo = Repository(local_dir="anonymizer", clone_from="felixrosberg/anonymizer", use_auth_token=token)
14
 
15
- from anonymizer.face_anonymizer_image_v5_3dmm_obscured_work import fetch_demo
16
 
17
- anonymizer_demo = fetch_demo()
18
- anonymizer_demo.queue()
19
- anonymizer_demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  anonymizer_repo = Repository(local_dir="anonymizer", clone_from="felixrosberg/anonymizer", use_auth_token=token)
14
 
15
+ from anonymizer.face_anonymizer_image_v5_3dmm_obscured_work import *
16
 
17
+ description = "Interactive demo of facial anonymization for images. " \
18
+ "You can also perform " \
19
+ "zero-shot face swapping using the anonymizer. **Note** that this model " \
20
+ "display " \
21
+ "an interesting behaviour, where it in most cases preserves ethnicity and gender even if source and " \
22
+ "target differ in these two attributes. You can also play around with *reconstruction attacks*, an adversarial " \
23
+ "model that can revert the anonymization. Furthermore, you can choose to include adversarial defense " \
24
+ "noise against the *reconstruction attack* model.\n\n"
25
+
26
+ article = "## Options \n " \
27
+ "- **Zero-shot face swap**: Performs face swap using the *name pending* anonymizer. \n" \
28
+ "- **Reconstruction attack**: After anonymization or face swap, performs a reconstruction attack, " \
29
+ "retrieving the original identity. \n " \
30
+ "- **Adverarial Defense**: Applies a uniform noise after anonymization or face swap, before a " \
31
+ "reconstruction attack, disrupting the reconstruction attack. \n " \
32
+ "- **Use anchor**: With this option, we generate anchor identities from precalculated identities. If " \
33
+ "this is not used, the original identity could be easily figured out be searching for a match with " \
34
+ "-z, where z is an identity embedding in a data base. \n" \
35
+ "- **3DMM**: Change to model regularized by a 3D Morphable Model. Better pose performance, slightly worse " \
36
+ "identity performance. As of now, reconstruction attack does not work on this model. \n" \
37
+ "## Sliders \n " \
38
+ "- **Defense Strength**: Controls how much adversarial defense noise to add. \n " \
39
+ "- **Margin**: Controls the cosine distance margin allowed when sampling anonymization identities. \n " \
40
+ "- **SLERP Factor**: Controls how the anchors are established. Expect variation in the anonymized face " \
41
+ "when changing this together with the margin. \n" \
42
+ "- **ID Interpolation**: Controls linear interpolation between target and source identity. \n " \
43
+ "- **Detection Scale**: Resizes the images with given value before passing the the detector. Useful " \
44
+ "for image with smaller faces that the detector struggle to detect. Increases inference time if > 1 " \
45
+ "and vice versa. \n" \
46
+ "## Outputs \n " \
47
+ "- **Output**: Manipulated face(s), anonymization, face swap, reconstruction attack etc. \n " \
48
+ "- **Mask**: The predicted mask from the model or the reconstruction attack model. \n" \
49
+ "- **Cosine Distances**: The mean cosine distance between anonymized face, target, inverse target, " \
50
+ "source and reconstruction. Visualizes the identity difference. If there are several faces present, " \
51
+ "this will demonstrate the mean. \n\n" \
52
+ "To consider the anonymization a success, we generally want the cosine distance between anonymized and " \
53
+ "target, anonymized and inverse target, and target and reconstruction to be > 0.63 (the " \
54
+ "threshold for ArcFace for a false acceptance rate of 0.001). \n \n" \
55
+ "## Disclaimer: DeepFake Capabilities \n " \
56
+ "This model is able to do identity swaps that is able to be exceptionally convincing for state-of-the-art facial " \
57
+ "recognition models. However, when changing the identity, the results are perceptually limited. Meaning that in " \
58
+ "most cases you are not really to notice the imposed identity. Thus, it is NOT practical for deep faking people in " \
59
+ "a malicious manner. To summaries, DeepFake capabilities are poor, anonymization capabilities are strong!"
60
+
61
+ theme = gr.themes.Monochrome(
62
+ secondary_hue="emerald",
63
+ neutral_hue="teal",
64
+ ).set(
65
+ body_background_fill='*primary_950',
66
+ body_background_fill_dark='*secondary_950',
67
+ body_text_color='*primary_50',
68
+ body_text_color_dark='*secondary_100',
69
+ body_text_color_subdued='*primary_300',
70
+ body_text_color_subdued_dark='*primary_300',
71
+ background_fill_primary='*primary_600',
72
+ background_fill_primary_dark='*primary_400',
73
+ background_fill_secondary='*primary_950',
74
+ background_fill_secondary_dark='*primary_950',
75
+ border_color_accent='*secondary_600',
76
+ border_color_primary='*secondary_50',
77
+ border_color_primary_dark='*secondary_50',
78
+ color_accent='*secondary_50',
79
+ color_accent_soft='*primary_500',
80
+ color_accent_soft_dark='*primary_500',
81
+ link_text_color='*secondary_950',
82
+ link_text_color_dark='*primary_50',
83
+ link_text_color_active='*primary_50',
84
+ link_text_color_active_dark='*primary_50',
85
+ link_text_color_hover='*primary_50',
86
+ link_text_color_hover_dark='*primary_50',
87
+ link_text_color_visited='*primary_50',
88
+ block_background_fill='*primary_950',
89
+ block_background_fill_dark='*primary_950',
90
+ block_border_color='*secondary_500',
91
+ block_border_color_dark='*secondary_500',
92
+ block_info_text_color='*primary_50',
93
+ block_info_text_color_dark='*primary_50',
94
+ block_label_background_fill='*primary_950',
95
+ block_label_background_fill_dark='*secondary_950',
96
+ block_label_border_color='*secondary_500',
97
+ block_label_border_color_dark='*secondary_500',
98
+ block_label_text_color='*secondary_500',
99
+ block_label_text_color_dark='*secondary_500',
100
+ block_title_background_fill='*primary_950',
101
+ panel_background_fill='*primary_950',
102
+ panel_border_color='*primary_950',
103
+ checkbox_background_color='*primary_950',
104
+ checkbox_background_color_dark='*primary_950',
105
+ checkbox_background_color_focus='*primary_950',
106
+ checkbox_border_color='*secondary_500',
107
+ input_background_fill='*primary_800',
108
+ input_background_fill_focus='*primary_950',
109
+ input_background_fill_hover='*secondary_950',
110
+ input_placeholder_color='*secondary_950',
111
+ slider_color='*primary_950',
112
+ slider_color_dark='*primary_950',
113
+ table_even_background_fill='*primary_800',
114
+ table_odd_background_fill='*primary_600',
115
+ button_primary_background_fill='*primary_800',
116
+ button_primary_background_fill_dark='*primary_800'
117
+ )
118
+
119
+ random_ch = ['_', '/', '|', '*', '.', '#', '¤', '£', '?', '!', '%', '~', '^', '-', '=', '@', 'o', ']', '[', '§', 'o']
120
+
121
+
122
+ def button_change(inputs):
123
+ if "Reconstruction Attack" in inputs and "Zero-shot Face Swap" in inputs:
124
+ s_s = ""
125
+ for s in "Face Swap and Reconstruct":
126
+ ch_0 = random_ch[np.random.randint(len(random_ch))]
127
+ ch_1 = random_ch[np.random.randint(len(random_ch))]
128
+ s_s += s
129
+ time.sleep(0.01)
130
+ yield gr.Button(ch_0 + s_s + ch_1), gr.CheckboxGroup(value=inputs, interactive=False)
131
+ time.sleep(0.01)
132
+ yield gr.Button(s_s), gr.CheckboxGroup(value=inputs, interactive=True)
133
+ elif "Reconstruction Attack" in inputs and "Zero-shot Face Swap" not in inputs:
134
+ s_s = ""
135
+ for s in "Anonymize and Reconstruct":
136
+ ch_0 = random_ch[np.random.randint(len(random_ch))]
137
+ ch_1 = random_ch[np.random.randint(len(random_ch))]
138
+ s_s += s
139
+ time.sleep(0.01)
140
+ yield gr.Button(ch_0 + s_s + ch_1), gr.CheckboxGroup(value=inputs, interactive=False)
141
+ time.sleep(0.01)
142
+ yield gr.Button(s_s), gr.CheckboxGroup(value=inputs, interactive=True)
143
+ elif "Zero-shot Face Swap" in inputs:
144
+ s_s = ""
145
+ for s in "Face Swap":
146
+ ch_0 = random_ch[np.random.randint(len(random_ch))]
147
+ ch_1 = random_ch[np.random.randint(len(random_ch))]
148
+ s_s += s
149
+ time.sleep(0.03)
150
+ yield gr.Button(ch_0 + s_s + ch_1), gr.CheckboxGroup(value=inputs, interactive=False)
151
+ time.sleep(0.03)
152
+ yield gr.Button(s_s), gr.CheckboxGroup(value=inputs, interactive=True)
153
+ else:
154
+ s_s = ""
155
+ for s in "Anonymize":
156
+ ch_0 = random_ch[np.random.randint(len(random_ch))]
157
+ ch_1 = random_ch[np.random.randint(len(random_ch))]
158
+ s_s += s
159
+ time.sleep(0.03)
160
+ yield gr.Button(ch_0 + s_s + ch_1), gr.CheckboxGroup(value=inputs, interactive=False)
161
+ time.sleep(0.03)
162
+ yield gr.Button(s_s), gr.CheckboxGroup(value=inputs, interactive=True)
163
+
164
+
165
+ with gr.Blocks(theme=theme,
166
+ css=""".gradio-container {background: url('file=anonymizer/assets/background6.gif')}""") as blk_demo:
167
+ gr.Markdown(value="# Face Anonymizer")
168
+ with gr.Row():
169
+ with gr.Column():
170
+ with gr.Box():
171
+ trg_in = gr.Image(type="pil", label='Target', height=300)
172
+ src_in = gr.Image(type="pil", label='Source', height=300)
173
+ with gr.Row():
174
+ b1 = gr.Button("Anonymize")
175
+ with gr.Row():
176
+ with gr.Accordion("Options", open=False):
177
+ chk_in = gr.CheckboxGroup(["Zero-shot Face Swap",
178
+ "Reconstruction Attack",
179
+ "Adversarial Defense",
180
+ "Use Anchor",
181
+ "3DMM"],
182
+ value=["Use Anchor"],
183
+ label="Mode",
184
+ info="Perform zero-shot face swap? "
185
+ "Apply reconstruction attack? "
186
+ "Apply defense against reconstruction attack? "
187
+ "Use anchor identities for fake sampling?")
188
+ def_in = gr.Slider(0.0, 0.2, value=0.1,
189
+ label='Defense Strength',
190
+ info="Strength of the defense noise against reconstruction attacks.")
191
+ mrg_in = gr.Slider(0.0, 1.0, value=0.3,
192
+ label='Margin',
193
+ info="Margin for sampling fake identities.")
194
+ slp_in = gr.Slider(0.0, 1.0, value=0.5,
195
+ label='SLERP Factor',
196
+ info="SLERP disance when establishing anchor identities.")
197
+ idi_in = gr.Slider(0.0, 1.0, value=0.0,
198
+ label='ID Interpolation',
199
+ info="Interpolation between target and source id vectors.")
200
+ det_in = gr.Slider(0.1, 2.0, value=1.0,
201
+ label='Detection Scale',
202
+ info="Resizes the images before passing to the detector.")
203
+
204
+ gr.Examples(examples=[['anonymizer/assets/0.jpg'], ['anonymizer/assets/1.jpg'], ['anonymizer/assets/2.jpg'], ['anonymizer/assets/3.jpg'], ['anonymizer/assets/4.jpg']],
205
+ inputs=trg_in)
206
+ with gr.Column():
207
+ with gr.Box():
208
+ ano_out = gr.Image(type="pil", label='Output', height=300, min_width=0)
209
+ msk_out = gr.Image(type="pil", label='Mask', height=300, min_width=0)
210
+ with gr.Row():
211
+ with gr.Accordion("Cosine Distances", open=False):
212
+ plt_out_0 = gr.Slider(0.0, 2.0, value=0.0, label='',
213
+ info="Anonymized and target")
214
+ plt_out_1 = gr.Slider(0.0, 2.0, value=0.0, label='',
215
+ info="Anonymized and source")
216
+ plt_out_2 = gr.Slider(0.0, 2.0, value=0.0, label='',
217
+ info="Anonymized and -target")
218
+ plt_out_3 = gr.Slider(0.0, 2.0, value=0.0, label='',
219
+ info="Target and source")
220
+ plt_out_4 = gr.Slider(0.0, 2.0, value=0.0, label='',
221
+ info="Anonymized and reconstructed")
222
+ plt_out_5 = gr.Slider(0.0, 2.0, value=0.0, label='',
223
+ info="Target and reconstructed")
224
+ cos_info_box = gr.Markdown("Cosine distance between embeddings of target, anonymized, "
225
+ "reconstruction and source. Note that source is the fake identity "
226
+ "when using the default anonymization (which will be similar or the same "
227
+ "depending on if anchor identities are used). Threshold for False Acceptance "
228
+ "Rate (FAR) of 0.001 is 0.63. If you anonymize using no anchors, you can expect facial "
229
+ "recognition will find the true identity by searching for -target.")
230
+ with gr.Row():
231
+ with gr.Accordion("Information", open=False):
232
+ with gr.Box():
233
+ info_box = gr.Markdown(description + article)
234
+
235
+ b1.click(inference, inputs=[trg_in, src_in, chk_in, def_in, mrg_in, slp_in, idi_in, det_in],
236
+ outputs=[ano_out, msk_out, plt_out_0, plt_out_1, plt_out_2, plt_out_3, plt_out_4, plt_out_5])
237
+ chk_in.change(button_change, inputs=[chk_in], outputs=[b1, chk_in], queue=True)
238
+
239
+
240
+ blk_demo.queue()
241
+ blk_demo.launch()