andro1241 commited on
Commit
b70008a
·
verified ·
1 Parent(s): 9b63fda

Upload 4 files

Browse files
processors/modules/background_remover/choices.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from typing import List, Sequence, get_args
2
+
3
+ from facefusion.common_helper import create_int_range
4
+ from facefusion.processors.modules.background_remover.types import BackgroundRemoverModel
5
+
6
+ background_remover_models : List[BackgroundRemoverModel] = list(get_args(BackgroundRemoverModel))
7
+
8
+ background_remover_color_range : Sequence[int] = create_int_range(0, 255, 1)
processors/modules/background_remover/core.py ADDED
@@ -0,0 +1,661 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from argparse import ArgumentParser
2
+ from functools import lru_cache, partial
3
+ from types import ModuleType
4
+ from typing import List, 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, inference_manager, logger, state_manager, translator, video_manager
13
+ from facefusion.common_helper import is_macos, is_windows
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.filesystem import in_directory, is_image, is_video, resolve_relative_path, same_file_extension
17
+ from facefusion.normalizer import normalize_color
18
+ from facefusion.processors.modules.background_remover import choices as background_remover_choices
19
+ from facefusion.processors.modules.background_remover.types import BackgroundRemoverInputs
20
+ from facefusion.processors.types import ProcessorOutputs
21
+ from facefusion.program_helper import find_argument_group
22
+ from facefusion.sanitizer import sanitize_int_range
23
+ from facefusion.thread_helper import thread_semaphore
24
+ from facefusion.types import ApplyStateItem, Args, DownloadScope, InferencePool, InferenceProvider, Mask, ModelOptions, ModelSet, ProcessMode, VisionFrame
25
+ from facefusion.vision import read_static_image, read_static_video_frame
26
+
27
+
28
+ @lru_cache()
29
+ def create_static_model_set(download_scope : DownloadScope) -> ModelSet:
30
+ return\
31
+ {
32
+ 'ben_2':
33
+ {
34
+ '__metadata__':
35
+ {
36
+ 'vendor': 'PramaLLC',
37
+ 'license': 'MIT',
38
+ 'year': 2025
39
+ },
40
+ 'hashes':
41
+ {
42
+ 'background_remover':
43
+ {
44
+ 'url': resolve_download_url('models-3.5.0', 'ben_2.hash'),
45
+ 'path': resolve_relative_path('../.assets/models/ben_2.hash')
46
+ }
47
+ },
48
+ 'sources':
49
+ {
50
+ 'background_remover':
51
+ {
52
+ 'url': resolve_download_url('models-3.5.0', 'ben_2.onnx'),
53
+ 'path': resolve_relative_path('../.assets/models/ben_2.onnx')
54
+ }
55
+ },
56
+ 'type': 'ben',
57
+ 'size': (1024, 1024),
58
+ 'mean': [ 0.0, 0.0, 0.0 ],
59
+ 'standard_deviation': [ 1.0, 1.0, 1.0 ]
60
+ },
61
+ 'birefnet_general':
62
+ {
63
+ '__metadata__':
64
+ {
65
+ 'vendor': 'ZhengPeng7',
66
+ 'license': 'MIT',
67
+ 'year': 2024
68
+ },
69
+ 'hashes':
70
+ {
71
+ 'background_remover':
72
+ {
73
+ 'url': resolve_download_url('models-3.5.0', 'birefnet_general.hash'),
74
+ 'path': resolve_relative_path('../.assets/models/birefnet_general.hash')
75
+ }
76
+ },
77
+ 'sources':
78
+ {
79
+ 'background_remover':
80
+ {
81
+ 'url': resolve_download_url('models-3.5.0', 'birefnet_general.onnx'),
82
+ 'path': resolve_relative_path('../.assets/models/birefnet_general.onnx')
83
+ }
84
+ },
85
+ 'type': 'birefnet',
86
+ 'size': (1024, 1024),
87
+ 'mean': [ 0.0, 0.0, 0.0 ],
88
+ 'standard_deviation': [ 1.0, 1.0, 1.0 ]
89
+ },
90
+ 'birefnet_portrait':
91
+ {
92
+ '__metadata__':
93
+ {
94
+ 'vendor': 'ZhengPeng7',
95
+ 'license': 'MIT',
96
+ 'year': 2024
97
+ },
98
+ 'hashes':
99
+ {
100
+ 'background_remover':
101
+ {
102
+ 'url': resolve_download_url('models-3.5.0', 'birefnet_portrait.hash'),
103
+ 'path': resolve_relative_path('../.assets/models/birefnet_portrait.hash')
104
+ }
105
+ },
106
+ 'sources':
107
+ {
108
+ 'background_remover':
109
+ {
110
+ 'url': resolve_download_url('models-3.5.0', 'birefnet_portrait.onnx'),
111
+ 'path': resolve_relative_path('../.assets/models/birefnet_portrait.onnx')
112
+ }
113
+ },
114
+ 'type': 'birefnet',
115
+ 'size': (1024, 1024),
116
+ 'mean': [ 0.0, 0.0, 0.0 ],
117
+ 'standard_deviation': [ 1.0, 1.0, 1.0 ]
118
+ },
119
+ 'corridor_key_1024':
120
+ {
121
+ '__metadata__':
122
+ {
123
+ 'vendor': 'nikopueringer',
124
+ 'license': 'Non-Commercial',
125
+ 'year': 2025
126
+ },
127
+ 'hashes':
128
+ {
129
+ 'background_remover':
130
+ {
131
+ 'url': resolve_download_url('models-3.6.0', 'corridor_key_1024.hash'),
132
+ 'path': resolve_relative_path('../.assets/models/corridor_key_1024.hash')
133
+ }
134
+ },
135
+ 'sources':
136
+ {
137
+ 'background_remover':
138
+ {
139
+ 'url': resolve_download_url('models-3.6.0', 'corridor_key_1024.onnx'),
140
+ 'path': resolve_relative_path('../.assets/models/corridor_key_1024.onnx')
141
+ }
142
+ },
143
+ 'type': 'corridor_key',
144
+ 'size': (1024, 1024),
145
+ 'mean': [ 0.485, 0.456, 0.406 ],
146
+ 'standard_deviation': [ 0.229, 0.224, 0.225 ]
147
+ },
148
+ 'corridor_key_2048':
149
+ {
150
+ '__metadata__':
151
+ {
152
+ 'vendor': 'nikopueringer',
153
+ 'license': 'Non-Commercial',
154
+ 'year': 2025
155
+ },
156
+ 'hashes':
157
+ {
158
+ 'background_remover':
159
+ {
160
+ 'url': resolve_download_url('models-3.6.0', 'corridor_key_2048.hash'),
161
+ 'path': resolve_relative_path('../.assets/models/corridor_key_2048.hash')
162
+ }
163
+ },
164
+ 'sources':
165
+ {
166
+ 'background_remover':
167
+ {
168
+ 'url': resolve_download_url('models-3.6.0', 'corridor_key_2048.onnx'),
169
+ 'path': resolve_relative_path('../.assets/models/corridor_key_2048.onnx')
170
+ }
171
+ },
172
+ 'type': 'corridor_key',
173
+ 'size': (2048, 2048),
174
+ 'mean': [ 0.485, 0.456, 0.406 ],
175
+ 'standard_deviation': [ 0.229, 0.224, 0.225 ]
176
+ },
177
+ 'isnet_general':
178
+ {
179
+ '__metadata__':
180
+ {
181
+ 'vendor': 'xuebinqin',
182
+ 'license': 'Apache-2.0',
183
+ 'year': 2022
184
+ },
185
+ 'hashes':
186
+ {
187
+ 'background_remover':
188
+ {
189
+ 'url': resolve_download_url('models-3.5.0', 'isnet_general.hash'),
190
+ 'path': resolve_relative_path('../.assets/models/isnet_general.hash')
191
+ }
192
+ },
193
+ 'sources':
194
+ {
195
+ 'background_remover':
196
+ {
197
+ 'url': resolve_download_url('models-3.5.0', 'isnet_general.onnx'),
198
+ 'path': resolve_relative_path('../.assets/models/isnet_general.onnx')
199
+ }
200
+ },
201
+ 'type': 'isnet',
202
+ 'size': (1024, 1024),
203
+ 'mean': [ 0.5, 0.5, 0.5 ],
204
+ 'standard_deviation': [ 1.0, 1.0, 1.0 ]
205
+ },
206
+ 'modnet':
207
+ {
208
+ '__metadata__':
209
+ {
210
+ 'vendor': 'ZHKKKe',
211
+ 'license': 'Apache-2.0',
212
+ 'year': 2020
213
+ },
214
+ 'hashes':
215
+ {
216
+ 'background_remover':
217
+ {
218
+ 'url': resolve_download_url('models-3.5.0', 'modnet.hash'),
219
+ 'path': resolve_relative_path('../.assets/models/modnet.hash')
220
+ }
221
+ },
222
+ 'sources':
223
+ {
224
+ 'background_remover':
225
+ {
226
+ 'url': resolve_download_url('models-3.5.0', 'modnet.onnx'),
227
+ 'path': resolve_relative_path('../.assets/models/modnet.onnx')
228
+ }
229
+ },
230
+ 'type': 'modnet',
231
+ 'size': (512, 512),
232
+ 'mean': [ 0.5, 0.5, 0.5 ],
233
+ 'standard_deviation': [ 0.5, 0.5, 0.5 ]
234
+ },
235
+ 'ormbg':
236
+ {
237
+ '__metadata__':
238
+ {
239
+ 'vendor': 'schirrmacher',
240
+ 'license': 'Apache-2.0',
241
+ 'year': 2024
242
+ },
243
+ 'hashes':
244
+ {
245
+ 'background_remover':
246
+ {
247
+ 'url': resolve_download_url('models-3.5.0', 'ormbg.hash'),
248
+ 'path': resolve_relative_path('../.assets/models/ormbg.hash')
249
+ }
250
+ },
251
+ 'sources':
252
+ {
253
+ 'background_remover':
254
+ {
255
+ 'url': resolve_download_url('models-3.5.0', 'ormbg.onnx'),
256
+ 'path': resolve_relative_path('../.assets/models/ormbg.onnx')
257
+ }
258
+ },
259
+ 'type': 'ormbg',
260
+ 'size': (1024, 1024),
261
+ 'mean': [ 0.0, 0.0, 0.0 ],
262
+ 'standard_deviation': [ 1.0, 1.0, 1.0 ]
263
+ },
264
+ 'rmbg_1.4':
265
+ {
266
+ '__metadata__':
267
+ {
268
+ 'vendor': 'Bria',
269
+ 'license': 'Non-Commercial',
270
+ 'year': 2023
271
+ },
272
+ 'hashes':
273
+ {
274
+ 'background_remover':
275
+ {
276
+ 'url': resolve_download_url('models-3.5.0', 'rmbg_1.4.hash'),
277
+ 'path': resolve_relative_path('../.assets/models/rmbg_1.4.hash')
278
+ }
279
+ },
280
+ 'sources':
281
+ {
282
+ 'background_remover':
283
+ {
284
+ 'url': resolve_download_url('models-3.5.0', 'rmbg_1.4.onnx'),
285
+ 'path': resolve_relative_path('../.assets/models/rmbg_1.4.onnx')
286
+ }
287
+ },
288
+ 'type': 'rmbg',
289
+ 'size': (1024, 1024),
290
+ 'mean': [ 0.5, 0.5, 0.5 ],
291
+ 'standard_deviation': [ 1.0, 1.0, 1.0 ]
292
+ },
293
+ 'rmbg_2.0':
294
+ {
295
+ '__metadata__':
296
+ {
297
+ 'vendor': 'Bria',
298
+ 'license': 'Non-Commercial',
299
+ 'year': 2024
300
+ },
301
+ 'hashes':
302
+ {
303
+ 'background_remover':
304
+ {
305
+ 'url': resolve_download_url('models-3.5.0', 'rmbg_2.0.hash'),
306
+ 'path': resolve_relative_path('../.assets/models/rmbg_2.0.hash')
307
+ }
308
+ },
309
+ 'sources':
310
+ {
311
+ 'background_remover':
312
+ {
313
+ 'url': resolve_download_url('models-3.5.0', 'rmbg_2.0.onnx'),
314
+ 'path': resolve_relative_path('../.assets/models/rmbg_2.0.onnx')
315
+ }
316
+ },
317
+ 'type': 'rmbg',
318
+ 'size': (1024, 1024),
319
+ 'mean': [ 0.485, 0.456, 0.406 ],
320
+ 'standard_deviation': [ 0.229, 0.224, 0.225 ]
321
+ },
322
+ 'silueta':
323
+ {
324
+ '__metadata__':
325
+ {
326
+ 'vendor': 'Kikedao',
327
+ 'license': 'Apache-2.0',
328
+ 'year': 2022
329
+ },
330
+ 'hashes':
331
+ {
332
+ 'background_remover':
333
+ {
334
+ 'url': resolve_download_url('models-3.5.0', 'silueta.hash'),
335
+ 'path': resolve_relative_path('../.assets/models/silueta.hash')
336
+ }
337
+ },
338
+ 'sources':
339
+ {
340
+ 'background_remover':
341
+ {
342
+ 'url': resolve_download_url('models-3.5.0', 'silueta.onnx'),
343
+ 'path': resolve_relative_path('../.assets/models/silueta.onnx')
344
+ }
345
+ },
346
+ 'type': 'silueta',
347
+ 'size': (320, 320),
348
+ 'mean': [ 0.485, 0.456, 0.406 ],
349
+ 'standard_deviation': [ 0.229, 0.224, 0.225 ]
350
+ },
351
+ 'u2net_cloth':
352
+ {
353
+ '__metadata__':
354
+ {
355
+ 'vendor': 'levindabhi',
356
+ 'license': 'MIT',
357
+ 'year': 2021
358
+ },
359
+ 'hashes':
360
+ {
361
+ 'background_remover':
362
+ {
363
+ 'url': resolve_download_url('models-3.5.0', 'u2net_cloth.hash'),
364
+ 'path': resolve_relative_path('../.assets/models/u2net_cloth.hash')
365
+ }
366
+ },
367
+ 'sources':
368
+ {
369
+ 'background_remover':
370
+ {
371
+ 'url': resolve_download_url('models-3.5.0', 'u2net_cloth.onnx'),
372
+ 'path': resolve_relative_path('../.assets/models/u2net_cloth.onnx')
373
+ }
374
+ },
375
+ 'type': 'u2net_cloth',
376
+ 'size': (768, 768),
377
+ 'mean': [ 0.485, 0.456, 0.406 ],
378
+ 'standard_deviation': [ 0.229, 0.224, 0.225 ]
379
+ },
380
+ 'u2net_general':
381
+ {
382
+ '__metadata__':
383
+ {
384
+ 'vendor': 'xuebinqin',
385
+ 'license': 'Apache-2.0',
386
+ 'year': 2020
387
+ },
388
+ 'hashes':
389
+ {
390
+ 'background_remover':
391
+ {
392
+ 'url': resolve_download_url('models-3.5.0', 'u2net_general.hash'),
393
+ 'path': resolve_relative_path('../.assets/models/u2net_general.hash')
394
+ }
395
+ },
396
+ 'sources':
397
+ {
398
+ 'background_remover':
399
+ {
400
+ 'url': resolve_download_url('models-3.5.0', 'u2net_general.onnx'),
401
+ 'path': resolve_relative_path('../.assets/models/u2net_general.onnx')
402
+ }
403
+ },
404
+ 'type': 'u2net',
405
+ 'size': (320, 320),
406
+ 'mean': [ 0.485, 0.456, 0.406 ],
407
+ 'standard_deviation': [ 0.229, 0.224, 0.225 ]
408
+ },
409
+ 'u2net_human':
410
+ {
411
+ '__metadata__':
412
+ {
413
+ 'vendor': 'xuebinqin',
414
+ 'license': 'Apache-2.0',
415
+ 'year': 2021
416
+ },
417
+ 'hashes':
418
+ {
419
+ 'background_remover':
420
+ {
421
+ 'url': resolve_download_url('models-3.5.0', 'u2net_human.hash'),
422
+ 'path': resolve_relative_path('../.assets/models/u2net_human.hash')
423
+ }
424
+ },
425
+ 'sources':
426
+ {
427
+ 'background_remover':
428
+ {
429
+ 'url': resolve_download_url('models-3.5.0', 'u2net_human.onnx'),
430
+ 'path': resolve_relative_path('../.assets/models/u2net_human.onnx')
431
+ }
432
+ },
433
+ 'type': 'u2net',
434
+ 'size': (320, 320),
435
+ 'mean': [ 0.485, 0.456, 0.406 ],
436
+ 'standard_deviation': [ 0.229, 0.224, 0.225 ]
437
+ },
438
+ 'u2netp':
439
+ {
440
+ '__metadata__':
441
+ {
442
+ 'vendor': 'xuebinqin',
443
+ 'license': 'Apache-2.0',
444
+ 'year': 2021
445
+ },
446
+ 'hashes':
447
+ {
448
+ 'background_remover':
449
+ {
450
+ 'url': resolve_download_url('models-3.5.0', 'u2netp.hash'),
451
+ 'path': resolve_relative_path('../.assets/models/u2netp.hash')
452
+ }
453
+ },
454
+ 'sources':
455
+ {
456
+ 'background_remover':
457
+ {
458
+ 'url': resolve_download_url('models-3.5.0', 'u2netp.onnx'),
459
+ 'path': resolve_relative_path('../.assets/models/u2netp.onnx')
460
+ }
461
+ },
462
+ 'type': 'u2netp',
463
+ 'size': (320, 320),
464
+ 'mean': [ 0.485, 0.456, 0.406 ],
465
+ 'standard_deviation': [ 0.229, 0.224, 0.225 ]
466
+ }
467
+ }
468
+
469
+
470
+ def get_inference_pool() -> InferencePool:
471
+ model_names = [ state_manager.get_item('background_remover_model') ]
472
+ model_source_set = get_model_options().get('sources')
473
+
474
+ return inference_manager.get_inference_pool(__name__, model_names, model_source_set)
475
+
476
+
477
+ def clear_inference_pool() -> None:
478
+ model_names = [ state_manager.get_item('background_remover_model') ]
479
+ inference_manager.clear_inference_pool(__name__, model_names)
480
+
481
+
482
+ def override_inference_providers() -> List[InferenceProvider]:
483
+ model_type = get_model_options().get('type')
484
+
485
+ if is_macos() and has_execution_provider('coreml') or is_windows() and has_execution_provider('directml') and model_type == 'corridor_key':
486
+ return [ facefusion.choices.execution_provider_set.get('cpu') ]
487
+
488
+ return []
489
+
490
+
491
+ def get_model_options() -> ModelOptions:
492
+ model_name = state_manager.get_item('background_remover_model')
493
+ return create_static_model_set('full').get(model_name)
494
+
495
+
496
+ def register_args(program : ArgumentParser) -> None:
497
+ group_processors = find_argument_group(program, 'processors')
498
+ if group_processors:
499
+ group_processors.add_argument('--background-remover-model', help = translator.get('help.model', __package__), default = config.get_str_value('processors', 'background_remover_model', 'modnet'), choices = background_remover_choices.background_remover_models)
500
+ group_processors.add_argument('--background-remover-fill-color', help = translator.get('help.fill_color', __package__), type = partial(sanitize_int_range, int_range = background_remover_choices.background_remover_color_range), default = config.get_int_list('processors', 'background_remover_fill_color', '0 0 0 0'), nargs = '+')
501
+ group_processors.add_argument('--background-remover-despill-color', help = translator.get('help.despill_color', __package__), type = partial(sanitize_int_range, int_range = background_remover_choices.background_remover_color_range), default = config.get_int_list('processors', 'background_remover_despill_color', '0 0 0 0'), nargs = '+')
502
+ facefusion.jobs.job_store.register_step_keys([ 'background_remover_model', 'background_remover_fill_color', 'background_remover_despill_color' ])
503
+
504
+
505
+ def apply_args(args : Args, apply_state_item : ApplyStateItem) -> None:
506
+ apply_state_item('background_remover_model', args.get('background_remover_model'))
507
+ apply_state_item('background_remover_fill_color', normalize_color(args.get('background_remover_fill_color')))
508
+ apply_state_item('background_remover_despill_color', normalize_color(args.get('background_remover_despill_color')))
509
+
510
+
511
+ def get_common_modules() -> List[ModuleType]:
512
+ return [ content_analyser ]
513
+
514
+
515
+ def pre_check() -> bool:
516
+ model_hash_set = get_model_options().get('hashes')
517
+ model_source_set = get_model_options().get('sources')
518
+
519
+ for common_module in get_common_modules():
520
+ if not common_module.pre_check():
521
+ return False
522
+
523
+ return conditional_download_hashes(model_hash_set) and conditional_download_sources(model_source_set)
524
+
525
+
526
+ def pre_process(mode : ProcessMode) -> bool:
527
+ 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')):
528
+ logger.error(translator.get('choose_image_or_video_target') + translator.get('exclamation_mark'), __name__)
529
+ return False
530
+ if mode == 'output' and not in_directory(state_manager.get_item('output_path')):
531
+ logger.error(translator.get('specify_image_or_video_output') + translator.get('exclamation_mark'), __name__)
532
+ return False
533
+ if mode == 'output' and not same_file_extension(state_manager.get_item('target_path'), state_manager.get_item('output_path')):
534
+ logger.error(translator.get('match_target_and_output_extension') + translator.get('exclamation_mark'), __name__)
535
+ return False
536
+ return True
537
+
538
+
539
+ def post_process() -> None:
540
+ read_static_image.cache_clear()
541
+ read_static_video_frame.cache_clear()
542
+ video_manager.clear_video_pool()
543
+
544
+ if state_manager.get_item('video_memory_strategy') in [ 'strict', 'moderate' ]:
545
+ clear_inference_pool()
546
+
547
+ if state_manager.get_item('video_memory_strategy') == 'strict':
548
+ for common_module in get_common_modules():
549
+ common_module.clear_inference_pool()
550
+
551
+
552
+ def remove_background(temp_vision_frame : VisionFrame) -> Tuple[VisionFrame, Mask]:
553
+ model_type = get_model_options().get('type')
554
+
555
+ if model_type == 'corridor_key':
556
+ remove_vision_mask, remove_vision_frame = forward_corridor_key(prepare_temp_frame(temp_vision_frame))
557
+ remove_vision_frame = numpy.squeeze(remove_vision_frame).transpose(1, 2, 0)
558
+ remove_vision_frame = numpy.clip(remove_vision_frame * 255, 0, 255).astype(numpy.uint8)
559
+ temp_vision_frame = cv2.resize(remove_vision_frame[:, :, ::-1], temp_vision_frame.shape[:2][::-1])
560
+ else:
561
+ remove_vision_mask = forward(prepare_temp_frame(temp_vision_frame))
562
+
563
+ remove_vision_mask = normalize_vision_mask(remove_vision_mask)
564
+ remove_vision_mask = cv2.resize(remove_vision_mask, temp_vision_frame.shape[:2][::-1])
565
+ temp_vision_frame = apply_despill_color(temp_vision_frame)
566
+ temp_vision_frame = apply_fill_color(temp_vision_frame, remove_vision_mask)
567
+ return temp_vision_frame, remove_vision_mask
568
+
569
+
570
+ def forward(temp_vision_frame : VisionFrame) -> VisionFrame:
571
+ background_remover = get_inference_pool().get('background_remover')
572
+ model_type = get_model_options().get('type')
573
+
574
+ with thread_semaphore():
575
+ remove_vision_frame = background_remover.run(None,
576
+ {
577
+ 'input': temp_vision_frame
578
+ })[0]
579
+
580
+ if model_type == 'u2net_cloth':
581
+ remove_vision_frame = numpy.argmax(remove_vision_frame, axis = 1)
582
+
583
+ return remove_vision_frame
584
+
585
+
586
+ def forward_corridor_key(temp_vision_frame : VisionFrame) -> Tuple[Mask, VisionFrame]:
587
+ background_remover = get_inference_pool().get('background_remover')
588
+
589
+ with thread_semaphore():
590
+ remove_vision_mask, remove_vision_frame = background_remover.run(None,
591
+ {
592
+ 'input': temp_vision_frame
593
+ })
594
+
595
+ return remove_vision_mask, remove_vision_frame
596
+
597
+
598
+ def prepare_temp_frame(temp_vision_frame : VisionFrame) -> VisionFrame:
599
+ model_type = get_model_options().get('type')
600
+ model_size = get_model_options().get('size')
601
+ model_mean = get_model_options().get('mean')
602
+ model_standard_deviation = get_model_options().get('standard_deviation')
603
+
604
+ if model_type == 'corridor_key':
605
+ coarse_color = temp_vision_frame[:, :, ::-1].astype(numpy.float32) / 255.0
606
+ coarse_bias = coarse_color[:, :, 1] - numpy.maximum(coarse_color[:, :, 0], coarse_color[:, :, 2])
607
+ coarse_vision_mask = cv2.resize(1.0 - numpy.clip(coarse_bias * 2.0, 0, 1), model_size)[:, :, numpy.newaxis]
608
+
609
+ temp_vision_frame = cv2.resize(temp_vision_frame, model_size)
610
+ temp_vision_frame = temp_vision_frame[:, :, ::-1] / 255.0
611
+ temp_vision_frame = (temp_vision_frame - model_mean) / model_standard_deviation
612
+
613
+ if model_type == 'corridor_key':
614
+ temp_vision_frame = numpy.concatenate([ temp_vision_frame, coarse_vision_mask ], axis = 2)
615
+
616
+ temp_vision_frame = temp_vision_frame.transpose(2, 0, 1)
617
+ temp_vision_frame = numpy.expand_dims(temp_vision_frame, axis = 0).astype(numpy.float32)
618
+ return temp_vision_frame
619
+
620
+
621
+ def normalize_vision_mask(temp_vision_mask : Mask) -> Mask:
622
+ temp_vision_mask = numpy.squeeze(temp_vision_mask).clip(0, 1) * 255
623
+ temp_vision_mask = numpy.clip(temp_vision_mask, 0, 255).astype(numpy.uint8)
624
+ return temp_vision_mask
625
+
626
+
627
+ def apply_fill_color(temp_vision_frame : VisionFrame, temp_vision_mask : Mask) -> VisionFrame:
628
+ background_remover_fill_color = state_manager.get_item('background_remover_fill_color')
629
+ temp_vision_mask = temp_vision_mask.astype(numpy.float32) / 255
630
+ temp_vision_mask = numpy.expand_dims(temp_vision_mask, axis = 2)
631
+ temp_vision_mask = (1 - temp_vision_mask) * background_remover_fill_color[-1] / 255
632
+ fill_vision_frame = numpy.zeros_like(temp_vision_frame)
633
+ fill_vision_frame[:, :, 0] = background_remover_fill_color[2]
634
+ fill_vision_frame[:, :, 1] = background_remover_fill_color[1]
635
+ fill_vision_frame[:, :, 2] = background_remover_fill_color[0]
636
+ temp_vision_frame = temp_vision_frame * (1 - temp_vision_mask) + fill_vision_frame * temp_vision_mask
637
+ temp_vision_frame = temp_vision_frame.astype(numpy.uint8)
638
+ return temp_vision_frame
639
+
640
+
641
+ def apply_despill_color(temp_vision_frame : VisionFrame) -> VisionFrame:
642
+ background_remover_despill_color = state_manager.get_item('background_remover_despill_color')
643
+ temp_vision_frame = temp_vision_frame.astype(numpy.float32)
644
+ color_alpha = background_remover_despill_color[3] / 255.0
645
+ despill_vision_frame = numpy.zeros_like(temp_vision_frame)
646
+ despill_vision_frame[:, :, 0] = background_remover_despill_color[2]
647
+ despill_vision_frame[:, :, 1] = background_remover_despill_color[1]
648
+ despill_vision_frame[:, :, 2] = background_remover_despill_color[0]
649
+ color_weight = despill_vision_frame / numpy.maximum(numpy.max(background_remover_despill_color[:3]), 1)
650
+ color_limit = numpy.roll(temp_vision_frame, 1, 2) + numpy.roll(temp_vision_frame, -1, 2)
651
+ limit_vision_frame = numpy.minimum(temp_vision_frame, color_limit * 0.5)
652
+ temp_vision_frame = temp_vision_frame + (limit_vision_frame - temp_vision_frame) * color_alpha * color_weight
653
+ temp_vision_frame = temp_vision_frame.astype(numpy.uint8)
654
+ return temp_vision_frame
655
+
656
+
657
+ def process_frame(inputs : BackgroundRemoverInputs) -> ProcessorOutputs:
658
+ temp_vision_frame = inputs.get('temp_vision_frame')
659
+ temp_vision_frame, temp_vision_mask = remove_background(temp_vision_frame)
660
+ temp_vision_mask = numpy.minimum.reduce([ temp_vision_mask, inputs.get('temp_vision_mask') ])
661
+ return temp_vision_frame, temp_vision_mask
processors/modules/background_remover/locales.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from facefusion.types import Locales
2
+
3
+ LOCALES : Locales =\
4
+ {
5
+ 'en':
6
+ {
7
+ 'help':
8
+ {
9
+ 'model': 'choose the model responsible for removing the background',
10
+ 'fill_color': 'apply red, green, blue and alpha values to the background',
11
+ 'despill_color': 'remove red, green, blue and alpha values from the foreground'
12
+ },
13
+ 'uis':
14
+ {
15
+ 'model_dropdown': 'BACKGROUND REMOVER MODEL',
16
+ 'fill_color_red_number': 'FILL COLOR RED',
17
+ 'fill_color_green_number': 'FILL COLOR GREEN',
18
+ 'fill_color_blue_number': 'FILL COLOR BLUE',
19
+ 'fill_color_alpha_number': 'FILL COLOR ALPHA',
20
+ 'despill_color_red_number': 'DESPILL COLOR RED',
21
+ 'despill_color_green_number': 'DESPILL COLOR GREEN',
22
+ 'despill_color_blue_number': 'DESPILL COLOR BLUE',
23
+ 'despill_color_alpha_number': 'DESPILL COLOR ALPHA'
24
+ }
25
+ }
26
+ }
processors/modules/background_remover/types.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List, Literal, TypedDict
2
+
3
+ from facefusion.types import Mask, VisionFrame
4
+
5
+ BackgroundRemoverInputs = TypedDict('BackgroundRemoverInputs',
6
+ {
7
+ 'target_vision_frames' : List[VisionFrame],
8
+ 'temp_vision_frame' : VisionFrame,
9
+ 'temp_vision_mask' : Mask
10
+ })
11
+
12
+ BackgroundRemoverModel = Literal['ben_2', 'birefnet_general', 'birefnet_portrait', 'corridor_key_1024', 'corridor_key_2048', 'isnet_general', 'modnet', 'ormbg', 'rmbg_1.4', 'rmbg_2.0', 'silueta', 'u2net_cloth', 'u2net_general', 'u2net_human', 'u2netp']