andro1241 commited on
Commit
0581c5f
·
verified ·
1 Parent(s): 6f5fee3

Upload 4 files

Browse files
processors/modules/face_swapper/choices.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List, Sequence, get_args
2
+
3
+ from facefusion.common_helper import create_float_range
4
+ from facefusion.processors.modules.face_swapper.types import FaceSwapperModel, FaceSwapperSet, FaceSwapperWeight
5
+
6
+
7
+ face_swapper_set : FaceSwapperSet =\
8
+ {
9
+ 'blendswap_256': [ '256x256', '384x384', '512x512', '768x768', '1024x1024' ],
10
+ 'ghost_1_256': [ '256x256', '512x512', '768x768', '1024x1024' ],
11
+ 'ghost_2_256': [ '256x256', '512x512', '768x768', '1024x1024' ],
12
+ 'ghost_3_256': [ '256x256', '512x512', '768x768', '1024x1024' ],
13
+ 'hififace_unofficial_256': [ '256x256', '512x512', '768x768', '1024x1024' ],
14
+ 'hyperswap_1a_256': [ '256x256', '512x512', '768x768', '1024x1024' ],
15
+ 'hyperswap_1b_256': [ '256x256', '512x512', '768x768', '1024x1024' ],
16
+ 'hyperswap_1c_256': [ '256x256', '512x512', '768x768', '1024x1024' ],
17
+ 'inswapper_128': [ '128x128', '256x256', '384x384', '512x512', '768x768', '1024x1024' ],
18
+ 'inswapper_128_fp16': [ '128x128', '256x256', '384x384', '512x512', '768x768', '1024x1024' ],
19
+ 'simswap_256': [ '256x256', '512x512', '768x768', '1024x1024' ],
20
+ 'simswap_unofficial_512': [ '512x512', '768x768', '1024x1024' ],
21
+ 'uniface_256': [ '256x256', '512x512', '768x768', '1024x1024' ]
22
+ }
23
+
24
+ face_swapper_models : List[FaceSwapperModel] = list(get_args(FaceSwapperModel))
25
+
26
+ face_swapper_weight_range : Sequence[FaceSwapperWeight] = create_float_range(0.0, 1.0, 0.05)
processors/modules/face_swapper/core.py ADDED
@@ -0,0 +1,794 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from argparse import ArgumentParser
2
+ from functools import lru_cache
3
+ from types import ModuleType
4
+ from typing import List, Optional, Tuple
5
+
6
+ import cv2
7
+ import numpy
8
+
9
+ import facefusion.choices
10
+ import facefusion.jobs.job_manager
11
+ import facefusion.jobs.job_store
12
+ from facefusion import config, content_analyser, face_classifier, face_detector, face_landmarker, face_masker, face_recognizer, inference_manager, logger, state_manager, translator, video_manager
13
+ from facefusion.common_helper import get_first, get_middle, is_macos
14
+ from facefusion.download import conditional_download_hashes, conditional_download_sources, resolve_download_url
15
+ from facefusion.execution import has_execution_provider
16
+ from facefusion.face_creator import average_face_identity, get_one_face, get_static_faces, scale_face
17
+ from facefusion.face_helper import paste_back, warp_face_by_face_landmark_5
18
+ from facefusion.face_masker import create_area_mask, create_box_mask, create_occlusion_mask, create_region_mask
19
+ from facefusion.face_selector import select_faces, sort_faces_by_order
20
+ from facefusion.filesystem import filter_image_paths, has_image, in_directory, is_image, is_video, resolve_relative_path, same_file_extension
21
+ from facefusion.model_helper import get_static_model_initializer
22
+ from facefusion.processors.modules.face_swapper import choices as face_swapper_choices
23
+ from facefusion.processors.modules.face_swapper.types import FaceSwapperInputs
24
+ from facefusion.processors.pixel_boost import explode_pixel_boost, implode_pixel_boost
25
+ from facefusion.processors.types import ProcessorOutputs
26
+ from facefusion.program_helper import find_argument_group
27
+ from facefusion.thread_helper import conditional_thread_semaphore
28
+ from facefusion.types import ApplyStateItem, Args, DownloadScope, Embedding, Face, InferencePool, InferenceProvider, ModelOptions, ModelSet, ProcessMode, VisionFrame
29
+ from facefusion.vision import read_static_image, read_static_images, read_static_video_frame, unpack_resolution
30
+
31
+
32
+ @lru_cache()
33
+ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
34
+ return\
35
+ {
36
+ 'blendswap_256':
37
+ {
38
+ '__metadata__':
39
+ {
40
+ 'vendor': 'mapooon',
41
+ 'license': 'Non-Commercial',
42
+ 'year': 2023
43
+ },
44
+ 'hashes':
45
+ {
46
+ 'face_swapper':
47
+ {
48
+ 'url': resolve_download_url('models-3.0.0', 'blendswap_256.hash'),
49
+ 'path': resolve_relative_path('../.assets/models/blendswap_256.hash')
50
+ }
51
+ },
52
+ 'sources':
53
+ {
54
+ 'face_swapper':
55
+ {
56
+ 'url': resolve_download_url('models-3.0.0', 'blendswap_256.onnx'),
57
+ 'path': resolve_relative_path('../.assets/models/blendswap_256.onnx')
58
+ }
59
+ },
60
+ 'type': 'blendswap',
61
+ 'template': 'ffhq_512',
62
+ 'size': (256, 256),
63
+ 'mean': [ 0.0, 0.0, 0.0 ],
64
+ 'standard_deviation': [ 1.0, 1.0, 1.0 ]
65
+ },
66
+ 'ghost_1_256':
67
+ {
68
+ '__metadata__':
69
+ {
70
+ 'vendor': 'ai-forever',
71
+ 'license': 'Apache-2.0',
72
+ 'year': 2022
73
+ },
74
+ 'hashes':
75
+ {
76
+ 'face_swapper':
77
+ {
78
+ 'url': resolve_download_url('models-3.0.0', 'ghost_1_256.hash'),
79
+ 'path': resolve_relative_path('../.assets/models/ghost_1_256.hash')
80
+ },
81
+ 'embedding_converter':
82
+ {
83
+ 'url': resolve_download_url('models-3.4.0', 'crossface_ghost.hash'),
84
+ 'path': resolve_relative_path('../.assets/models/crossface_ghost.hash')
85
+ }
86
+ },
87
+ 'sources':
88
+ {
89
+ 'face_swapper':
90
+ {
91
+ 'url': resolve_download_url('models-3.0.0', 'ghost_1_256.onnx'),
92
+ 'path': resolve_relative_path('../.assets/models/ghost_1_256.onnx')
93
+ },
94
+ 'embedding_converter':
95
+ {
96
+ 'url': resolve_download_url('models-3.4.0', 'crossface_ghost.onnx'),
97
+ 'path': resolve_relative_path('../.assets/models/crossface_ghost.onnx')
98
+ }
99
+ },
100
+ 'type': 'ghost',
101
+ 'template': 'arcface_112_v1',
102
+ 'size': (256, 256),
103
+ 'mean': [ 0.5, 0.5, 0.5 ],
104
+ 'standard_deviation': [ 0.5, 0.5, 0.5 ]
105
+ },
106
+ 'ghost_2_256':
107
+ {
108
+ '__metadata__':
109
+ {
110
+ 'vendor': 'ai-forever',
111
+ 'license': 'Apache-2.0',
112
+ 'year': 2022
113
+ },
114
+ 'hashes':
115
+ {
116
+ 'face_swapper':
117
+ {
118
+ 'url': resolve_download_url('models-3.0.0', 'ghost_2_256.hash'),
119
+ 'path': resolve_relative_path('../.assets/models/ghost_2_256.hash')
120
+ },
121
+ 'embedding_converter':
122
+ {
123
+ 'url': resolve_download_url('models-3.4.0', 'crossface_ghost.hash'),
124
+ 'path': resolve_relative_path('../.assets/models/crossface_ghost.hash')
125
+ }
126
+ },
127
+ 'sources':
128
+ {
129
+ 'face_swapper':
130
+ {
131
+ 'url': resolve_download_url('models-3.0.0', 'ghost_2_256.onnx'),
132
+ 'path': resolve_relative_path('../.assets/models/ghost_2_256.onnx')
133
+ },
134
+ 'embedding_converter':
135
+ {
136
+ 'url': resolve_download_url('models-3.4.0', 'crossface_ghost.onnx'),
137
+ 'path': resolve_relative_path('../.assets/models/crossface_ghost.onnx')
138
+ }
139
+ },
140
+ 'type': 'ghost',
141
+ 'template': 'arcface_112_v1',
142
+ 'size': (256, 256),
143
+ 'mean': [ 0.5, 0.5, 0.5 ],
144
+ 'standard_deviation': [ 0.5, 0.5, 0.5 ]
145
+ },
146
+ 'ghost_3_256':
147
+ {
148
+ '__metadata__':
149
+ {
150
+ 'vendor': 'ai-forever',
151
+ 'license': 'Apache-2.0',
152
+ 'year': 2022
153
+ },
154
+ 'hashes':
155
+ {
156
+ 'face_swapper':
157
+ {
158
+ 'url': resolve_download_url('models-3.0.0', 'ghost_3_256.hash'),
159
+ 'path': resolve_relative_path('../.assets/models/ghost_3_256.hash')
160
+ },
161
+ 'embedding_converter':
162
+ {
163
+ 'url': resolve_download_url('models-3.4.0', 'crossface_ghost.hash'),
164
+ 'path': resolve_relative_path('../.assets/models/crossface_ghost.hash')
165
+ }
166
+ },
167
+ 'sources':
168
+ {
169
+ 'face_swapper':
170
+ {
171
+ 'url': resolve_download_url('models-3.0.0', 'ghost_3_256.onnx'),
172
+ 'path': resolve_relative_path('../.assets/models/ghost_3_256.onnx')
173
+ },
174
+ 'embedding_converter':
175
+ {
176
+ 'url': resolve_download_url('models-3.4.0', 'crossface_ghost.onnx'),
177
+ 'path': resolve_relative_path('../.assets/models/crossface_ghost.onnx')
178
+ }
179
+ },
180
+ 'type': 'ghost',
181
+ 'template': 'arcface_112_v1',
182
+ 'size': (256, 256),
183
+ 'mean': [ 0.5, 0.5, 0.5 ],
184
+ 'standard_deviation': [ 0.5, 0.5, 0.5 ]
185
+ },
186
+ 'hififace_unofficial_256':
187
+ {
188
+ '__metadata__':
189
+ {
190
+ 'vendor': 'GuijiAI',
191
+ 'license': 'Unknown',
192
+ 'year': 2021
193
+ },
194
+ 'hashes':
195
+ {
196
+ 'face_swapper':
197
+ {
198
+ 'url': resolve_download_url('models-3.1.0', 'hififace_unofficial_256.hash'),
199
+ 'path': resolve_relative_path('../.assets/models/hififace_unofficial_256.hash')
200
+ },
201
+ 'embedding_converter':
202
+ {
203
+ 'url': resolve_download_url('models-3.4.0', 'crossface_hififace.hash'),
204
+ 'path': resolve_relative_path('../.assets/models/crossface_hififace.hash')
205
+ }
206
+ },
207
+ 'sources':
208
+ {
209
+ 'face_swapper':
210
+ {
211
+ 'url': resolve_download_url('models-3.1.0', 'hififace_unofficial_256.onnx'),
212
+ 'path': resolve_relative_path('../.assets/models/hififace_unofficial_256.onnx')
213
+ },
214
+ 'embedding_converter':
215
+ {
216
+ 'url': resolve_download_url('models-3.4.0', 'crossface_hififace.onnx'),
217
+ 'path': resolve_relative_path('../.assets/models/crossface_hififace.onnx')
218
+ }
219
+ },
220
+ 'type': 'hififace',
221
+ 'template': 'mtcnn_512',
222
+ 'size': (256, 256),
223
+ 'mean': [ 0.5, 0.5, 0.5 ],
224
+ 'standard_deviation': [ 0.5, 0.5, 0.5 ]
225
+ },
226
+ 'hyperswap_1a_256':
227
+ {
228
+ '__metadata__':
229
+ {
230
+ 'vendor': 'FaceFusion',
231
+ 'license': 'ResearchRAIL',
232
+ 'year': 2025
233
+ },
234
+ 'hashes':
235
+ {
236
+ 'face_swapper':
237
+ {
238
+ 'url': resolve_download_url('models-3.3.0', 'hyperswap_1a_256.hash'),
239
+ 'path': resolve_relative_path('../.assets/models/hyperswap_1a_256.hash')
240
+ }
241
+ },
242
+ 'sources':
243
+ {
244
+ 'face_swapper':
245
+ {
246
+ 'url': resolve_download_url('models-3.3.0', 'hyperswap_1a_256.onnx'),
247
+ 'path': resolve_relative_path('../.assets/models/hyperswap_1a_256.onnx')
248
+ }
249
+ },
250
+ 'precision': 'fp16',
251
+ 'type': 'hyperswap',
252
+ 'template': 'arcface_128',
253
+ 'size': (256, 256),
254
+ 'mean': [ 0.5, 0.5, 0.5 ],
255
+ 'standard_deviation': [ 0.5, 0.5, 0.5 ]
256
+ },
257
+ 'hyperswap_1b_256':
258
+ {
259
+ '__metadata__':
260
+ {
261
+ 'vendor': 'FaceFusion',
262
+ 'license': 'ResearchRAIL',
263
+ 'year': 2025
264
+ },
265
+ 'hashes':
266
+ {
267
+ 'face_swapper':
268
+ {
269
+ 'url': resolve_download_url('models-3.3.0', 'hyperswap_1b_256.hash'),
270
+ 'path': resolve_relative_path('../.assets/models/hyperswap_1b_256.hash')
271
+ }
272
+ },
273
+ 'sources':
274
+ {
275
+ 'face_swapper':
276
+ {
277
+ 'url': resolve_download_url('models-3.3.0', 'hyperswap_1b_256.onnx'),
278
+ 'path': resolve_relative_path('../.assets/models/hyperswap_1b_256.onnx')
279
+ }
280
+ },
281
+ 'precision': 'fp16',
282
+ 'type': 'hyperswap',
283
+ 'template': 'arcface_128',
284
+ 'size': (256, 256),
285
+ 'mean': [ 0.5, 0.5, 0.5 ],
286
+ 'standard_deviation': [ 0.5, 0.5, 0.5 ]
287
+ },
288
+ 'hyperswap_1c_256':
289
+ {
290
+ '__metadata__':
291
+ {
292
+ 'vendor': 'FaceFusion',
293
+ 'license': 'ResearchRAIL',
294
+ 'year': 2025
295
+ },
296
+ 'hashes':
297
+ {
298
+ 'face_swapper':
299
+ {
300
+ 'url': resolve_download_url('models-3.3.0', 'hyperswap_1c_256.hash'),
301
+ 'path': resolve_relative_path('../.assets/models/hyperswap_1c_256.hash')
302
+ }
303
+ },
304
+ 'sources':
305
+ {
306
+ 'face_swapper':
307
+ {
308
+ 'url': resolve_download_url('models-3.3.0', 'hyperswap_1c_256.onnx'),
309
+ 'path': resolve_relative_path('../.assets/models/hyperswap_1c_256.onnx')
310
+ }
311
+ },
312
+ 'precision': 'fp16',
313
+ 'type': 'hyperswap',
314
+ 'template': 'arcface_128',
315
+ 'size': (256, 256),
316
+ 'mean': [ 0.5, 0.5, 0.5 ],
317
+ 'standard_deviation': [ 0.5, 0.5, 0.5 ]
318
+ },
319
+ 'inswapper_128':
320
+ {
321
+ '__metadata__':
322
+ {
323
+ 'vendor': 'InsightFace',
324
+ 'license': 'Non-Commercial',
325
+ 'year': 2023
326
+ },
327
+ 'hashes':
328
+ {
329
+ 'face_swapper':
330
+ {
331
+ 'url': resolve_download_url('models-3.0.0', 'inswapper_128.hash'),
332
+ 'path': resolve_relative_path('../.assets/models/inswapper_128.hash')
333
+ }
334
+ },
335
+ 'sources':
336
+ {
337
+ 'face_swapper':
338
+ {
339
+ 'url': resolve_download_url('models-3.0.0', 'inswapper_128.onnx'),
340
+ 'path': resolve_relative_path('../.assets/models/inswapper_128.onnx')
341
+ }
342
+ },
343
+ 'type': 'inswapper',
344
+ 'template': 'arcface_128',
345
+ 'size': (128, 128),
346
+ 'mean': [ 0.0, 0.0, 0.0 ],
347
+ 'standard_deviation': [ 1.0, 1.0, 1.0 ]
348
+ },
349
+ 'inswapper_128_fp16':
350
+ {
351
+ '__metadata__':
352
+ {
353
+ 'vendor': 'InsightFace',
354
+ 'license': 'Non-Commercial',
355
+ 'year': 2023
356
+ },
357
+ 'hashes':
358
+ {
359
+ 'face_swapper':
360
+ {
361
+ 'url': resolve_download_url('models-3.0.0', 'inswapper_128_fp16.hash'),
362
+ 'path': resolve_relative_path('../.assets/models/inswapper_128_fp16.hash')
363
+ }
364
+ },
365
+ 'sources':
366
+ {
367
+ 'face_swapper':
368
+ {
369
+ 'url': resolve_download_url('models-3.0.0', 'inswapper_128_fp16.onnx'),
370
+ 'path': resolve_relative_path('../.assets/models/inswapper_128_fp16.onnx')
371
+ }
372
+ },
373
+ 'precision': 'fp16',
374
+ 'type': 'inswapper',
375
+ 'template': 'arcface_128',
376
+ 'size': (128, 128),
377
+ 'mean': [ 0.0, 0.0, 0.0 ],
378
+ 'standard_deviation': [ 1.0, 1.0, 1.0 ]
379
+ },
380
+ 'simswap_256':
381
+ {
382
+ '__metadata__':
383
+ {
384
+ 'vendor': 'neuralchen',
385
+ 'license': 'Non-Commercial',
386
+ 'year': 2020
387
+ },
388
+ 'hashes':
389
+ {
390
+ 'face_swapper':
391
+ {
392
+ 'url': resolve_download_url('models-3.0.0', 'simswap_256.hash'),
393
+ 'path': resolve_relative_path('../.assets/models/simswap_256.hash')
394
+ },
395
+ 'embedding_converter':
396
+ {
397
+ 'url': resolve_download_url('models-3.4.0', 'crossface_simswap.hash'),
398
+ 'path': resolve_relative_path('../.assets/models/crossface_simswap.hash')
399
+ }
400
+ },
401
+ 'sources':
402
+ {
403
+ 'face_swapper':
404
+ {
405
+ 'url': resolve_download_url('models-3.0.0', 'simswap_256.onnx'),
406
+ 'path': resolve_relative_path('../.assets/models/simswap_256.onnx')
407
+ },
408
+ 'embedding_converter':
409
+ {
410
+ 'url': resolve_download_url('models-3.4.0', 'crossface_simswap.onnx'),
411
+ 'path': resolve_relative_path('../.assets/models/crossface_simswap.onnx')
412
+ }
413
+ },
414
+ 'type': 'simswap',
415
+ 'template': 'arcface_112_v1',
416
+ 'size': (256, 256),
417
+ 'mean': [ 0.485, 0.456, 0.406 ],
418
+ 'standard_deviation': [ 0.229, 0.224, 0.225 ]
419
+ },
420
+ 'simswap_unofficial_512':
421
+ {
422
+ '__metadata__':
423
+ {
424
+ 'vendor': 'neuralchen',
425
+ 'license': 'Non-Commercial',
426
+ 'year': 2020
427
+ },
428
+ 'hashes':
429
+ {
430
+ 'face_swapper':
431
+ {
432
+ 'url': resolve_download_url('models-3.0.0', 'simswap_unofficial_512.hash'),
433
+ 'path': resolve_relative_path('../.assets/models/simswap_unofficial_512.hash')
434
+ },
435
+ 'embedding_converter':
436
+ {
437
+ 'url': resolve_download_url('models-3.4.0', 'crossface_simswap.hash'),
438
+ 'path': resolve_relative_path('../.assets/models/crossface_simswap.hash')
439
+ }
440
+ },
441
+ 'sources':
442
+ {
443
+ 'face_swapper':
444
+ {
445
+ 'url': resolve_download_url('models-3.0.0', 'simswap_unofficial_512.onnx'),
446
+ 'path': resolve_relative_path('../.assets/models/simswap_unofficial_512.onnx')
447
+ },
448
+ 'embedding_converter':
449
+ {
450
+ 'url': resolve_download_url('models-3.4.0', 'crossface_simswap.onnx'),
451
+ 'path': resolve_relative_path('../.assets/models/crossface_simswap.onnx')
452
+ }
453
+ },
454
+ 'type': 'simswap',
455
+ 'template': 'arcface_112_v1',
456
+ 'size': (512, 512),
457
+ 'mean': [ 0.0, 0.0, 0.0 ],
458
+ 'standard_deviation': [ 1.0, 1.0, 1.0 ]
459
+ },
460
+ 'uniface_256':
461
+ {
462
+ '__metadata__':
463
+ {
464
+ 'vendor': 'xc-csc101',
465
+ 'license': 'Unknown',
466
+ 'year': 2022
467
+ },
468
+ 'hashes':
469
+ {
470
+ 'face_swapper':
471
+ {
472
+ 'url': resolve_download_url('models-3.0.0', 'uniface_256.hash'),
473
+ 'path': resolve_relative_path('../.assets/models/uniface_256.hash')
474
+ }
475
+ },
476
+ 'sources':
477
+ {
478
+ 'face_swapper':
479
+ {
480
+ 'url': resolve_download_url('models-3.0.0', 'uniface_256.onnx'),
481
+ 'path': resolve_relative_path('../.assets/models/uniface_256.onnx')
482
+ }
483
+ },
484
+ 'type': 'uniface',
485
+ 'template': 'ffhq_512',
486
+ 'size': (256, 256),
487
+ 'mean': [ 0.5, 0.5, 0.5 ],
488
+ 'standard_deviation': [ 0.5, 0.5, 0.5 ]
489
+ }
490
+ }
491
+
492
+
493
+ def get_inference_pool() -> InferencePool:
494
+ model_names = [ state_manager.get_item('face_swapper_model') ]
495
+ model_source_set = get_model_options().get('sources')
496
+
497
+ return inference_manager.get_inference_pool(__name__, model_names, model_source_set)
498
+
499
+
500
+ def clear_inference_pool() -> None:
501
+ model_names = [ state_manager.get_item('face_swapper_model') ]
502
+ inference_manager.clear_inference_pool(__name__, model_names)
503
+
504
+
505
+ def adjust_inference_providers() -> List[InferenceProvider]:
506
+ model_precision = get_model_options().get('precision')
507
+ model_type = get_model_options().get('type')
508
+
509
+ if is_macos() and has_execution_provider('coreml'):
510
+ if model_type in [ 'ghost', 'uniface' ] or model_precision == 'fp16':
511
+ return\
512
+ [
513
+ (facefusion.choices.execution_provider_set.get('coreml'),
514
+ {
515
+ 'ModelFormat': 'MLProgram'
516
+ })
517
+ ]
518
+
519
+ return []
520
+
521
+
522
+ def get_model_options() -> ModelOptions:
523
+ model_name = state_manager.get_item('face_swapper_model')
524
+ return create_static_model_set('full').get(model_name)
525
+
526
+
527
+ def register_args(program : ArgumentParser) -> None:
528
+ group_processors = find_argument_group(program, 'processors')
529
+ if group_processors:
530
+ group_processors.add_argument('--face-swapper-model', help = translator.get('help.model', __package__), default = config.get_str_value('processors', 'face_swapper_model', 'hyperswap_1a_256'), choices = face_swapper_choices.face_swapper_models)
531
+ known_args, _ = program.parse_known_args()
532
+ face_swapper_pixel_boost_choices = face_swapper_choices.face_swapper_set.get(known_args.face_swapper_model)
533
+ group_processors.add_argument('--face-swapper-pixel-boost', help = translator.get('help.pixel_boost', __package__), default = config.get_str_value('processors', 'face_swapper_pixel_boost', get_first(face_swapper_pixel_boost_choices)), choices = face_swapper_pixel_boost_choices)
534
+ group_processors.add_argument('--face-swapper-weight', help = translator.get('help.weight', __package__), type = float, default = config.get_float_value('processors', 'face_swapper_weight', '0.5'), choices = face_swapper_choices.face_swapper_weight_range)
535
+ facefusion.jobs.job_store.register_step_keys([ 'face_swapper_model', 'face_swapper_pixel_boost', 'face_swapper_weight' ])
536
+
537
+
538
+ def apply_args(args : Args, apply_state_item : ApplyStateItem) -> None:
539
+ apply_state_item('face_swapper_model', args.get('face_swapper_model'))
540
+ apply_state_item('face_swapper_pixel_boost', args.get('face_swapper_pixel_boost'))
541
+ apply_state_item('face_swapper_weight', args.get('face_swapper_weight'))
542
+
543
+
544
+ def get_common_modules() -> List[ModuleType]:
545
+ return [ content_analyser, face_classifier, face_detector, face_landmarker, face_masker, face_recognizer ]
546
+
547
+
548
+ def pre_check() -> bool:
549
+ model_hash_set = get_model_options().get('hashes')
550
+ model_source_set = get_model_options().get('sources')
551
+
552
+ for common_module in get_common_modules():
553
+ if not common_module.pre_check():
554
+ return False
555
+
556
+ return conditional_download_hashes(model_hash_set) and conditional_download_sources(model_source_set)
557
+
558
+
559
+ def pre_process(mode : ProcessMode) -> bool:
560
+ if not has_image(state_manager.get_item('source_paths')):
561
+ logger.error(translator.get('choose_image_source') + translator.get('exclamation_mark'), __name__)
562
+ return False
563
+
564
+ source_image_paths = filter_image_paths(state_manager.get_item('source_paths'))
565
+ source_vision_frames = read_static_images(source_image_paths)
566
+ source_faces = get_static_faces(source_vision_frames)
567
+
568
+ if not get_one_face(source_faces):
569
+ logger.error(translator.get('no_source_face_detected') + translator.get('exclamation_mark'), __name__)
570
+ return False
571
+
572
+ if mode in [ 'output', 'preview' ] and not is_image(state_manager.get_item('target_path')) and not is_video(state_manager.get_item('target_path')):
573
+ logger.error(translator.get('choose_image_or_video_target') + translator.get('exclamation_mark'), __name__)
574
+ return False
575
+
576
+ if mode == 'output' and not in_directory(state_manager.get_item('output_path')):
577
+ logger.error(translator.get('specify_image_or_video_output') + translator.get('exclamation_mark'), __name__)
578
+ return False
579
+
580
+ if mode == 'output' and not same_file_extension(state_manager.get_item('target_path'), state_manager.get_item('output_path')):
581
+ logger.error(translator.get('match_target_and_output_extension') + translator.get('exclamation_mark'), __name__)
582
+ return False
583
+
584
+ return True
585
+
586
+
587
+ def post_process() -> None:
588
+ read_static_image.cache_clear()
589
+ read_static_video_frame.cache_clear()
590
+ video_manager.clear_video_pool()
591
+
592
+ if state_manager.get_item('video_memory_strategy') in [ 'strict', 'moderate' ]:
593
+ get_static_model_initializer.cache_clear()
594
+ clear_inference_pool()
595
+
596
+ if state_manager.get_item('video_memory_strategy') == 'strict':
597
+ for common_module in get_common_modules():
598
+ common_module.clear_inference_pool()
599
+
600
+
601
+ def swap_face(source_face : Face, target_face : Face, source_vision_frame : VisionFrame, temp_vision_frame : VisionFrame) -> VisionFrame:
602
+ model_template = get_model_options().get('template')
603
+ model_size = get_model_options().get('size')
604
+ pixel_boost_size = unpack_resolution(state_manager.get_item('face_swapper_pixel_boost'))
605
+ pixel_boost_total = pixel_boost_size[0] // model_size[0]
606
+ crop_vision_frame, affine_matrix = warp_face_by_face_landmark_5(temp_vision_frame, target_face.landmark_set.get('5/68'), model_template, pixel_boost_size)
607
+ temp_vision_frames = []
608
+ crop_masks = []
609
+
610
+ if 'box' in state_manager.get_item('face_mask_types'):
611
+ box_mask = create_box_mask(crop_vision_frame, state_manager.get_item('face_mask_blur'), state_manager.get_item('face_mask_padding'))
612
+ crop_masks.append(box_mask)
613
+
614
+ if 'occlusion' in state_manager.get_item('face_mask_types'):
615
+ occlusion_mask = create_occlusion_mask(crop_vision_frame)
616
+ crop_masks.append(occlusion_mask)
617
+
618
+ pixel_boost_vision_frames = implode_pixel_boost(crop_vision_frame, pixel_boost_total, model_size)
619
+ for pixel_boost_vision_frame in pixel_boost_vision_frames:
620
+ pixel_boost_vision_frame = prepare_crop_frame(pixel_boost_vision_frame)
621
+ pixel_boost_vision_frame = forward_swap_face(source_face, target_face, source_vision_frame, pixel_boost_vision_frame)
622
+ pixel_boost_vision_frame = normalize_crop_frame(pixel_boost_vision_frame)
623
+ temp_vision_frames.append(pixel_boost_vision_frame)
624
+ crop_vision_frame = explode_pixel_boost(temp_vision_frames, pixel_boost_total, model_size, pixel_boost_size)
625
+
626
+ if 'area' in state_manager.get_item('face_mask_types'):
627
+ face_landmark_68 = cv2.transform(target_face.landmark_set.get('68').reshape(1, -1, 2), affine_matrix).reshape(-1, 2)
628
+ area_mask = create_area_mask(crop_vision_frame, face_landmark_68, state_manager.get_item('face_mask_areas'))
629
+ crop_masks.append(area_mask)
630
+
631
+ if 'region' in state_manager.get_item('face_mask_types'):
632
+ region_mask = create_region_mask(crop_vision_frame, state_manager.get_item('face_mask_regions'))
633
+ crop_masks.append(region_mask)
634
+
635
+ crop_mask = numpy.minimum.reduce(crop_masks).clip(0, 1)
636
+ paste_vision_frame = paste_back(temp_vision_frame, crop_vision_frame, crop_mask, affine_matrix)
637
+ return paste_vision_frame
638
+
639
+
640
+ def forward_swap_face(source_face : Face, target_face : Face, source_vision_frame : VisionFrame, crop_vision_frame : VisionFrame) -> VisionFrame:
641
+ face_swapper = get_inference_pool().get('face_swapper')
642
+ model_type = get_model_options().get('type')
643
+ face_swapper_inputs = {}
644
+
645
+ for face_swapper_input in face_swapper.get_inputs():
646
+ if face_swapper_input.name == 'source':
647
+ if model_type in [ 'blendswap', 'uniface' ]:
648
+ face_swapper_inputs[face_swapper_input.name] = prepare_source_frame(source_face, source_vision_frame)
649
+ else:
650
+ source_embedding = prepare_source_embedding(source_face)
651
+ source_embedding = balance_source_embedding(source_embedding, target_face.embedding)
652
+ face_swapper_inputs[face_swapper_input.name] = source_embedding
653
+ if face_swapper_input.name == 'target':
654
+ face_swapper_inputs[face_swapper_input.name] = crop_vision_frame
655
+
656
+ with conditional_thread_semaphore():
657
+ crop_vision_frame = face_swapper.run(None, face_swapper_inputs)[0][0]
658
+
659
+ return crop_vision_frame
660
+
661
+
662
+ def forward_convert_embedding(face_embedding : Embedding) -> Embedding:
663
+ embedding_converter = get_inference_pool().get('embedding_converter')
664
+
665
+ with conditional_thread_semaphore():
666
+ face_embedding = embedding_converter.run(None,
667
+ {
668
+ 'input': face_embedding
669
+ })[0]
670
+
671
+ return face_embedding
672
+
673
+
674
+ def prepare_source_frame(source_face : Face, source_vision_frame : VisionFrame) -> VisionFrame:
675
+ model_type = get_model_options().get('type')
676
+
677
+ if model_type == 'blendswap':
678
+ source_vision_frame, _ = warp_face_by_face_landmark_5(source_vision_frame, source_face.landmark_set.get('5/68'), 'arcface_112_v2', (112, 112))
679
+
680
+ if model_type == 'uniface':
681
+ source_vision_frame, _ = warp_face_by_face_landmark_5(source_vision_frame, source_face.landmark_set.get('5/68'), 'ffhq_512', (256, 256))
682
+
683
+ source_vision_frame = source_vision_frame[:, :, ::-1] / 255.0
684
+ source_vision_frame = source_vision_frame.transpose(2, 0, 1)
685
+ source_vision_frame = numpy.expand_dims(source_vision_frame, axis = 0).astype(numpy.float32)
686
+ return source_vision_frame
687
+
688
+
689
+ def prepare_source_embedding(source_face : Face) -> Embedding:
690
+ model_type = get_model_options().get('type')
691
+
692
+ if model_type == 'ghost':
693
+ source_embedding = source_face.embedding.reshape(-1, 512)
694
+ source_embedding, _ = convert_source_embedding(source_embedding)
695
+ source_embedding = source_embedding.reshape(1, -1)
696
+ return source_embedding
697
+
698
+ if model_type == 'hyperswap':
699
+ source_embedding = source_face.embedding_norm.reshape((1, -1))
700
+ return source_embedding
701
+
702
+ if model_type == 'inswapper':
703
+ model_path = get_model_options().get('sources').get('face_swapper').get('path')
704
+ model_initializer = get_static_model_initializer(model_path)
705
+ source_embedding = source_face.embedding.reshape((1, -1))
706
+ source_embedding = numpy.dot(source_embedding, model_initializer) / numpy.linalg.norm(source_embedding)
707
+ return source_embedding
708
+
709
+ source_embedding = source_face.embedding.reshape(-1, 512)
710
+ _, source_embedding_norm = convert_source_embedding(source_embedding)
711
+ source_embedding = source_embedding_norm.reshape(1, -1)
712
+ return source_embedding
713
+
714
+
715
+ def balance_source_embedding(source_embedding : Embedding, target_embedding : Embedding) -> Embedding:
716
+ model_type = get_model_options().get('type')
717
+ face_swapper_weight = state_manager.get_item('face_swapper_weight')
718
+ face_swapper_weight = numpy.interp(face_swapper_weight, [ 0, 1 ], [ 0.35, -0.35 ]).astype(numpy.float32)
719
+
720
+ if model_type in [ 'hififace', 'hyperswap', 'inswapper', 'simswap' ]:
721
+ target_embedding = target_embedding / numpy.linalg.norm(target_embedding)
722
+
723
+ source_embedding = source_embedding.reshape(1, -1)
724
+ target_embedding = target_embedding.reshape(1, -1)
725
+ source_embedding = source_embedding * (1 - face_swapper_weight) + target_embedding * face_swapper_weight
726
+ return source_embedding
727
+
728
+
729
+ def convert_source_embedding(source_embedding : Embedding) -> Tuple[Embedding, Embedding]:
730
+ source_embedding = forward_convert_embedding(source_embedding)
731
+ source_embedding = source_embedding.ravel()
732
+ source_embedding_norm = source_embedding / numpy.linalg.norm(source_embedding)
733
+ return source_embedding, source_embedding_norm
734
+
735
+
736
+ def prepare_crop_frame(crop_vision_frame : VisionFrame) -> VisionFrame:
737
+ model_mean = get_model_options().get('mean')
738
+ model_standard_deviation = get_model_options().get('standard_deviation')
739
+
740
+ crop_vision_frame = crop_vision_frame[:, :, ::-1] / 255.0
741
+ crop_vision_frame = (crop_vision_frame - model_mean) / model_standard_deviation
742
+ crop_vision_frame = crop_vision_frame.transpose(2, 0, 1)
743
+ crop_vision_frame = numpy.expand_dims(crop_vision_frame, axis = 0).astype(numpy.float32)
744
+ return crop_vision_frame
745
+
746
+
747
+ def normalize_crop_frame(crop_vision_frame : VisionFrame) -> VisionFrame:
748
+ model_type = get_model_options().get('type')
749
+ model_mean = get_model_options().get('mean')
750
+ model_standard_deviation = get_model_options().get('standard_deviation')
751
+
752
+ crop_vision_frame = crop_vision_frame.transpose(1, 2, 0)
753
+
754
+ if model_type in [ 'ghost', 'hififace', 'hyperswap', 'uniface' ]:
755
+ crop_vision_frame = crop_vision_frame * model_standard_deviation + model_mean
756
+
757
+ crop_vision_frame = crop_vision_frame.clip(0, 1)
758
+ crop_vision_frame = crop_vision_frame[:, :, ::-1] * 255
759
+ return crop_vision_frame
760
+
761
+
762
+ def extract_source_face(source_vision_frames : List[VisionFrame]) -> Optional[Face]:
763
+ source_faces = []
764
+
765
+ if source_vision_frames:
766
+ for source_vision_frame in source_vision_frames:
767
+ temp_faces = get_static_faces([ source_vision_frame ])
768
+ temp_faces = sort_faces_by_order(temp_faces, 'large-small')
769
+
770
+ if temp_faces:
771
+ source_faces.append(get_first(temp_faces))
772
+
773
+ return average_face_identity(source_faces)
774
+
775
+
776
+ def process_frame(inputs : FaceSwapperInputs) -> ProcessorOutputs:
777
+ reference_vision_frame = inputs.get('reference_vision_frame')
778
+ source_vision_frames = inputs.get('source_vision_frames')
779
+ target_vision_frames = inputs.get('target_vision_frames')
780
+ temp_vision_frame = inputs.get('temp_vision_frame')
781
+ temp_vision_mask = inputs.get('temp_vision_mask')
782
+
783
+ target_vision_frame = get_middle(target_vision_frames)
784
+ source_face = extract_source_face(source_vision_frames)
785
+ target_faces = select_faces(reference_vision_frame, source_vision_frames, target_vision_frames)
786
+
787
+ if source_face and target_faces:
788
+ source_vision_frame = get_first(source_vision_frames)
789
+
790
+ for target_face in target_faces:
791
+ target_face = scale_face(target_face, target_vision_frame, temp_vision_frame)
792
+ temp_vision_frame = swap_face(source_face, target_face, source_vision_frame, temp_vision_frame)
793
+
794
+ return temp_vision_frame, temp_vision_mask
processors/modules/face_swapper/locales.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from facefusion.types import Locales
2
+
3
+ LOCALES : Locales =\
4
+ {
5
+ 'en':
6
+ {
7
+ 'help':
8
+ {
9
+ 'model': 'choose the model responsible for swapping the face',
10
+ 'pixel_boost': 'choose the pixel boost resolution for the face swapper',
11
+ 'weight': 'specify the degree of weight applied to the face'
12
+ },
13
+ 'uis':
14
+ {
15
+ 'model_dropdown': 'FACE SWAPPER MODEL',
16
+ 'pixel_boost_dropdown': 'FACE SWAPPER PIXEL BOOST',
17
+ 'weight_slider': 'FACE SWAPPER WEIGHT'
18
+ }
19
+ }
20
+ }
processors/modules/face_swapper/types.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, List, Literal, TypeAlias, TypedDict
2
+
3
+ from facefusion.types import Mask, VisionFrame
4
+
5
+ FaceSwapperInputs = TypedDict('FaceSwapperInputs',
6
+ {
7
+ 'reference_vision_frame' : VisionFrame,
8
+ 'source_vision_frames' : List[VisionFrame],
9
+ 'target_vision_frames' : List[VisionFrame],
10
+ 'temp_vision_frame' : VisionFrame,
11
+ 'temp_vision_mask' : Mask
12
+ })
13
+
14
+ FaceSwapperModel = Literal['blendswap_256', 'ghost_1_256', 'ghost_2_256', 'ghost_3_256', 'hififace_unofficial_256', 'hyperswap_1a_256', 'hyperswap_1b_256', 'hyperswap_1c_256', 'inswapper_128', 'inswapper_128_fp16', 'simswap_256', 'simswap_unofficial_512', 'uniface_256']
15
+
16
+ FaceSwapperWeight : TypeAlias = float
17
+
18
+ FaceSwapperSet : TypeAlias = Dict[FaceSwapperModel, List[str]]