dosesnrolls1 commited on
Commit
1651531
·
verified ·
1 Parent(s): 035449a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -35
app.py CHANGED
@@ -5,6 +5,7 @@ import time
5
  import torch
6
  import shutil
7
  import argparse
 
8
  import onnxruntime
9
  import numpy as np
10
  import gradio as gr
@@ -12,6 +13,7 @@ import concurrent.futures
12
  from tqdm import tqdm
13
  from moviepy.editor import VideoFileClip
14
 
 
15
  import spaces
16
 
17
  from face_swapper import Inswapper, paste_to_whole
@@ -21,13 +23,14 @@ from face_enhancer import get_available_enhancer_names, load_face_enhancer_model
21
  from utils import trim_video, open_directory, split_list_by_lengths, merge_img_sequence_from_ref, create_image_grid
22
 
23
  parser = argparse.ArgumentParser(description="Free Face Swapper")
24
- parser.add_argument("--out_dir", default=os.getcwd())
25
- parser.add_argument("--batch_size", default=32)
26
- parser.add_argument("--cuda", action="store_true", default=False)
27
- parser.add_argument("--colab", action="store_true", default=False)
28
- user_args = parser.parse_args()
29
 
30
  USE_COLAB = user_args.colab
 
31
  DEF_OUTPUT_PATH = user_args.out_dir
32
  BATCH_SIZE = int(user_args.batch_size)
33
 
@@ -35,12 +38,10 @@ WORKSPACE = None
35
  OUTPUT_FILE = None
36
  PREVIEW = None
37
  STREAMER = None
38
-
39
  DETECT_CONDITION = "best detection"
40
  DETECT_SIZE = 640
41
  DETECT_THRESH = 0.6
42
  NUM_OF_SRC_SPECIFIC = 10
43
-
44
  MASK_INCLUDE = ["Skin", "R-Eyebrow", "L-Eyebrow", "L-Eye", "R-Eye", "Nose", "Mouth", "L-Lip", "U-Lip"]
45
  MASK_SOFT_KERNEL = 17
46
  MASK_SOFT_ITERATIONS = 10
@@ -51,13 +52,11 @@ FACE_SWAPPER = None
51
  FACE_ANALYSER = None
52
  FACE_ENHANCER = None
53
  FACE_PARSER = None
54
-
55
  FACE_ENHANCER_LIST = ["NONE"]
56
  FACE_ENHANCER_LIST.extend(get_available_enhancer_names())
57
  FACE_ENHANCER_LIST.extend(cv2_interpolations)
58
 
59
  PROVIDER = ["CPUExecutionProvider"]
60
- USE_CUDA = False
61
  device = "cpu"
62
 
63
  def empty_cache():
@@ -84,17 +83,39 @@ load_face_analyser_model()
84
  load_face_swapper_model()
85
 
86
  @spaces.GPU
87
- def gpu_process(input_type, image_path, video_path, directory_path, source_path, output_path, output_name,
88
- keep_output_sequence, condition, age, distance, face_enhancer_name, enable_face_parser,
89
- mask_includes, mask_soft_kernel, mask_soft_iterations, blur_amount, erode_amount, face_scale,
90
- enable_laplacian_blend, crop_top, crop_bott, crop_left, crop_right, *specifics):
91
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  global WORKSPACE, OUTPUT_FILE, PREVIEW, FACE_ENHANCER, FACE_PARSER
93
-
94
  start_time = time.time()
95
 
96
- def make_status(msg):
97
- return f"### \n {msg}"
 
98
 
99
  includes = mask_regions_to_list(mask_includes)
100
  specifics = list(specifics)
@@ -125,7 +146,7 @@ def gpu_process(input_type, image_path, video_path, directory_path, source_path,
125
  source_data,
126
  swap_condition=condition,
127
  detect_condition=DETECT_CONDITION,
128
- scale=face_scale
129
  )
130
 
131
  preds = []
@@ -146,7 +167,14 @@ def gpu_process(input_type, image_path, video_path, directory_path, source_path,
146
 
147
  if enable_face_parser:
148
  masks = []
149
- for batch_mask in get_parsed_mask(FACE_PARSER, preds, classes=includes, device=device, batch_size=BATCH_SIZE, softness=int(mask_soft_iterations)):
 
 
 
 
 
 
 
150
  masks.append(batch_mask)
151
  empty_cache()
152
  masks = np.concatenate(masks, axis=0) if len(masks) >= 1 else masks
@@ -157,23 +185,27 @@ def gpu_process(input_type, image_path, video_path, directory_path, source_path,
157
  split_matrs = split_list_by_lengths(matrs, num_faces_per_frame)
158
  split_masks = split_list_by_lengths(masks, num_faces_per_frame)
159
 
160
- def post_process(frame_idx, frame_img, split_preds, split_matrs, split_masks, enable_laplacian_blend, crop_mask, blur_amount, erode_amount):
161
  whole_img = cv2.imread(frame_img)
162
  blend_method = "laplacian" if enable_laplacian_blend else "linear"
163
  for p, m, mask in zip(split_preds[frame_idx], split_matrs[frame_idx], split_masks[frame_idx]):
164
  p = cv2.resize(p, (512, 512))
165
  mask = cv2.resize(mask, (512, 512)) if mask is not None else None
166
  m /= 0.25
167
- whole_img = paste_to_whole(p, whole_img, m, mask=mask, crop_mask=crop_mask,
168
- blend_method=blend_method, blur_amount=blur_amount, erode_amount=erode_amount)
 
 
 
 
 
 
 
 
169
  cv2.imwrite(frame_img, whole_img)
170
 
171
  with concurrent.futures.ThreadPoolExecutor() as executor:
172
- futures = [
173
- executor.submit(post_process, idx, frame_img, split_preds, split_matrs, split_masks,
174
- enable_laplacian_blend, crop_mask, blur_amount, erode_amount)
175
- for idx, frame_img in enumerate(image_sequence)
176
- ]
177
  for _ in tqdm(concurrent.futures.as_completed(futures), total=len(futures), desc="Pasting back"):
178
  pass
179
 
@@ -184,7 +216,7 @@ def gpu_process(input_type, image_path, video_path, directory_path, source_path,
184
  OUTPUT_FILE = output_file
185
  WORKSPACE = output_path
186
  PREVIEW = cv2.imread(output_file)[:, :, ::-1]
187
- return f"✔️ Completed in {int((time.time() - start_time) // 60)} min.", gr.update(visible=True, value=PREVIEW), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
188
 
189
  if input_type == "Video":
190
  temp_path = os.path.join(output_path, output_name, "sequence")
@@ -213,7 +245,7 @@ def gpu_process(input_type, image_path, video_path, directory_path, source_path,
213
 
214
  WORKSPACE = output_path
215
  OUTPUT_FILE = output_video_path
216
- return f"✔️ Completed in {int((time.time() - start_time) // 60)} min.", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=True, value=OUTPUT_FILE)
217
 
218
  return "Unsupported input type", gr.update(), gr.update(), gr.update(), gr.update()
219
 
@@ -281,12 +313,35 @@ with gr.Blocks(css=css) as interface:
281
  gen_variable_txt = ",".join([f"src{i+1}" for i in range(NUM_OF_SRC_SPECIFIC)] + [f"trg{i+1}" for i in range(NUM_OF_SRC_SPECIFIC)])
282
  exec(f"src_specific_inputs = ({gen_variable_txt})")
283
 
284
- swap_inputs = [input_type, image_input, video_input, gr.Text(), source_image_input, output_directory, output_name,
285
- keep_output_sequence, swap_option, age, gr.Number(value=0.6), face_enhancer_name, enable_face_parser_mask,
286
- mask_include, mask_soft_kernel, mask_soft_iterations, blur_amount, erode_amount, face_scale,
287
- enable_laplacian_blend, crop_top, crop_bott, crop_left, crop_right, *src_specific_inputs]
288
-
289
- swap_button.click(fn=gpu_process, inputs=swap_inputs, outputs=[info, preview_image, output_directory_button, output_video_button, preview_video], show_progress=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  cancel_button.click(fn=stop_running, inputs=None, outputs=[info])
291
 
292
  if __name__ == "__main__":
 
5
  import torch
6
  import shutil
7
  import argparse
8
+ import subprocess
9
  import onnxruntime
10
  import numpy as np
11
  import gradio as gr
 
13
  from tqdm import tqdm
14
  from moviepy.editor import VideoFileClip
15
 
16
+ # Import spaces only after dependencies are pinned in requirements.txt
17
  import spaces
18
 
19
  from face_swapper import Inswapper, paste_to_whole
 
23
  from utils import trim_video, open_directory, split_list_by_lengths, merge_img_sequence_from_ref, create_image_grid
24
 
25
  parser = argparse.ArgumentParser(description="Free Face Swapper")
26
+ parser.add_argument("--out_dir", help="Default Output directory", default=os.getcwd())
27
+ parser.add_argument("--batch_size", help="Gpu batch size", default=32)
28
+ parser.add_argument("--cuda", action="store_true", help="Enable cuda", default=False)
29
+ parser.add_argument("--colab", action="store_true", help="Enable colab mode", default=False)
30
+ user_args, _ = parser.parse_known_args()
31
 
32
  USE_COLAB = user_args.colab
33
+ USE_CUDA = False
34
  DEF_OUTPUT_PATH = user_args.out_dir
35
  BATCH_SIZE = int(user_args.batch_size)
36
 
 
38
  OUTPUT_FILE = None
39
  PREVIEW = None
40
  STREAMER = None
 
41
  DETECT_CONDITION = "best detection"
42
  DETECT_SIZE = 640
43
  DETECT_THRESH = 0.6
44
  NUM_OF_SRC_SPECIFIC = 10
 
45
  MASK_INCLUDE = ["Skin", "R-Eyebrow", "L-Eyebrow", "L-Eye", "R-Eye", "Nose", "Mouth", "L-Lip", "U-Lip"]
46
  MASK_SOFT_KERNEL = 17
47
  MASK_SOFT_ITERATIONS = 10
 
52
  FACE_ANALYSER = None
53
  FACE_ENHANCER = None
54
  FACE_PARSER = None
 
55
  FACE_ENHANCER_LIST = ["NONE"]
56
  FACE_ENHANCER_LIST.extend(get_available_enhancer_names())
57
  FACE_ENHANCER_LIST.extend(cv2_interpolations)
58
 
59
  PROVIDER = ["CPUExecutionProvider"]
 
60
  device = "cpu"
61
 
62
  def empty_cache():
 
83
  load_face_swapper_model()
84
 
85
  @spaces.GPU
86
+ def process(
87
+ input_type,
88
+ image_path,
89
+ video_path,
90
+ directory_path,
91
+ source_path,
92
+ output_path,
93
+ output_name,
94
+ keep_output_sequence,
95
+ condition,
96
+ age,
97
+ distance,
98
+ face_enhancer_name,
99
+ enable_face_parser,
100
+ mask_includes,
101
+ mask_soft_kernel,
102
+ mask_soft_iterations,
103
+ blur_amount,
104
+ erode_amount,
105
+ face_scale,
106
+ enable_laplacian_blend,
107
+ crop_top,
108
+ crop_bott,
109
+ crop_left,
110
+ crop_right,
111
+ *specifics,
112
+ ):
113
  global WORKSPACE, OUTPUT_FILE, PREVIEW, FACE_ENHANCER, FACE_PARSER
 
114
  start_time = time.time()
115
 
116
+ def finish_text():
117
+ mins, secs = divmod(time.time() - start_time, 60)
118
+ return f"✔️ Completed in {int(mins)} min {int(secs)} sec."
119
 
120
  includes = mask_regions_to_list(mask_includes)
121
  specifics = list(specifics)
 
146
  source_data,
147
  swap_condition=condition,
148
  detect_condition=DETECT_CONDITION,
149
+ scale=face_scale,
150
  )
151
 
152
  preds = []
 
167
 
168
  if enable_face_parser:
169
  masks = []
170
+ for batch_mask in get_parsed_mask(
171
+ FACE_PARSER,
172
+ preds,
173
+ classes=includes,
174
+ device=device,
175
+ batch_size=BATCH_SIZE,
176
+ softness=int(mask_soft_iterations),
177
+ ):
178
  masks.append(batch_mask)
179
  empty_cache()
180
  masks = np.concatenate(masks, axis=0) if len(masks) >= 1 else masks
 
185
  split_matrs = split_list_by_lengths(matrs, num_faces_per_frame)
186
  split_masks = split_list_by_lengths(masks, num_faces_per_frame)
187
 
188
+ def post_process(frame_idx, frame_img):
189
  whole_img = cv2.imread(frame_img)
190
  blend_method = "laplacian" if enable_laplacian_blend else "linear"
191
  for p, m, mask in zip(split_preds[frame_idx], split_matrs[frame_idx], split_masks[frame_idx]):
192
  p = cv2.resize(p, (512, 512))
193
  mask = cv2.resize(mask, (512, 512)) if mask is not None else None
194
  m /= 0.25
195
+ whole_img = paste_to_whole(
196
+ p,
197
+ whole_img,
198
+ m,
199
+ mask=mask,
200
+ crop_mask=crop_mask,
201
+ blend_method=blend_method,
202
+ blur_amount=blur_amount,
203
+ erode_amount=erode_amount,
204
+ )
205
  cv2.imwrite(frame_img, whole_img)
206
 
207
  with concurrent.futures.ThreadPoolExecutor() as executor:
208
+ futures = [executor.submit(post_process, idx, frame_img) for idx, frame_img in enumerate(image_sequence)]
 
 
 
 
209
  for _ in tqdm(concurrent.futures.as_completed(futures), total=len(futures), desc="Pasting back"):
210
  pass
211
 
 
216
  OUTPUT_FILE = output_file
217
  WORKSPACE = output_path
218
  PREVIEW = cv2.imread(output_file)[:, :, ::-1]
219
+ return finish_text(), gr.update(visible=True, value=PREVIEW), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
220
 
221
  if input_type == "Video":
222
  temp_path = os.path.join(output_path, output_name, "sequence")
 
245
 
246
  WORKSPACE = output_path
247
  OUTPUT_FILE = output_video_path
248
+ return finish_text(), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=True, value=OUTPUT_FILE)
249
 
250
  return "Unsupported input type", gr.update(), gr.update(), gr.update(), gr.update()
251
 
 
313
  gen_variable_txt = ",".join([f"src{i+1}" for i in range(NUM_OF_SRC_SPECIFIC)] + [f"trg{i+1}" for i in range(NUM_OF_SRC_SPECIFIC)])
314
  exec(f"src_specific_inputs = ({gen_variable_txt})")
315
 
316
+ swap_inputs = [
317
+ input_type,
318
+ image_input,
319
+ video_input,
320
+ gr.Text(),
321
+ source_image_input,
322
+ output_directory,
323
+ output_name,
324
+ keep_output_sequence,
325
+ swap_option,
326
+ age,
327
+ gr.Number(value=0.6),
328
+ face_enhancer_name,
329
+ enable_face_parser_mask,
330
+ mask_include,
331
+ mask_soft_kernel,
332
+ mask_soft_iterations,
333
+ blur_amount,
334
+ erode_amount,
335
+ face_scale,
336
+ enable_laplacian_blend,
337
+ crop_top,
338
+ crop_bott,
339
+ crop_left,
340
+ crop_right,
341
+ *src_specific_inputs,
342
+ ]
343
+
344
+ swap_button.click(fn=process, inputs=swap_inputs, outputs=[info, preview_image, output_directory_button, output_video_button, preview_video], show_progress=True)
345
  cancel_button.click(fn=stop_running, inputs=None, outputs=[info])
346
 
347
  if __name__ == "__main__":