Athagi commited on
Commit
570c459
Β·
1 Parent(s): 140f1b3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +98 -63
app.py CHANGED
@@ -1,70 +1,105 @@
1
- import gradio as gr
2
  import os
3
  import cv2
4
- import torch
5
  import numpy as np
 
 
 
6
  from PIL import Image
 
7
 
8
- from gfpgan import GFPGANer
9
- from insightface.app import FaceAnalysis
10
- from insightface.model_zoo import model_zoo
11
-
12
- # Paths
13
- MODEL_DIR = "models"
14
- GFPGAN_MODEL_PATH = os.path.join(MODEL_DIR, "GFPGANv1.4.pth")
15
- INSWAPPER_PATH = os.path.join(MODEL_DIR, "inswapper_128.onnx")
16
-
17
- # Initialize GFPGAN
18
- gfpganer = GFPGANer(
19
- model_path=GFPGAN_MODEL_PATH,
20
- upscale=2,
21
- arch='clean',
22
- channel_multiplier=2,
23
- bg_upsampler=None
24
- )
25
-
26
- # Initialize InsightFace (for face detection + swapping)
27
- faceapp = FaceAnalysis(name='buffalo_l', providers=['CPUExecutionProvider'])
28
- faceapp.prepare(ctx_id=0)
29
-
30
- swapper = model_zoo.get_model(INSWAPPER_PATH, providers=['CPUExecutionProvider'])
31
-
32
- # Function: Face Restoration + Swapping
33
- def restore_and_swap(input_img: Image.Image, target_img: Image.Image):
34
- input_np = np.array(input_img.convert("RGB"))
35
- target_np = np.array(target_img.convert("RGB"))
36
-
37
- # Step 1: Face restore
38
- cropped_faces, restored_img = gfpganer.enhance(input_np, has_aligned=False, only_center_face=False, paste_back=True)
39
-
40
- # Step 2: Detect face in target
41
- target_faces = faceapp.get(target_np)
42
- if len(target_faces) == 0:
43
- return Image.fromarray(restored_img), "No face found in target image."
44
 
45
- # Step 3: Detect face in restored image
46
- source_faces = faceapp.get(restored_img)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  if len(source_faces) == 0:
48
- return Image.fromarray(restored_img), "No face found in restored image."
49
-
50
- # Step 4: Face swap using first face
51
- swapped = swapper.get(restored_img, source_faces[0], target_faces[0], paste_back=True)
52
-
53
- return Image.fromarray(swapped), "Success! Face restored and swapped."
54
-
55
- # Gradio Interface
56
- iface = gr.Interface(
57
- fn=restore_and_swap,
58
- inputs=[
59
- gr.Image(type="pil", label="Input Image (to restore + swap)"),
60
- gr.Image(type="pil", label="Target Image (face to apply)")
61
- ],
62
- outputs=[
63
- gr.Image(type="pil", label="Output Image"),
64
- gr.Textbox(label="Status")
65
- ],
66
- title="GFPGAN + InsightFace Face Swapper",
67
- description="This app restores old faces using GFPGAN and swaps them with another face using InsightFace InSwapper."
68
- )
69
-
70
- iface.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import cv2
 
3
  import numpy as np
4
+ import gradio as gr
5
+ from insightface.app import FaceAnalysis
6
+ from insightface.model_zoo import get_model
7
  from PIL import Image
8
+ import tempfile
9
 
10
+ # Load InsightFace components
11
+ face_analyzer = FaceAnalysis(name='buffalo_l', providers=['CPUExecutionProvider'])
12
+ face_analyzer.prepare(ctx_id=0, det_size=(640, 640))
13
+
14
+ swapper_model_path = "models/inswapper_128.onnx"
15
+ swapper = get_model(swapper_model_path, download=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ def draw_faces(image_np, faces):
18
+ """Draw bounding boxes and labels on detected faces."""
19
+ image_draw = image_np.copy()
20
+ for i, face in enumerate(faces):
21
+ box = face.bbox.astype(int)
22
+ cv2.rectangle(image_draw, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 2)
23
+ cv2.putText(image_draw, f"Face {i}", (box[0], box[1] - 10),
24
+ cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
25
+ return image_draw
26
+
27
+ def preview_faces(target_image):
28
+ """Preview all detected faces in target image."""
29
+ if target_image is None:
30
+ raise gr.Error("Please upload a target image.")
31
+ target_np = cv2.cvtColor(np.array(target_image), cv2.COLOR_RGB2BGR)
32
+ faces = face_analyzer.get(target_np)
33
+ if len(faces) == 0:
34
+ raise gr.Error("No faces found in target image.")
35
+ preview_img = draw_faces(target_np, faces)
36
+ preview_img_rgb = cv2.cvtColor(preview_img, cv2.COLOR_BGR2RGB)
37
+ return Image.fromarray(preview_img_rgb), [str(i) for i in range(len(faces))]
38
+
39
+ def swap_faces(source_img, target_img, face_index_str, blend_alpha):
40
+ if source_img is None or target_img is None:
41
+ raise gr.Error("Please upload both source and target images.")
42
+
43
+ source_np = cv2.cvtColor(np.array(source_img), cv2.COLOR_RGB2BGR)
44
+ target_np = cv2.cvtColor(np.array(target_img), cv2.COLOR_RGB2BGR)
45
+
46
+ source_faces = face_analyzer.get(source_np)
47
  if len(source_faces) == 0:
48
+ raise gr.Error("No face found in source image.")
49
+
50
+ target_faces = face_analyzer.get(target_np)
51
+ if len(target_faces) == 0:
52
+ raise gr.Error("No faces found in target image.")
53
+
54
+ face_index = int(face_index_str)
55
+ if face_index >= len(target_faces):
56
+ raise gr.Error("Face index out of range.")
57
+
58
+ # Perform face swap
59
+ try:
60
+ swapped = swapper.get(target_np, target_faces[face_index], source_faces[0], paste_back=True)
61
+ # Blend original + swapped if alpha < 1.0
62
+ if 0 <= blend_alpha < 1.0:
63
+ blended = cv2.addWeighted(target_np, 1 - blend_alpha, swapped, blend_alpha, 0)
64
+ else:
65
+ blended = swapped
66
+ final_rgb = cv2.cvtColor(blended, cv2.COLOR_BGR2RGB)
67
+ output_img = Image.fromarray(final_rgb)
68
+
69
+ # Save temp file for download
70
+ tmp_file = tempfile.NamedTemporaryFile(suffix=".jpg", delete=False)
71
+ output_img.save(tmp_file.name)
72
+ return output_img, tmp_file.name, "βœ… Face swap successful!"
73
+
74
+ except Exception as e:
75
+ raise gr.Error(f"Face swap failed: {e}")
76
+
77
+ # Gradio UI
78
+ with gr.Blocks(title="Enhanced Face Swap") as demo:
79
+ gr.Markdown("## πŸ” Enhanced Face Swapper (CPU-only)")
80
+
81
+ with gr.Row():
82
+ source_image = gr.Image(label="Source Face", type="pil")
83
+ target_image = gr.Image(label="Target Image", type="pil")
84
+
85
+ preview_btn = gr.Button("πŸ‘οΈ Preview Detected Faces")
86
+ preview_output = gr.Image(label="Target Faces Preview")
87
+ face_dropdown = gr.Dropdown(choices=[], label="Select Face Index")
88
+ blend_slider = gr.Slider(label="Swap Strength", minimum=0.0, maximum=1.0, step=0.1, value=1.0)
89
+ swap_button = gr.Button("πŸ”„ Swap Face")
90
+
91
+ with gr.Row():
92
+ output_image = gr.Image(label="Swapped Result")
93
+ download_file = gr.File(label="Download Swapped Image")
94
+
95
+ status = gr.Textbox(label="Status", interactive=False)
96
+
97
+ preview_btn.click(preview_faces, inputs=target_image,
98
+ outputs=[preview_output, face_dropdown])
99
+
100
+ swap_button.click(swap_faces,
101
+ inputs=[source_image, target_image, face_dropdown, blend_slider],
102
+ outputs=[output_image, download_file, status])
103
+
104
+ if __name__ == "__main__":
105
+ demo.launch()