DegMaTsu commited on
Commit
837219b
·
verified ·
1 Parent(s): 7653fcf

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +254 -254
app.py CHANGED
@@ -1,254 +1,254 @@
1
- import os
2
- import torch
3
- from comfy.model_management import CPUState # Импорт из того же файла
4
-
5
- # Отключаем CUDA, чтобы избежать инициализации
6
- os.environ["CUDA_VISIBLE_DEVICES"] = ""
7
- os.environ["PYTORCH_CUDA_ALLOC_CONF"] = ""
8
-
9
- # Принудительно устанавливаем CPU режим
10
- import comfy.model_management
11
- comfy.model_management.cpu_state = CPUState.CPU
12
-
13
- import random
14
- import sys
15
- from typing import Sequence, Mapping, Any, Union
16
- from PIL import Image
17
- from huggingface_hub import hf_hub_download
18
- import spaces
19
-
20
- import subprocess, sys
21
-
22
- import gradio
23
- import gradio_client
24
- import gradio as gr
25
-
26
- print("gradio version:", gradio.__version__)
27
- print("gradio_client version:", gradio_client.__version__)
28
-
29
- hf_hub_download(repo_id="ezioruan/inswapper_128.onnx", filename="inswapper_128.onnx", local_dir="models/insightface")
30
- hf_hub_download(repo_id="martintomov/comfy", filename="facerestore_models/GPEN-BFR-512.onnx", local_dir="models")
31
-
32
- hf_hub_download(repo_id="facefusion/models-3.3.0", filename="hyperswap_1a_256.onnx", local_dir="models/hyperswap")
33
- hf_hub_download(repo_id="facefusion/models-3.3.0", filename="hyperswap_1b_256.onnx", local_dir="models/hyperswap")
34
- hf_hub_download(repo_id="facefusion/models-3.3.0", filename="hyperswap_1c_256.onnx", local_dir="models/hyperswap")
35
-
36
- hf_hub_download(repo_id="martintomov/comfy", filename="facedetection/yolov5l-face.pth", local_dir="models")
37
- ###hf_hub_download(repo_id="darkeril/collection", filename="detection_Resnet50_Final.pth", local_dir="models/facedetection")
38
- hf_hub_download(repo_id="gmk123/GFPGAN", filename="parsing_parsenet.pth", local_dir="models/facedetection")
39
-
40
- hf_hub_download(repo_id="MonsterMMORPG/tools", filename="1k3d68.onnx", local_dir="models/insightface/models/buffalo_l")
41
- hf_hub_download(repo_id="MonsterMMORPG/tools", filename="2d106det.onnx", local_dir="models/insightface/models/buffalo_l")
42
- hf_hub_download(repo_id="maze/faceX", filename="det_10g.onnx", local_dir="models/insightface/models/buffalo_l")
43
- hf_hub_download(repo_id="typhoon01/aux_models", filename="genderage.onnx", local_dir="models/insightface/models/buffalo_l")
44
- hf_hub_download(repo_id="maze/faceX", filename="w600k_r50.onnx", local_dir="models/insightface/models/buffalo_l")
45
-
46
- hf_hub_download(repo_id="vladmandic/insightface-faceanalysis", filename="buffalo_l.zip", local_dir="models/insightface/models/buffalo_l")
47
-
48
-
49
- def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
50
- """Returns the value at the given index of a sequence or mapping.
51
-
52
- If the object is a sequence (like list or string), returns the value at the given index.
53
- If the object is a mapping (like a dictionary), returns the value at the index-th key.
54
-
55
- Some return a dictionary, in these cases, we look for the "results" key
56
-
57
- Args:
58
- obj (Union[Sequence, Mapping]): The object to retrieve the value from.
59
- index (int): The index of the value to retrieve.
60
-
61
- Returns:
62
- Any: The value at the given index.
63
-
64
- Raises:
65
- IndexError: If the index is out of bounds for the object and the object is not a mapping.
66
- """
67
- try:
68
- return obj[index]
69
- except KeyError:
70
- return obj["result"][index]
71
-
72
-
73
- def find_path(name: str, path: str = None) -> str:
74
- """
75
- Recursively looks at parent folders starting from the given path until it finds the given name.
76
- Returns the path as a Path object if found, or None otherwise.
77
- """
78
- # If no path is given, use the current working directory
79
- if path is None:
80
- path = os.getcwd()
81
-
82
- # Check if the current directory contains the name
83
- if name in os.listdir(path):
84
- path_name = os.path.join(path, name)
85
- print(f"{name} found: {path_name}")
86
- return path_name
87
-
88
- # Get the parent directory
89
- parent_directory = os.path.dirname(path)
90
-
91
- # If the parent directory is the same as the current directory, we've reached the root and stop the search
92
- if parent_directory == path:
93
- return None
94
-
95
- # Recursively call the function with the parent directory
96
- return find_path(name, parent_directory)
97
-
98
-
99
- def add_comfyui_directory_to_sys_path() -> None:
100
- """
101
- Add 'ComfyUI' to the sys.path
102
- """
103
- comfyui_path = find_path("ComfyUI")
104
- if comfyui_path is not None and os.path.isdir(comfyui_path):
105
- sys.path.append(comfyui_path)
106
- print(f"'{comfyui_path}' added to sys.path")
107
-
108
-
109
- def add_extra_model_paths() -> None:
110
- """
111
- Parse the optional extra_model_paths.yaml file and add the parsed paths to the sys.path.
112
- """
113
- try:
114
- from main import load_extra_path_config
115
- except ImportError:
116
- print(
117
- "Could not import load_extra_path_config from main.py. Looking in utils.extra_config instead."
118
- )
119
- from utils.extra_config import load_extra_path_config
120
-
121
- extra_model_paths = find_path("extra_model_paths.yaml")
122
-
123
- if extra_model_paths is not None:
124
- load_extra_path_config(extra_model_paths)
125
- else:
126
- print("Could not find the extra_model_paths config file.")
127
-
128
-
129
- add_comfyui_directory_to_sys_path()
130
- add_extra_model_paths()
131
-
132
-
133
- def import_custom_nodes() -> None:
134
- """Find all custom nodes in the custom_nodes folder and add those node objects to NODE_CLASS_MAPPINGS
135
-
136
- This function sets up a new asyncio event loop, initializes the PromptServer,
137
- creates a PromptQueue, and initializes the custom nodes.
138
- """
139
- import asyncio
140
- import execution
141
- from nodes import init_extra_nodes
142
- import server
143
-
144
- # Creating a new event loop and setting it as the default loop
145
- loop = asyncio.new_event_loop()
146
- asyncio.set_event_loop(loop)
147
-
148
- # Creating an instance of PromptServer with the loop
149
- server_instance = server.PromptServer(loop)
150
- execution.PromptQueue(server_instance)
151
-
152
- # Initializing custom nodes
153
- # Запускаем корутину и ждём её завершения
154
- loop.run_until_complete(init_extra_nodes())
155
-
156
- import_custom_nodes()
157
- from nodes import NODE_CLASS_MAPPINGS
158
-
159
- # --- Глобальная загрузка моделей (один раз при старте) ---
160
- loadimage = NODE_CLASS_MAPPINGS["LoadImage"]()
161
- reactorfaceswap = NODE_CLASS_MAPPINGS["ReActorFaceSwap"]()
162
- saveimage = NODE_CLASS_MAPPINGS["SaveImage"]()
163
-
164
- #@spaces.GPU
165
- def generate_image(source_image, target_image, target_index, swap_model, face_restore_model, restore_strength):
166
- with torch.inference_mode():
167
- loadimage_2 = loadimage.load_image(image=source_image)
168
- loadimage_3 = loadimage.load_image(image=target_image)
169
-
170
- reactorfaceswap_76 = reactorfaceswap.execute(
171
- enabled=True,
172
- swap_model=swap_model, # Используем выбранную модель
173
- facedetection="YOLOv5l",
174
- face_restore_model=face_restore_model,
175
- face_restore_visibility=restore_strength,
176
- codeformer_weight=0.5,
177
- detect_gender_input="no",
178
- detect_gender_source="no",
179
- input_faces_index=str(target_index), # Преобразуем в строку
180
- source_faces_index="0",
181
- console_log_level=1,
182
- input_image=get_value_at_index(loadimage_3, 0),
183
- source_image=get_value_at_index(loadimage_2, 0),
184
- )
185
-
186
- saveimage_77 = saveimage.save_images(
187
- filename_prefix="ComfyUI",
188
- images=get_value_at_index(reactorfaceswap_76, 0),
189
- )
190
-
191
- saved_path = f"output/{saveimage_77['ui']['images'][0]['filename']}"
192
- return saved_path
193
-
194
- if __name__ == "__main__":
195
- with gr.Blocks() as app:
196
- with gr.Row():
197
- with gr.Column():
198
- # Вложенный Row для групп (группы расположены горизонтально)
199
- with gr.Row():
200
- # Первая группа
201
- with gr.Group():
202
- source_image = gr.Image(label="Source (Face)", type="filepath")
203
- swap_model = gr.Dropdown(
204
- choices=["inswapper_128.onnx", "hyperswap_1a_256.onnx", "hyperswap_1b_256.onnx", "hyperswap_1c_256.onnx"],
205
- value="hyperswap_1b_256.onnx",
206
- label="Swap Model"
207
- )
208
- face_restore_model = gr.Dropdown(
209
- choices=["none", "GPEN-BFR-512.onnx"],
210
- value="none",
211
- label="Face Restore Model"
212
- )
213
- restore_strength = gr.Slider(
214
- minimum=0,
215
- maximum=1,
216
- step=0.05,
217
- value=0.7,
218
- label="Face Restore Strength"
219
- )
220
-
221
- # Вторая группа
222
- with gr.Group():
223
- target_image = gr.Image(label="Target (Body)", type="filepath")
224
- target_index = gr.Dropdown(
225
- choices=[0, 1, 2, 3, 4],
226
- value=0,
227
- label="Target Face Index"
228
- )
229
- gr.Markdown("Index_0 = Largest Face. To switch for another target face - switch to Index_1, Index_2, e.t.c")
230
- generate_btn = gr.Button("Generate") # Кнопка генерации
231
-
232
- with gr.Column():
233
- output_image = gr.Image(label="Generated Image") # Вывод изображения
234
-
235
- with gr.Row():
236
- with gr.Column(scale=1):
237
- gr.Markdown("***Hyperswap_1b_256.onnx is the best (in most cases) - but sometimes model produce FAIL swap (do not do any swapping). It's known inner bug.")
238
- gr.Markdown("***Hyperswap models do not need Face Restorer - use it with None. Inswapper_128 need Face Restorer - use it with GPEN-BFR-512 at strenght 0.7-0.8.")
239
- gr.Markdown("*** This Space uses only CPU. You have unlimited usage in HF Spaces on CPU.")
240
- gr.Markdown("*** For avoiding queue - duplicate this space to your account (it's free). Top right corner - Three dots - Duplicate this Space. Make them Private. Enjoy!")
241
- gr.Markdown(
242
- "***ComfyUI Reactor Fast Face Swap Hyperswap running directly on Gradio. - "
243
- "[How to convert your any ComfyUI workflow to Gradio]"
244
- "(https://huggingface.co/blog/run-comfyui-workflows-on-spaces)"
245
- )
246
-
247
- # Связываем клик кнопки с функцией
248
- generate_btn.click(
249
- fn=generate_image,
250
- inputs=[source_image, target_image, target_index, swap_model, face_restore_model, restore_strength],
251
- outputs=[output_image]
252
- )
253
-
254
- app.launch(share=True)
 
1
+ import os
2
+ import torch
3
+ from comfy.model_management import CPUState # Импорт из того же файла
4
+
5
+ # Отключаем CUDA, чтобы избежать инициализации
6
+ os.environ["CUDA_VISIBLE_DEVICES"] = ""
7
+ os.environ["PYTORCH_CUDA_ALLOC_CONF"] = ""
8
+
9
+ # Принудительно устанавливаем CPU режим
10
+ import comfy.model_management
11
+ comfy.model_management.cpu_state = CPUState.CPU
12
+
13
+ import random
14
+ import sys
15
+ from typing import Sequence, Mapping, Any, Union
16
+ from PIL import Image
17
+ from huggingface_hub import hf_hub_download
18
+ import spaces
19
+
20
+ import subprocess, sys
21
+
22
+ import gradio
23
+ import gradio_client
24
+ import gradio as gr
25
+
26
+ print("gradio version:", gradio.__version__)
27
+ print("gradio_client version:", gradio_client.__version__)
28
+
29
+ hf_hub_download(repo_id="ezioruan/inswapper_128.onnx", filename="inswapper_128.onnx", local_dir="models/insightface")
30
+ hf_hub_download(repo_id="martintomov/comfy", filename="facerestore_models/GPEN-BFR-512.onnx", local_dir="models")
31
+
32
+ hf_hub_download(repo_id="facefusion/models-3.3.0", filename="hyperswap_1a_256.onnx", local_dir="models/hyperswap")
33
+ hf_hub_download(repo_id="facefusion/models-3.3.0", filename="hyperswap_1b_256.onnx", local_dir="models/hyperswap")
34
+ hf_hub_download(repo_id="facefusion/models-3.3.0", filename="hyperswap_1c_256.onnx", local_dir="models/hyperswap")
35
+
36
+ hf_hub_download(repo_id="martintomov/comfy", filename="facedetection/yolov5l-face.pth", local_dir="models")
37
+ ###hf_hub_download(repo_id="darkeril/collection", filename="detection_Resnet50_Final.pth", local_dir="models/facedetection")
38
+ hf_hub_download(repo_id="gmk123/GFPGAN", filename="parsing_parsenet.pth", local_dir="models/facedetection")
39
+
40
+ hf_hub_download(repo_id="MonsterMMORPG/tools", filename="1k3d68.onnx", local_dir="models/insightface/models/buffalo_l")
41
+ hf_hub_download(repo_id="MonsterMMORPG/tools", filename="2d106det.onnx", local_dir="models/insightface/models/buffalo_l")
42
+ hf_hub_download(repo_id="maze/faceX", filename="det_10g.onnx", local_dir="models/insightface/models/buffalo_l")
43
+ hf_hub_download(repo_id="typhoon01/aux_models", filename="genderage.onnx", local_dir="models/insightface/models/buffalo_l")
44
+ hf_hub_download(repo_id="maze/faceX", filename="w600k_r50.onnx", local_dir="models/insightface/models/buffalo_l")
45
+
46
+ hf_hub_download(repo_id="vladmandic/insightface-faceanalysis", filename="buffalo_l.zip", local_dir="models/insightface/models/buffalo_l")
47
+
48
+
49
+ def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
50
+ """Returns the value at the given index of a sequence or mapping.
51
+
52
+ If the object is a sequence (like list or string), returns the value at the given index.
53
+ If the object is a mapping (like a dictionary), returns the value at the index-th key.
54
+
55
+ Some return a dictionary, in these cases, we look for the "results" key
56
+
57
+ Args:
58
+ obj (Union[Sequence, Mapping]): The object to retrieve the value from.
59
+ index (int): The index of the value to retrieve.
60
+
61
+ Returns:
62
+ Any: The value at the given index.
63
+
64
+ Raises:
65
+ IndexError: If the index is out of bounds for the object and the object is not a mapping.
66
+ """
67
+ try:
68
+ return obj[index]
69
+ except KeyError:
70
+ return obj["result"][index]
71
+
72
+
73
+ def find_path(name: str, path: str = None) -> str:
74
+ """
75
+ Recursively looks at parent folders starting from the given path until it finds the given name.
76
+ Returns the path as a Path object if found, or None otherwise.
77
+ """
78
+ # If no path is given, use the current working directory
79
+ if path is None:
80
+ path = os.getcwd()
81
+
82
+ # Check if the current directory contains the name
83
+ if name in os.listdir(path):
84
+ path_name = os.path.join(path, name)
85
+ print(f"{name} found: {path_name}")
86
+ return path_name
87
+
88
+ # Get the parent directory
89
+ parent_directory = os.path.dirname(path)
90
+
91
+ # If the parent directory is the same as the current directory, we've reached the root and stop the search
92
+ if parent_directory == path:
93
+ return None
94
+
95
+ # Recursively call the function with the parent directory
96
+ return find_path(name, parent_directory)
97
+
98
+
99
+ def add_comfyui_directory_to_sys_path() -> None:
100
+ """
101
+ Add 'ComfyUI' to the sys.path
102
+ """
103
+ comfyui_path = find_path("ComfyUI")
104
+ if comfyui_path is not None and os.path.isdir(comfyui_path):
105
+ sys.path.append(comfyui_path)
106
+ print(f"'{comfyui_path}' added to sys.path")
107
+
108
+
109
+ def add_extra_model_paths() -> None:
110
+ """
111
+ Parse the optional extra_model_paths.yaml file and add the parsed paths to the sys.path.
112
+ """
113
+ try:
114
+ from main import load_extra_path_config
115
+ except ImportError:
116
+ print(
117
+ "Could not import load_extra_path_config from main.py. Looking in utils.extra_config instead."
118
+ )
119
+ from utils.extra_config import load_extra_path_config
120
+
121
+ extra_model_paths = find_path("extra_model_paths.yaml")
122
+
123
+ if extra_model_paths is not None:
124
+ load_extra_path_config(extra_model_paths)
125
+ else:
126
+ print("Could not find the extra_model_paths config file.")
127
+
128
+
129
+ add_comfyui_directory_to_sys_path()
130
+ add_extra_model_paths()
131
+
132
+
133
+ def import_custom_nodes() -> None:
134
+ """Find all custom nodes in the custom_nodes folder and add those node objects to NODE_CLASS_MAPPINGS
135
+
136
+ This function sets up a new asyncio event loop, initializes the PromptServer,
137
+ creates a PromptQueue, and initializes the custom nodes.
138
+ """
139
+ import asyncio
140
+ import execution
141
+ from nodes import init_extra_nodes
142
+ import server
143
+
144
+ # Creating a new event loop and setting it as the default loop
145
+ loop = asyncio.new_event_loop()
146
+ asyncio.set_event_loop(loop)
147
+
148
+ # Creating an instance of PromptServer with the loop
149
+ server_instance = server.PromptServer(loop)
150
+ execution.PromptQueue(server_instance)
151
+
152
+ # Initializing custom nodes
153
+ # Запускаем корутину и ждём её завершения
154
+ loop.run_until_complete(init_extra_nodes())
155
+
156
+ import_custom_nodes()
157
+ from nodes import NODE_CLASS_MAPPINGS
158
+
159
+ # --- Глобальная загрузка моделей (один раз при старте) ---
160
+ loadimage = NODE_CLASS_MAPPINGS["LoadImage"]()
161
+ reactorfaceswap = NODE_CLASS_MAPPINGS["ReActorFaceSwap"]()
162
+ saveimage = NODE_CLASS_MAPPINGS["SaveImage"]()
163
+
164
+ #@spaces.GPU
165
+ def generate_image(source_image, target_image, target_index, swap_model, face_restore_model, restore_strength):
166
+ with torch.inference_mode():
167
+ loadimage_2 = loadimage.load_image(image=source_image)
168
+ loadimage_3 = loadimage.load_image(image=target_image)
169
+
170
+ reactorfaceswap_76 = reactorfaceswap.execute(
171
+ enabled=True,
172
+ swap_model=swap_model, # Используем выбранную модель
173
+ facedetection="YOLOv5l",
174
+ face_restore_model=face_restore_model,
175
+ face_restore_visibility=restore_strength,
176
+ codeformer_weight=0.5,
177
+ detect_gender_input="no",
178
+ detect_gender_source="no",
179
+ input_faces_index=str(target_index), # Преобразуем в строку
180
+ source_faces_index="0",
181
+ console_log_level=1,
182
+ input_image=get_value_at_index(loadimage_3, 0),
183
+ source_image=get_value_at_index(loadimage_2, 0),
184
+ )
185
+
186
+ saveimage_77 = saveimage.save_images(
187
+ filename_prefix="ComfyUI",
188
+ images=get_value_at_index(reactorfaceswap_76, 0),
189
+ )
190
+
191
+ saved_path = f"output/{saveimage_77['ui']['images'][0]['filename']}"
192
+ return saved_path
193
+
194
+ if __name__ == "__main__":
195
+ with gr.Blocks() as app:
196
+ with gr.Row():
197
+ with gr.Column():
198
+ # Вложенный Row для групп (группы расположены горизонтально)
199
+ with gr.Row():
200
+ # Первая группа
201
+ with gr.Group():
202
+ source_image = gr.Image(label="Source (Face)", type="filepath")
203
+ swap_model = gr.Dropdown(
204
+ choices=["inswapper_128.onnx", "hyperswap_1a_256.onnx", "hyperswap_1b_256.onnx", "hyperswap_1c_256.onnx"],
205
+ value="hyperswap_1b_256.onnx",
206
+ label="Swap Model"
207
+ )
208
+ face_restore_model = gr.Dropdown(
209
+ choices=["none", "GPEN-BFR-512.onnx"],
210
+ value="none",
211
+ label="Face Restore Model"
212
+ )
213
+ restore_strength = gr.Slider(
214
+ minimum=0,
215
+ maximum=1,
216
+ step=0.05,
217
+ value=0.7,
218
+ label="Face Restore Strength"
219
+ )
220
+
221
+ # Вторая группа
222
+ with gr.Group():
223
+ target_image = gr.Image(label="Target (Body)", type="filepath")
224
+ target_index = gr.Dropdown(
225
+ choices=[0, 1, 2, 3, 4],
226
+ value=0,
227
+ label="Target Face Index"
228
+ )
229
+ gr.Markdown("Index_0 = Largest Face. To switch for another target face - switch to Index_1, Index_2, e.t.c")
230
+ generate_btn = gr.Button("Generate") # Кнопка генерации
231
+
232
+ with gr.Column():
233
+ output_image = gr.Image(label="Generated Image") # Вывод изображения
234
+
235
+ with gr.Row():
236
+ with gr.Column(scale=1):
237
+ gr.Markdown("***Hyperswap_1b_256.onnx is the best (in most cases) - but sometimes model produce FAIL swap (do not do any swapping). It's known inner bug.")
238
+ gr.Markdown("***Hyperswap models do not need Face Restorer - use it with None. Inswapper_128 need Face Restorer - use it with GPEN-BFR-512 at strength 0.7-0.8.")
239
+ gr.Markdown("*** This Space uses only CPU. You have unlimited usage in HF Spaces on CPU.")
240
+ gr.Markdown("*** For avoiding queue - duplicate this space to your account (it's free). Top right corner - Three dots - Duplicate this Space. Make them Private. Enjoy!")
241
+ gr.Markdown(
242
+ "***ComfyUI Reactor Fast Face Swap Hyperswap running directly on Gradio. - "
243
+ "[How to convert your any ComfyUI workflow to Gradio]"
244
+ "(https://huggingface.co/blog/run-comfyui-workflows-on-spaces)"
245
+ )
246
+
247
+ # Связываем клик кнопки с функцией
248
+ generate_btn.click(
249
+ fn=generate_image,
250
+ inputs=[source_image, target_image, target_index, swap_model, face_restore_model, restore_strength],
251
+ outputs=[output_image]
252
+ )
253
+
254
+ app.launch(share=True)