VanNguyen1214 commited on
Commit
83d879e
·
verified ·
1 Parent(s): 8dff9a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -182
app.py CHANGED
@@ -1,182 +1,173 @@
1
-
2
- import gradio as gr
3
- from overlay import overlay_source
4
- from detect_face import predict, NUM_CLASSES
5
- from swapface import swap_face_now
6
- import os
7
- from pathlib import Path
8
-
9
- BASE_DIR = Path(__file__).parent # thư mục chứa app.py
10
- FOLDER = BASE_DIR / "example_wigs"
11
-
12
- # --- Hàm load ảnh từ folder ---
13
- def load_images_from_folder(folder_path: str) -> list[str]:
14
- """
15
- Trả về list[str] chứa tất cả các hình (jpg, png, gif, bmp) trong folder_path.
16
- """
17
- supported = {'.jpg', '.jpeg', '.png', '.gif', '.bmp'}
18
- if not os.path.isdir(folder_path):
19
- print(f"Cảnh báo: '{folder_path}' không phải folder hợp lệ.")
20
- return []
21
- files = [
22
- os.path.join(folder_path, fn)
23
- for fn in os.listdir(folder_path)
24
- if os.path.splitext(fn)[1].lower() in supported
25
- ]
26
- if not files:
27
- print(f"Không tìm thấy hình trong: {folder_path}")
28
- return files
29
-
30
- def on_gallery_select(evt: gr.SelectData):
31
- """
32
- Khi click thumbnail: trả về
33
- 1) filepath để nạp vào Image Source
34
- 2) tên file (basename) để hiển thị trong Textbox
35
- """
36
- val = evt.value
37
-
38
- # --- logic trích filepath y như cũ ---
39
- if isinstance(val, dict):
40
- img = val.get("image")
41
- if isinstance(img, str):
42
- filepath = img
43
- elif isinstance(img, dict):
44
- filepath = img.get("path") or img.get("url")
45
- else:
46
- filepath = next(
47
- (v for v in val.values() if isinstance(v, str) and os.path.isfile(v)),
48
- None
49
- )
50
- elif isinstance(val, str):
51
- filepath = val
52
- else:
53
- raise ValueError(f"Kiểu không hỗ trợ: {type(val)}")
54
-
55
- filename = os.path.basename(filepath) if filepath else ""
56
- return filepath, filename
57
-
58
- # --- Hàm xác định folder dựa trên phân lớp ---
59
- def infer_folder(image) -> str:
60
- cls = predict(image)["predicted_class"]
61
- folder = str(FOLDER / cls)
62
- return folder
63
-
64
- # --- Hàm gộp: phân loại + load ảnh ---
65
- def handle_bg_change(image):
66
- """
67
- Khi thay đổi background:
68
- 1. Phân loại khuôn mặt
69
- 2. Load ảnh từ folder tương ứng
70
- """
71
- if image is None:
72
- return "", []
73
-
74
- try:
75
- folder = infer_folder(image)
76
- images = load_images_from_folder(folder)
77
- return folder, images
78
- except Exception as e:
79
- print(f"Lỗi xử lý ảnh: {e}")
80
- return "", []
81
-
82
- # --- Hàm swap face ---
83
- def swap_face_wrapper(background_img, result_img):
84
- """
85
- Wrapper function cho swap face giữa background và result image
86
- """
87
- if background_img is None or result_img is None:
88
- return None
89
-
90
- try:
91
- # Swap face từ background vào result image
92
- swapped = swap_face_now(background_img, result_img, do_enhance=True)
93
- return swapped
94
- except Exception as e:
95
- print(f"Lỗi swap face: {e}")
96
- return result_img # Trả về ảnh gốc nếu có lỗi
97
-
98
- # --- Hàm gộp overlay + swap face ---
99
- def combined_hair_and_face(background_img, source_img):
100
- """
101
- Hàm gộp: chạy overlay trước, sau đó swap face
102
- """
103
- if background_img is None or source_img is None:
104
- return None
105
-
106
- try:
107
- # Bước 1: Chạy overlay (ghép tóc)
108
- hair_result = overlay_source(background_img, source_img)
109
-
110
- # Bước 2: Chạy swap face từ background lên kết quả overlay
111
- final_result = swap_face_wrapper(background_img, hair_result)
112
-
113
- return final_result
114
- except Exception as e:
115
- print(f"Lỗi trong quá trình gộp hair + face: {e}")
116
- return None
117
-
118
- # --- Xây dựng giao diện Gradio ---
119
- def build_demo():
120
- with gr.Blocks(title="Hair Try-On & Face Swap", theme=gr.themes.Soft()) as demo:
121
- gr.Markdown("""
122
- # 🎯 Hair Try-On & Face Swap Application
123
- """)
124
- with gr.Row():
125
- bg = gr.Image(type="pil", label="Background", height=500)
126
- src = gr.Image(type="pil", label="Source", height=500, interactive=False)
127
- out = gr.Image(label="Result", height=500, interactive=False)
128
-
129
- folder_path_box = gr.Textbox(label="Folder path", visible=False)
130
-
131
-
132
- with gr.Row():
133
- src_name_box = gr.Textbox(
134
- label="Wigs Name",
135
- interactive=False,
136
- show_copy_button=True , # tuỳ chọn – tiện copy đường dẫn
137
- scale = 1
138
- )
139
- gallery = gr.Gallery(
140
- label="Recommend For You",
141
- height=300,
142
- value=[],
143
- type="filepath",
144
- interactive=False,
145
- columns=5,
146
- object_fit="cover",
147
- allow_preview=True,
148
- scale = 8
149
- )
150
- with gr.Column(scale=1):
151
- combined_btn = gr.Button("🔄✨ Run Hair + Face Swap", variant="primary")
152
- btn = gr.Button("🔄 Run Hair Only", variant="secondary")
153
- swap_btn = gr.Button("👤 Swap Face Only", variant="secondary")
154
-
155
-
156
-
157
- # Chạy gộp hair + face swap
158
- combined_btn.click(fn=combined_hair_and_face, inputs=[bg, src], outputs=[out])
159
-
160
- # Chạy ghép tóc
161
- btn.click(fn=overlay_source, inputs=[bg, src], outputs=[out])
162
-
163
- # Chạy swap face
164
- swap_btn.click(fn=swap_face_wrapper, inputs=[bg, out], outputs=[out])
165
-
166
- # Khi đổi ảnh background, tự động phân loại và load ảnh gợi ý
167
- bg.change(
168
- fn=handle_bg_change,
169
- inputs=[bg],
170
- outputs=[folder_path_box, gallery],
171
- show_progress=True
172
- )
173
- # Khi chọn ảnh trong gallery, cập nhật vào khung Source
174
- gallery.select(
175
- fn=on_gallery_select,
176
- outputs=[src, src_name_box]
177
- )
178
-
179
- return demo
180
-
181
- if __name__ == "__main__":
182
- build_demo().launch()
 
1
+
2
+ import gradio as gr
3
+ from overlay import overlay_source
4
+ from detect_face import predict, NUM_CLASSES
5
+ from swapface import swap_face_now
6
+ import os
7
+ from pathlib import Path
8
+
9
+ BASE_DIR = Path(__file__).parent # thư mục chứa app.py
10
+ FOLDER = BASE_DIR / "example_wigs"
11
+
12
+ # --- Hàm load ảnh từ folder ---
13
+ def load_images_from_folder(folder_path: str) -> list[str]:
14
+ """
15
+ Trả về list[str] chứa tất cả các hình (jpg, png, gif, bmp) trong folder_path.
16
+ """
17
+ supported = {'.jpg', '.jpeg', '.png', '.gif', '.bmp'}
18
+ if not os.path.isdir(folder_path):
19
+ print(f"Cảnh báo: '{folder_path}' không phải folder hợp lệ.")
20
+ return []
21
+ files = [
22
+ os.path.join(folder_path, fn)
23
+ for fn in os.listdir(folder_path)
24
+ if os.path.splitext(fn)[1].lower() in supported
25
+ ]
26
+ if not files:
27
+ print(f"Không tìm thấy hình trong: {folder_path}")
28
+ return files
29
+
30
+ def on_gallery_select(evt: gr.SelectData):
31
+ """
32
+ Khi click thumbnail: trả về
33
+ 1) filepath để nạp vào Image Source
34
+ 2) tên file (basename) để hiển thị trong Textbox
35
+ """
36
+ val = evt.value
37
+
38
+ # --- logic trích filepath y như cũ ---
39
+ if isinstance(val, dict):
40
+ img = val.get("image")
41
+ if isinstance(img, str):
42
+ filepath = img
43
+ elif isinstance(img, dict):
44
+ filepath = img.get("path") or img.get("url")
45
+ else:
46
+ filepath = next(
47
+ (v for v in val.values() if isinstance(v, str) and os.path.isfile(v)),
48
+ None
49
+ )
50
+ elif isinstance(val, str):
51
+ filepath = val
52
+ else:
53
+ raise ValueError(f"Kiểu không hỗ trợ: {type(val)}")
54
+
55
+ filename = os.path.basename(filepath) if filepath else ""
56
+ return filepath, filename
57
+
58
+ # --- Hàm xác định folder dựa trên phân lớp ---
59
+ def infer_folder(image) -> str:
60
+ cls = predict(image)["predicted_class"]
61
+ folder = str(FOLDER / cls)
62
+ return folder
63
+
64
+ # --- Hàm gộp: phân loại + load ảnh ---
65
+ def handle_bg_change(image):
66
+ """
67
+ Khi thay đổi background:
68
+ 1. Phân loại khuôn mặt
69
+ 2. Load ảnh từ folder tương ứng
70
+ """
71
+ if image is None:
72
+ return "", []
73
+
74
+ try:
75
+ folder = infer_folder(image)
76
+ images = load_images_from_folder(folder)
77
+ return folder, images
78
+ except Exception as e:
79
+ print(f"Lỗi xử lý ảnh: {e}")
80
+ return "", []
81
+
82
+ # --- Hàm swap face ---
83
+ def swap_face_wrapper(background_img, result_img):
84
+ """
85
+ Wrapper function cho swap face giữa background và result image
86
+ """
87
+ if background_img is None or result_img is None:
88
+ return None
89
+
90
+ try:
91
+ # Swap face từ background vào result image
92
+ swapped = swap_face_now(background_img, result_img, do_enhance=True)
93
+ return swapped
94
+ except Exception as e:
95
+ print(f"Lỗi swap face: {e}")
96
+ return result_img # Trả về ảnh gốc nếu có lỗi
97
+
98
+ # --- Hàm gộp overlay + swap face ---
99
+ def combined_hair_and_face(background_img, source_img):
100
+ """
101
+ Hàm gộp: chạy overlay trước, sau đó swap face
102
+ """
103
+ if background_img is None or source_img is None:
104
+ return None
105
+
106
+ try:
107
+ # Bước 1: Chạy overlay (ghép tóc)
108
+ hair_result = overlay_source(background_img, source_img)
109
+
110
+ # Bước 2: Chạy swap face từ background lên kết quả overlay
111
+ final_result = swap_face_wrapper(background_img, hair_result)
112
+
113
+ return final_result
114
+ except Exception as e:
115
+ print(f"Lỗi trong quá trình gộp hair + face: {e}")
116
+ return None
117
+
118
+ # --- Xây dựng giao diện Gradio ---
119
+ def build_demo():
120
+ with gr.Blocks(title="Hair Try-On & Face Swap", theme=gr.themes.Soft()) as demo:
121
+ gr.Markdown("""
122
+ # 🎯 Hair Try-On & Face Swap Application
123
+ """)
124
+ with gr.Row():
125
+ bg = gr.Image(type="pil", label="Background", height=500)
126
+ src = gr.Image(type="pil", label="Source", height=500, interactive=False)
127
+ out = gr.Image(label="Result", height=500, interactive=False)
128
+
129
+ folder_path_box = gr.Textbox(label="Folder path", visible=False)
130
+
131
+
132
+ with gr.Row():
133
+ src_name_box = gr.Textbox(
134
+ label="Wigs Name",
135
+ interactive=False,
136
+ show_copy_button=True , # tuỳ chọn – tiện copy đường dẫn
137
+ scale = 1
138
+ )
139
+ gallery = gr.Gallery(
140
+ label="Recommend For You",
141
+ height=300,
142
+ value=[],
143
+ type="filepath",
144
+ interactive=False,
145
+ columns=5,
146
+ object_fit="cover",
147
+ allow_preview=True,
148
+ scale = 8
149
+ )
150
+ with gr.Column(scale=1):
151
+ combined_btn = gr.Button("🔄✨ Run Hair + Face Swap", variant="primary")
152
+
153
+ # Chạy gộp hair + face swap
154
+ combined_btn.click(fn=combined_hair_and_face, inputs=[bg, src], outputs=[out])
155
+
156
+
157
+ # Khi đổi ảnh background, tự động phân loại và load ảnh gợi ý
158
+ bg.change(
159
+ fn=handle_bg_change,
160
+ inputs=[bg],
161
+ outputs=[folder_path_box, gallery],
162
+ show_progress=True
163
+ )
164
+ # Khi chọn ảnh trong gallery, cập nhật vào khung Source
165
+ gallery.select(
166
+ fn=on_gallery_select,
167
+ outputs=[src, src_name_box]
168
+ )
169
+
170
+ return demo
171
+
172
+ if __name__ == "__main__":
173
+ build_demo().launch()