Artysgor commited on
Commit
37923f7
โ€ข
1 Parent(s): 05f63d8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -469
app.py CHANGED
@@ -17,6 +17,8 @@ import queue
17
  from tqdm import tqdm
18
  import concurrent.futures
19
  from moviepy.editor import VideoFileClip
 
 
20
 
21
  from face_swapper import Inswapper, paste_to_whole
22
  from face_analyser import detect_conditions, get_analysed_data, swap_options_list
@@ -183,27 +185,19 @@ def process(
183
 
184
  start_time = time.time()
185
  total_exec_time = lambda start_time: divmod(time.time() - start_time, 60)
186
- get_finsh_text = lambda start_time: f"โœ”๏ธ Completed in {int(total_exec_time(start_time)[0])} min {int(total_exec_time(start_time)[1])} sec."
187
 
188
  ## ------------------------------ PREPARE INPUTS & LOAD MODELS ------------------------------
189
 
190
-
191
-
192
- yield "### \n ๐Ÿ’Š Loading face analyser model...", *ui_before()
193
  load_face_analyser_model()
194
-
195
- yield "### \n ๐Ÿ‘‘ Loading face swapper model...", *ui_before()
196
  load_face_swapper_model()
197
 
198
  if face_enhancer_name != "NONE":
199
  if face_enhancer_name not in cv2_interpolations:
200
- yield f"### \n ๐Ÿ”ฎ Loading {face_enhancer_name} model...", *ui_before()
201
  FACE_ENHANCER = load_face_enhancer_model(name=face_enhancer_name, device=device)
202
  else:
203
  FACE_ENHANCER = None
204
 
205
  if enable_face_parser:
206
- yield "### \n ๐Ÿงฒ Loading face parsing model...", *ui_before()
207
  load_face_parser_model()
208
 
209
  includes = mask_regions_to_list(mask_includes)
@@ -220,8 +214,6 @@ def process(
220
  def swap_process(image_sequence):
221
  ## ------------------------------ CONTENT CHECK ------------------------------
222
 
223
-
224
- yield "### \n ๐Ÿ“ก Analysing face data...", *ui_before()
225
  if condition != "Specific Face":
226
  source_data = source_path, age
227
  else:
@@ -236,12 +228,9 @@ def process(
236
  )
237
 
238
  ## ------------------------------ SWAP FUNC ------------------------------
239
-
240
- yield "### \n โš™๏ธ Generating faces...", *ui_before()
241
  preds = []
242
  matrs = []
243
  count = 0
244
- global PREVIEW
245
  for batch_pred, batch_matr in FACE_SWAPPER.batch_forward(whole_frame_list, analysed_targets, analysed_sources):
246
  preds.extend(batch_pred)
247
  matrs.extend(batch_matr)
@@ -250,14 +239,11 @@ def process(
250
 
251
  if USE_CUDA:
252
  image_grid = create_image_grid(batch_pred, size=128)
253
- PREVIEW = image_grid[:, :, ::-1]
254
- yield f"### \n โš™๏ธ Generating face Batch {count}", *ui_before()
255
 
256
  ## ------------------------------ FACE ENHANCEMENT ------------------------------
257
 
258
  generated_len = len(preds)
259
  if face_enhancer_name != "NONE":
260
- yield f"### \n ๐Ÿ“ Upscaling faces with {face_enhancer_name}...", *ui_before()
261
  for idx, pred in tqdm(enumerate(preds), total=generated_len, desc=f"Upscaling with {face_enhancer_name}"):
262
  enhancer_model, enhancer_model_runner = FACE_ENHANCER
263
  pred = enhancer_model_runner(pred, enhancer_model)
@@ -267,7 +253,6 @@ def process(
267
  ## ------------------------------ FACE PARSING ------------------------------
268
 
269
  if enable_face_parser:
270
- yield "### \n ๐Ÿ–‡๏ธ Face-parsing mask...", *ui_before()
271
  masks = []
272
  count = 0
273
  for batch_mask in get_parsed_mask(FACE_PARSER, preds, classes=includes, device=device, batch_size=BATCH_SIZE, softness=int(mask_soft_iterations)):
@@ -277,8 +262,6 @@ def process(
277
 
278
  if len(batch_mask) > 1:
279
  image_grid = create_image_grid(batch_mask, size=128)
280
- PREVIEW = image_grid[:, :, ::-1]
281
- yield f"### \n โœ๏ธ Face parsing Batch {count}", *ui_before()
282
  masks = np.concatenate(masks, axis=0) if len(masks) >= 1 else masks
283
  else:
284
  masks = [None] * generated_len
@@ -294,7 +277,6 @@ def process(
294
 
295
  ## ------------------------------ PASTE-BACK ------------------------------
296
 
297
- yield "### \n ๐Ÿ› ๏ธ Pasting back...", *ui_before()
298
  def post_process(frame_idx, frame_img, split_preds, split_matrs, split_masks, enable_laplacian_blend, crop_mask, blur_amount, erode_amount):
299
  whole_img_path = frame_img
300
  whole_img = cv2.imread(whole_img_path)
@@ -326,8 +308,17 @@ def process(
326
  blur_amount,
327
  erode_amount
328
  )
329
-
330
-
 
 
 
 
 
 
 
 
 
331
  ## ------------------------------ IMAGE ------------------------------
332
 
333
  if input_type == "Image":
@@ -400,12 +391,9 @@ def process(
400
  for info_update in swap_process(file_paths):
401
  yield info_update
402
 
403
- PREVIEW = cv2.imread(file_paths[-1])[:, :, ::-1]
404
  WORKSPACE = temp_path
405
  OUTPUT_FILE = file_paths[-1]
406
 
407
- yield get_finsh_text(start_time), *ui_after()
408
-
409
  ## ------------------------------ STREAM ------------------------------
410
 
411
  elif input_type == "Stream":
@@ -414,83 +402,7 @@ def process(
414
 
415
  ## ------------------------------ GRADIO FUNC ------------------------------
416
 
417
-
418
- def update_radio(value):
419
- if value == "Image":
420
- return (
421
- gr.update(visible=True),
422
- gr.update(visible=False),
423
- gr.update(visible=False),
424
- )
425
- elif value == "Video":
426
- return (
427
- gr.update(visible=False),
428
- gr.update(visible=True),
429
- gr.update(visible=False),
430
- )
431
- elif value == "Directory":
432
- return (
433
- gr.update(visible=False),
434
- gr.update(visible=False),
435
- gr.update(visible=True),
436
- )
437
- elif value == "Stream":
438
- return (
439
- gr.update(visible=False),
440
- gr.update(visible=False),
441
- gr.update(visible=True),
442
- )
443
-
444
-
445
- def swap_option_changed(value):
446
- if value.startswith("Age"):
447
- return (
448
- gr.update(visible=True),
449
- gr.update(visible=False),
450
- gr.update(visible=True),
451
- )
452
- elif value == "Specific Face":
453
- return (
454
- gr.update(visible=False),
455
- gr.update(visible=True),
456
- gr.update(visible=False),
457
- )
458
- return gr.update(visible=False), gr.update(visible=False), gr.update(visible=True)
459
-
460
-
461
- def video_changed(video_path):
462
- sliders_update = gr.Slider.update
463
- button_update = gr.Button.update
464
- number_update = gr.Number.update
465
-
466
- if video_path is None:
467
- return (
468
- sliders_update(minimum=0, maximum=0, value=0),
469
- sliders_update(minimum=1, maximum=1, value=1),
470
- number_update(value=1),
471
- )
472
- try:
473
- clip = VideoFileClip(video_path)
474
- fps = clip.fps
475
- total_frames = clip.reader.nframes
476
- clip.close()
477
- return (
478
- sliders_update(minimum=0, maximum=total_frames, value=0, interactive=True),
479
- sliders_update(
480
- minimum=0, maximum=total_frames, value=total_frames, interactive=True
481
- ),
482
- number_update(value=fps),
483
- )
484
- except:
485
- return (
486
- sliders_update(value=0),
487
- sliders_update(value=0),
488
- number_update(value=1),
489
- )
490
-
491
-
492
  def analyse_settings_changed(detect_condition, detection_size, detection_threshold):
493
- yield "### \n ๐Ÿ’ก Applying new values..."
494
  global FACE_ANALYSER
495
  global DETECT_CONDITION
496
  DETECT_CONDITION = detect_condition
@@ -500,8 +412,56 @@ def analyse_settings_changed(detect_condition, detection_size, detection_thresho
500
  det_size=(int(detection_size), int(detection_size)),
501
  det_thresh=float(detection_threshold),
502
  )
503
- yield f"### \n โœ”๏ธ Applied detect condition:{detect_condition}, detection size: {detection_size}, detection threshold: {detection_threshold}"
504
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
 
506
  def stop_running():
507
  global STREAMER
@@ -526,381 +486,15 @@ def slider_changed(show_frame, video_path, frame_index):
526
 
527
 
528
  def trim_and_reload(video_path, output_path, output_name, start_frame, stop_frame):
529
- yield video_path, f"### \n ๐Ÿ› ๏ธ Trimming video frame {start_frame} to {stop_frame}..."
530
  try:
531
  output_path = os.path.join(output_path, output_name)
532
  trimmed_video = trim_video(video_path, output_path, start_frame, stop_frame)
533
- yield trimmed_video, "### \n โœ”๏ธ Video trimmed and reloaded."
534
  except Exception as e:
535
  print(e)
536
- yield video_path, "### \n โŒ Video trimming failed. See console for more info."
537
-
538
-
539
- ## ------------------------------ GRADIO GUI ------------------------------
540
-
541
- css = """
542
- footer{display:none !important}
543
- """
544
-
545
- with gr.Blocks(css=css) as interface:
546
- gr.Markdown("# ๐Ÿงธ Deepfake Faceswap")
547
- gr.Markdown("### ๐Ÿ“ฅ insightface inswapper bypass NSFW.")
548
- with gr.Row():
549
- with gr.Row():
550
- with gr.Column(scale=0.4):
551
- with gr.Tab("โš–๏ธ Swap Condition"):
552
- swap_option = gr.Dropdown(
553
- swap_options_list,
554
- info="Choose which face or faces in the target image to swap.",
555
- multiselect=False,
556
- show_label=False,
557
- value=swap_options_list[0],
558
- interactive=True,
559
- )
560
- age = gr.Number(
561
- value=25, label="Value", interactive=True, visible=False
562
- )
563
-
564
- with gr.Tab("๐ŸŽ›๏ธ Detection Settings"):
565
- detect_condition_dropdown = gr.Dropdown(
566
- detect_conditions,
567
- label="Condition",
568
- value=DETECT_CONDITION,
569
- interactive=True,
570
- info="This condition is only used when multiple faces are detected on source or specific image.",
571
- )
572
- detection_size = gr.Number(
573
- label="Detection Size", value=DETECT_SIZE, interactive=True
574
- )
575
- detection_threshold = gr.Number(
576
- label="Detection Threshold",
577
- value=DETECT_THRESH,
578
- interactive=True,
579
- )
580
- apply_detection_settings = gr.Button("Apply settings")
581
-
582
- with gr.Tab("โ™ป๏ธ Output Settings"):
583
- output_directory = gr.Text(
584
- label="Output Directory",
585
- value=DEF_OUTPUT_PATH,
586
- interactive=True,
587
- )
588
- output_name = gr.Text(
589
- label="Output Name", value="Result", interactive=True
590
- )
591
- keep_output_sequence = gr.Checkbox(
592
- label="Keep output sequence", value=False, interactive=True
593
- )
594
-
595
- with gr.Tab("๐Ÿ’Ž Other Settings"):
596
- face_scale = gr.Slider(
597
- label="Face Scale",
598
- minimum=0,
599
- maximum=2,
600
- value=1,
601
- interactive=True,
602
- )
603
-
604
- face_enhancer_name = gr.Dropdown(
605
- FACE_ENHANCER_LIST, label="Face Enhancer", value="NONE", multiselect=False, interactive=True
606
- )
607
-
608
- with gr.Accordion("Advanced Mask", open=False):
609
- enable_face_parser_mask = gr.Checkbox(
610
- label="Enable Face Parsing",
611
- value=False,
612
- interactive=True,
613
- )
614
-
615
- mask_include = gr.Dropdown(
616
- mask_regions.keys(),
617
- value=MASK_INCLUDE,
618
- multiselect=True,
619
- label="Include",
620
- interactive=True,
621
- )
622
- mask_soft_kernel = gr.Number(
623
- label="Soft Erode Kernel",
624
- value=MASK_SOFT_KERNEL,
625
- minimum=3,
626
- interactive=True,
627
- visible = False
628
- )
629
- mask_soft_iterations = gr.Number(
630
- label="Soft Erode Iterations",
631
- value=MASK_SOFT_ITERATIONS,
632
- minimum=0,
633
- interactive=True,
634
-
635
- )
636
-
637
-
638
- with gr.Accordion("Crop Mask", open=False):
639
- crop_top = gr.Slider(label="Top", minimum=0, maximum=511, value=0, step=1, interactive=True)
640
- crop_bott = gr.Slider(label="Bottom", minimum=0, maximum=511, value=511, step=1, interactive=True)
641
- crop_left = gr.Slider(label="Left", minimum=0, maximum=511, value=0, step=1, interactive=True)
642
- crop_right = gr.Slider(label="Right", minimum=0, maximum=511, value=511, step=1, interactive=True)
643
-
644
-
645
- erode_amount = gr.Slider(
646
- label="Mask Erode",
647
- minimum=0,
648
- maximum=1,
649
- value=MASK_ERODE_AMOUNT,
650
- step=0.05,
651
- interactive=True,
652
- )
653
-
654
- blur_amount = gr.Slider(
655
- label="Mask Blur",
656
- minimum=0,
657
- maximum=1,
658
- value=MASK_BLUR_AMOUNT,
659
- step=0.05,
660
- interactive=True,
661
- )
662
-
663
- enable_laplacian_blend = gr.Checkbox(
664
- label="Laplacian Blending",
665
- value=True,
666
- interactive=True,
667
- )
668
-
669
-
670
- source_image_input = gr.Image(
671
- label="Source face", type="filepath", interactive=True
672
- )
673
-
674
- with gr.Box(visible=False) as specific_face:
675
- for i in range(NUM_OF_SRC_SPECIFIC):
676
- idx = i + 1
677
- code = "\n"
678
- code += f"with gr.Tab(label='({idx})'):"
679
- code += "\n\twith gr.Row():"
680
- code += f"\n\t\tsrc{idx} = gr.Image(interactive=True, type='numpy', label='Source Face {idx}')"
681
- code += f"\n\t\ttrg{idx} = gr.Image(interactive=True, type='numpy', label='Specific Face {idx}')"
682
- exec(code)
683
-
684
- distance_slider = gr.Slider(
685
- minimum=0,
686
- maximum=2,
687
- value=0.6,
688
- interactive=True,
689
- label="Distance",
690
- info="Lower distance is more similar and higher distance is less similar to the target face.",
691
- )
692
-
693
- with gr.Group():
694
- input_type = gr.Radio(
695
- ["Image", "Video"],
696
- label="Target Type",
697
- value="Image",
698
- )
699
-
700
- with gr.Box(visible=True) as input_image_group:
701
- image_input = gr.Image(
702
- label="Target Image", interactive=True, type="filepath"
703
- )
704
-
705
- with gr.Box(visible=False) as input_video_group:
706
- vid_widget = gr.Video if USE_COLAB else gr.Text
707
- video_input = gr.Video(
708
- label="Target Video", interactive=True
709
- )
710
- with gr.Accordion("๐ŸŽจ Trim video", open=False):
711
- with gr.Column():
712
- with gr.Row():
713
- set_slider_range_btn = gr.Button(
714
- "Set frame range", interactive=True
715
- )
716
- show_trim_preview_btn = gr.Checkbox(
717
- label="Show frame when slider change",
718
- value=True,
719
- interactive=True,
720
- )
721
-
722
- video_fps = gr.Number(
723
- value=30,
724
- interactive=False,
725
- label="Fps",
726
- visible=False,
727
- )
728
- start_frame = gr.Slider(
729
- minimum=0,
730
- maximum=1,
731
- value=0,
732
- step=1,
733
- interactive=True,
734
- label="Start Frame",
735
- info="",
736
- )
737
- end_frame = gr.Slider(
738
- minimum=0,
739
- maximum=1,
740
- value=1,
741
- step=1,
742
- interactive=True,
743
- label="End Frame",
744
- info="",
745
- )
746
- trim_and_reload_btn = gr.Button(
747
- "Trim and Reload", interactive=True
748
- )
749
-
750
- with gr.Box(visible=False) as input_directory_group:
751
- direc_input = gr.Text(label="Path", interactive=True)
752
-
753
- with gr.Column(scale=0.6):
754
- info = gr.Markdown(value="...")
755
-
756
- with gr.Row():
757
- swap_button = gr.Button("๐ŸŽฏ Swap", variant="primary")
758
- cancel_button = gr.Button("โŒ Cancel")
759
-
760
- preview_image = gr.Image(label="Output", interactive=False)
761
- preview_video = gr.Video(
762
- label="Output", interactive=False, visible=False
763
- )
764
-
765
- with gr.Row():
766
- output_directory_button = gr.Button(
767
- "๐Ÿ’Œ", interactive=False, visible=False
768
- )
769
- output_video_button = gr.Button(
770
- "๐Ÿ“ฝ๏ธ", interactive=False, visible=False
771
- )
772
-
773
- with gr.Box():
774
- with gr.Row():
775
- gr.Markdown(
776
- "### [๐ŸŽญ Sponsor]"
777
- )
778
- gr.Markdown(
779
- "### [๐Ÿ–ฅ๏ธ Source code](https://huggingface.co/spaces/victorisgeek/SwapFace2Pon)"
780
- )
781
- gr.Markdown(
782
- "### [ ๐Ÿงฉ Playground](https://huggingface.co/spaces/victorisgeek/SwapFace2Pon)"
783
- )
784
- gr.Markdown(
785
- "### [๐Ÿ“ธ Run in Colab](https://colab.research.google.com/github/victorgeel/FaceSwapNoNfsw/blob/main/SwapFace.ipynb)"
786
- )
787
- gr.Markdown(
788
- "### [๐Ÿค— Modified Version](https://github.com/victorgeel/FaceSwapNoNfsw)"
789
- )
790
-
791
- ## ------------------------------ GRADIO EVENTS ------------------------------
792
-
793
- set_slider_range_event = set_slider_range_btn.click(
794
- video_changed,
795
- inputs=[video_input],
796
- outputs=[start_frame, end_frame, video_fps],
797
- )
798
 
799
- trim_and_reload_event = trim_and_reload_btn.click(
800
- fn=trim_and_reload,
801
- inputs=[video_input, output_directory, output_name, start_frame, end_frame],
802
- outputs=[video_input, info],
803
- )
804
-
805
- start_frame_event = start_frame.release(
806
- fn=slider_changed,
807
- inputs=[show_trim_preview_btn, video_input, start_frame],
808
- outputs=[preview_image, preview_video],
809
- show_progress=True,
810
- )
811
-
812
- end_frame_event = end_frame.release(
813
- fn=slider_changed,
814
- inputs=[show_trim_preview_btn, video_input, end_frame],
815
- outputs=[preview_image, preview_video],
816
- show_progress=True,
817
- )
818
-
819
- input_type.change(
820
- update_radio,
821
- inputs=[input_type],
822
- outputs=[input_image_group, input_video_group, input_directory_group],
823
- )
824
- swap_option.change(
825
- swap_option_changed,
826
- inputs=[swap_option],
827
- outputs=[age, specific_face, source_image_input],
828
- )
829
-
830
- apply_detection_settings.click(
831
- analyse_settings_changed,
832
- inputs=[detect_condition_dropdown, detection_size, detection_threshold],
833
- outputs=[info],
834
- )
835
-
836
- src_specific_inputs = []
837
- gen_variable_txt = ",".join(
838
- [f"src{i+1}" for i in range(NUM_OF_SRC_SPECIFIC)]
839
- + [f"trg{i+1}" for i in range(NUM_OF_SRC_SPECIFIC)]
840
- )
841
- exec(f"src_specific_inputs = ({gen_variable_txt})")
842
- swap_inputs = [
843
- input_type,
844
- image_input,
845
- video_input,
846
- direc_input,
847
- source_image_input,
848
- output_directory,
849
- output_name,
850
- keep_output_sequence,
851
- swap_option,
852
- age,
853
- distance_slider,
854
- face_enhancer_name,
855
- enable_face_parser_mask,
856
- mask_include,
857
- mask_soft_kernel,
858
- mask_soft_iterations,
859
- blur_amount,
860
- erode_amount,
861
- face_scale,
862
- enable_laplacian_blend,
863
- crop_top,
864
- crop_bott,
865
- crop_left,
866
- crop_right,
867
- *src_specific_inputs,
868
- ]
869
-
870
- swap_outputs = [
871
- info,
872
- preview_image,
873
- output_directory_button,
874
- output_video_button,
875
- preview_video,
876
- ]
877
-
878
- swap_event = swap_button.click(
879
- fn=process, inputs=swap_inputs, outputs=swap_outputs, show_progress=True
880
- )
881
-
882
- cancel_button.click(
883
- fn=stop_running,
884
- inputs=None,
885
- outputs=[info],
886
- cancels=[
887
- swap_event,
888
- trim_and_reload_event,
889
- set_slider_range_event,
890
- start_frame_event,
891
- end_frame_event,
892
- ],
893
- show_progress=True,
894
- )
895
- output_directory_button.click(
896
- lambda: open_directory(path=WORKSPACE), inputs=None, outputs=None
897
- )
898
- output_video_button.click(
899
- lambda: open_directory(path=OUTPUT_FILE), inputs=None, outputs=None
900
- )
901
 
902
  if __name__ == "__main__":
903
  if USE_COLAB:
904
  print("Running in colab mode")
905
 
906
- interface.queue(concurrency_count=2, max_size=20).launch(share=USE_COLAB)
 
17
  from tqdm import tqdm
18
  import concurrent.futures
19
  from moviepy.editor import VideoFileClip
20
+ from PIL import Image
21
+ import io
22
 
23
  from face_swapper import Inswapper, paste_to_whole
24
  from face_analyser import detect_conditions, get_analysed_data, swap_options_list
 
185
 
186
  start_time = time.time()
187
  total_exec_time = lambda start_time: divmod(time.time() - start_time, 60)
 
188
 
189
  ## ------------------------------ PREPARE INPUTS & LOAD MODELS ------------------------------
190
 
 
 
 
191
  load_face_analyser_model()
 
 
192
  load_face_swapper_model()
193
 
194
  if face_enhancer_name != "NONE":
195
  if face_enhancer_name not in cv2_interpolations:
 
196
  FACE_ENHANCER = load_face_enhancer_model(name=face_enhancer_name, device=device)
197
  else:
198
  FACE_ENHANCER = None
199
 
200
  if enable_face_parser:
 
201
  load_face_parser_model()
202
 
203
  includes = mask_regions_to_list(mask_includes)
 
214
  def swap_process(image_sequence):
215
  ## ------------------------------ CONTENT CHECK ------------------------------
216
 
 
 
217
  if condition != "Specific Face":
218
  source_data = source_path, age
219
  else:
 
228
  )
229
 
230
  ## ------------------------------ SWAP FUNC ------------------------------
 
 
231
  preds = []
232
  matrs = []
233
  count = 0
 
234
  for batch_pred, batch_matr in FACE_SWAPPER.batch_forward(whole_frame_list, analysed_targets, analysed_sources):
235
  preds.extend(batch_pred)
236
  matrs.extend(batch_matr)
 
239
 
240
  if USE_CUDA:
241
  image_grid = create_image_grid(batch_pred, size=128)
 
 
242
 
243
  ## ------------------------------ FACE ENHANCEMENT ------------------------------
244
 
245
  generated_len = len(preds)
246
  if face_enhancer_name != "NONE":
 
247
  for idx, pred in tqdm(enumerate(preds), total=generated_len, desc=f"Upscaling with {face_enhancer_name}"):
248
  enhancer_model, enhancer_model_runner = FACE_ENHANCER
249
  pred = enhancer_model_runner(pred, enhancer_model)
 
253
  ## ------------------------------ FACE PARSING ------------------------------
254
 
255
  if enable_face_parser:
 
256
  masks = []
257
  count = 0
258
  for batch_mask in get_parsed_mask(FACE_PARSER, preds, classes=includes, device=device, batch_size=BATCH_SIZE, softness=int(mask_soft_iterations)):
 
262
 
263
  if len(batch_mask) > 1:
264
  image_grid = create_image_grid(batch_mask, size=128)
 
 
265
  masks = np.concatenate(masks, axis=0) if len(masks) >= 1 else masks
266
  else:
267
  masks = [None] * generated_len
 
277
 
278
  ## ------------------------------ PASTE-BACK ------------------------------
279
 
 
280
  def post_process(frame_idx, frame_img, split_preds, split_matrs, split_masks, enable_laplacian_blend, crop_mask, blur_amount, erode_amount):
281
  whole_img_path = frame_img
282
  whole_img = cv2.imread(whole_img_path)
 
308
  blur_amount,
309
  erode_amount
310
  )
311
+ ## ------------------------------ Gardio API ------------------------------
312
+ iface = gr.Interface(
313
+ fn=process_api,
314
+ inputs=[
315
+ gr.Textbox(label="Source Image (base64)"),
316
+ gr.Textbox(label="Target Image (base64)")
317
+ ],
318
+ outputs=gr.Textbox(label="Result Image (base64)"),
319
+ title="Face Swap API",
320
+ description="Submit two base64 encoded images to swap faces."
321
+ )
322
  ## ------------------------------ IMAGE ------------------------------
323
 
324
  if input_type == "Image":
 
391
  for info_update in swap_process(file_paths):
392
  yield info_update
393
 
 
394
  WORKSPACE = temp_path
395
  OUTPUT_FILE = file_paths[-1]
396
 
 
 
397
  ## ------------------------------ STREAM ------------------------------
398
 
399
  elif input_type == "Stream":
 
402
 
403
  ## ------------------------------ GRADIO FUNC ------------------------------
404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  def analyse_settings_changed(detect_condition, detection_size, detection_threshold):
 
406
  global FACE_ANALYSER
407
  global DETECT_CONDITION
408
  DETECT_CONDITION = detect_condition
 
412
  det_size=(int(detection_size), int(detection_size)),
413
  det_thresh=float(detection_threshold),
414
  )
 
415
 
416
+ def decode_base64_image(base64_string):
417
+ img_data = base64.b64decode(base64_string)
418
+ img = Image.open(io.BytesIO(img_data))
419
+ return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
420
+
421
+ def process_api(source_base64, target_base64):
422
+ source_image = decode_base64_image(source_base64)
423
+ target_image = decode_base64_image(target_base64)
424
+
425
+ temp_source_path = "temp_source.jpg"
426
+ temp_target_path = "temp_target.jpg"
427
+ cv2.imwrite(temp_source_path, source_image)
428
+ cv2.imwrite(temp_target_path, target_image)
429
+
430
+ result = process(
431
+ input_type="Image",
432
+ image_path=temp_target_path,
433
+ video_path=None,
434
+ directory_path=None,
435
+ source_path=temp_source_path,
436
+ output_path="output",
437
+ output_name="result",
438
+ keep_output_sequence=False,
439
+ condition="First found face",
440
+ age=None,
441
+ distance=None,
442
+ face_enhancer_name="NONE",
443
+ enable_face_parser=False,
444
+ mask_includes=MASK_INCLUDE,
445
+ mask_soft_kernel=MASK_SOFT_KERNEL,
446
+ mask_soft_iterations=MASK_SOFT_ITERATIONS,
447
+ blur_amount=MASK_BLUR_AMOUNT,
448
+ erode_amount=MASK_ERODE_AMOUNT,
449
+ face_scale=1.0,
450
+ enable_laplacian_blend=True,
451
+ crop_top,
452
+ crop_bott,
453
+ crop_left,
454
+ crop_right,
455
+ )
456
+
457
+ os.remove(temp_source_path)
458
+ os.remove(temp_target_path)
459
+
460
+ result_image = cv2.imread("output/result.png")
461
+ _, buffer = cv2.imencode('.jpg', result_image)
462
+ result_base64 = base64.b64encode(buffer).decode('utf-8')
463
+
464
+ return result_base64
465
 
466
  def stop_running():
467
  global STREAMER
 
486
 
487
 
488
  def trim_and_reload(video_path, output_path, output_name, start_frame, stop_frame):
 
489
  try:
490
  output_path = os.path.join(output_path, output_name)
491
  trimmed_video = trim_video(video_path, output_path, start_frame, stop_frame)
 
492
  except Exception as e:
493
  print(e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
494
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
495
 
496
  if __name__ == "__main__":
497
  if USE_COLAB:
498
  print("Running in colab mode")
499
 
500
+ iface.queue(concurrency_count=2, max_size=20).launch(share=USE_COLAB)