Spaces:
Running
on
Zero
Running
on
Zero
Rishi Desai
commited on
Commit
·
3e1c3ec
1
Parent(s):
e8c9f0d
extracted model loaders
Browse files- FaceEnhancementProd.py +70 -77
- README.md +13 -25
FaceEnhancementProd.py
CHANGED
@@ -7,6 +7,9 @@ import torch
|
|
7 |
BASE_PATH = "./"
|
8 |
COMFYUI_PATH = os.path.join(BASE_PATH, "ComfyUI")
|
9 |
|
|
|
|
|
|
|
10 |
def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
|
11 |
"""Returns the value at the given index of a sequence or mapping.
|
12 |
|
@@ -125,23 +128,79 @@ from nodes import (
|
|
125 |
ControlNetApplyAdvanced,
|
126 |
)
|
127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
def main(
|
130 |
face_image: str,
|
131 |
input_image: str,
|
132 |
output_image: str,
|
133 |
dist_image: str = None,
|
134 |
-
positive_prompt: str = ""
|
|
|
135 |
):
|
136 |
-
|
|
|
|
|
137 |
with torch.inference_mode():
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
|
146 |
cliptextencode = CLIPTextEncode()
|
147 |
cliptextencode_23 = cliptextencode.encode(
|
@@ -153,9 +212,6 @@ def main(
|
|
153 |
|
154 |
loadimage_40 = loadimage.load_image(image=input_image)
|
155 |
|
156 |
-
vaeloader = VAELoader()
|
157 |
-
vaeloader_95 = vaeloader.load_vae(vae_name="ae.safetensors")
|
158 |
-
|
159 |
vaeencode = VAEEncode()
|
160 |
vaeencode_35 = vaeencode.encode(
|
161 |
pixels=get_value_at_index(loadimage_40, 0),
|
@@ -169,37 +225,9 @@ def main(
|
|
169 |
text=positive_prompt, clip=get_value_at_index(dualcliploader_94, 0)
|
170 |
)
|
171 |
|
172 |
-
pulidfluxmodelloader = NODE_CLASS_MAPPINGS["PulidFluxModelLoader"]()
|
173 |
-
pulidfluxmodelloader_44 = pulidfluxmodelloader.load_model(
|
174 |
-
pulid_file="pulid_flux_v0.9.1.safetensors"
|
175 |
-
)
|
176 |
-
|
177 |
-
pulidfluxevacliploader = NODE_CLASS_MAPPINGS["PulidFluxEvaClipLoader"]()
|
178 |
-
pulidfluxevacliploader_45 = pulidfluxevacliploader.load_eva_clip()
|
179 |
-
|
180 |
-
pulidfluxinsightfaceloader = NODE_CLASS_MAPPINGS["PulidFluxInsightFaceLoader"]()
|
181 |
-
pulidfluxinsightfaceloader_46 = pulidfluxinsightfaceloader.load_insightface(
|
182 |
-
provider="CUDA"
|
183 |
-
)
|
184 |
-
|
185 |
-
controlnetloader = ControlNetLoader()
|
186 |
-
controlnetloader_49 = controlnetloader.load_controlnet(
|
187 |
-
control_net_name="Flux_Dev_ControlNet_Union_Pro_ShakkerLabs.safetensors"
|
188 |
-
)
|
189 |
-
|
190 |
ksamplerselect = NODE_CLASS_MAPPINGS["KSamplerSelect"]()
|
191 |
ksamplerselect_50 = ksamplerselect.get_sampler(sampler_name="euler")
|
192 |
|
193 |
-
unetloader = UNETLoader()
|
194 |
-
unetloader_93 = unetloader.load_unet(
|
195 |
-
unet_name="flux1-dev.safetensors", weight_dtype="default"
|
196 |
-
)
|
197 |
-
|
198 |
-
faceanalysismodels = NODE_CLASS_MAPPINGS["FaceAnalysisModels"]()
|
199 |
-
faceanalysismodels_118 = faceanalysismodels.load_models(
|
200 |
-
library="insightface", provider="CUDA"
|
201 |
-
)
|
202 |
-
|
203 |
applypulidflux = NODE_CLASS_MAPPINGS["ApplyPulidFlux"]()
|
204 |
setunioncontrolnettype = NODE_CLASS_MAPPINGS["SetUnionControlNetType"]()
|
205 |
controlnetapplyadvanced = ControlNetApplyAdvanced()
|
@@ -269,24 +297,7 @@ def main(
|
|
269 |
vae=get_value_at_index(vaeloader_95, 0),
|
270 |
)
|
271 |
|
272 |
-
faceembeddistance_117 = faceembeddistance.analize(
|
273 |
-
similarity_metric="cosine",
|
274 |
-
filter_thresh=100,
|
275 |
-
filter_best=0,
|
276 |
-
generate_image_overlay=True,
|
277 |
-
analysis_models=get_value_at_index(faceanalysismodels_118, 0),
|
278 |
-
reference=get_value_at_index(loadimage_24, 0),
|
279 |
-
image=get_value_at_index(vaedecode_114, 0),
|
280 |
-
)
|
281 |
-
|
282 |
-
display_any_rgthree_121 = display_any_rgthree.main(
|
283 |
-
source=get_value_at_index(faceembeddistance_117, 1)
|
284 |
-
)
|
285 |
-
|
286 |
-
# Save using direct image saving
|
287 |
save_comfy_images(get_value_at_index(vaedecode_114, 0), [output_image])
|
288 |
-
if dist_image:
|
289 |
-
save_comfy_images(get_value_at_index(faceembeddistance_117, 0), [dist_image])
|
290 |
|
291 |
|
292 |
def save_comfy_images(images, output_dirs):
|
@@ -307,26 +318,8 @@ def save_comfy_images(images, output_dirs):
|
|
307 |
|
308 |
|
309 |
def enhance_face(face_image: str, input_image: str, output_image: str, dist_image: str = None, positive_prompt: str = ""):
|
|
|
310 |
main(face_image, input_image, output_image, dist_image, positive_prompt)
|
311 |
|
312 |
if __name__ == "__main__":
|
313 |
-
|
314 |
-
|
315 |
-
if len(sys.argv) < 4:
|
316 |
-
print("Usage: python FaceEnhancementProd.py face_image input_image output_image [dist_image] [positive_prompt]")
|
317 |
-
sys.exit(1)
|
318 |
-
|
319 |
-
face_image = sys.argv[1]
|
320 |
-
input_image = sys.argv[2]
|
321 |
-
output_image = sys.argv[3]
|
322 |
-
|
323 |
-
dist_image = None
|
324 |
-
positive_prompt = ""
|
325 |
-
|
326 |
-
if len(sys.argv) > 4:
|
327 |
-
dist_image = sys.argv[4]
|
328 |
-
|
329 |
-
if len(sys.argv) > 5:
|
330 |
-
positive_prompt = sys.argv[5]
|
331 |
-
|
332 |
-
main(face_image, input_image, output_image, dist_image, positive_prompt)
|
|
|
7 |
BASE_PATH = "./"
|
8 |
COMFYUI_PATH = os.path.join(BASE_PATH, "ComfyUI")
|
9 |
|
10 |
+
# Declare models as a global variable at the top of the script
|
11 |
+
models = None
|
12 |
+
|
13 |
def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
|
14 |
"""Returns the value at the given index of a sequence or mapping.
|
15 |
|
|
|
128 |
ControlNetApplyAdvanced,
|
129 |
)
|
130 |
|
131 |
+
@torch.inference_mode()
|
132 |
+
def load_models():
|
133 |
+
dualcliploader = DualCLIPLoader()
|
134 |
+
dualcliploader_94 = dualcliploader.load_clip(
|
135 |
+
clip_name1="t5xxl_fp16.safetensors",
|
136 |
+
clip_name2="clip_l.safetensors",
|
137 |
+
type="flux",
|
138 |
+
device="default",
|
139 |
+
)
|
140 |
+
|
141 |
+
vaeloader = VAELoader()
|
142 |
+
vaeloader_95 = vaeloader.load_vae(vae_name="ae.safetensors")
|
143 |
+
|
144 |
+
pulidfluxmodelloader = NODE_CLASS_MAPPINGS["PulidFluxModelLoader"]()
|
145 |
+
pulidfluxmodelloader_44 = pulidfluxmodelloader.load_model(
|
146 |
+
pulid_file="pulid_flux_v0.9.1.safetensors"
|
147 |
+
)
|
148 |
+
|
149 |
+
pulidfluxevacliploader = NODE_CLASS_MAPPINGS["PulidFluxEvaClipLoader"]()
|
150 |
+
pulidfluxevacliploader_45 = pulidfluxevacliploader.load_eva_clip()
|
151 |
+
|
152 |
+
pulidfluxinsightfaceloader = NODE_CLASS_MAPPINGS["PulidFluxInsightFaceLoader"]()
|
153 |
+
pulidfluxinsightfaceloader_46 = pulidfluxinsightfaceloader.load_insightface(
|
154 |
+
provider="CUDA"
|
155 |
+
)
|
156 |
+
|
157 |
+
controlnetloader = ControlNetLoader()
|
158 |
+
controlnetloader_49 = controlnetloader.load_controlnet(
|
159 |
+
control_net_name="Flux_Dev_ControlNet_Union_Pro_ShakkerLabs.safetensors"
|
160 |
+
)
|
161 |
+
|
162 |
+
unetloader = UNETLoader()
|
163 |
+
unetloader_93 = unetloader.load_unet(
|
164 |
+
unet_name="flux1-dev.safetensors", weight_dtype="default"
|
165 |
+
)
|
166 |
+
|
167 |
+
return {
|
168 |
+
"dualcliploader_94": dualcliploader_94,
|
169 |
+
"vaeloader_95": vaeloader_95,
|
170 |
+
"pulidfluxmodelloader_44": pulidfluxmodelloader_44,
|
171 |
+
"pulidfluxevacliploader_45": pulidfluxevacliploader_45,
|
172 |
+
"pulidfluxinsightfaceloader_46": pulidfluxinsightfaceloader_46,
|
173 |
+
"controlnetloader_49": controlnetloader_49,
|
174 |
+
"unetloader_93": unetloader_93
|
175 |
+
}
|
176 |
+
|
177 |
+
def initialize_models():
|
178 |
+
global models
|
179 |
+
if models is None:
|
180 |
+
import_custom_nodes() # Ensure NODE_CLASS_MAPPINGS is initialized
|
181 |
+
models = load_models()
|
182 |
+
|
183 |
+
initialize_models()
|
184 |
|
185 |
def main(
|
186 |
face_image: str,
|
187 |
input_image: str,
|
188 |
output_image: str,
|
189 |
dist_image: str = None,
|
190 |
+
positive_prompt: str = "",
|
191 |
+
# models: dict = None
|
192 |
):
|
193 |
+
global models
|
194 |
+
if models is None:
|
195 |
+
raise ValueError("Models must be initialized before calling main(). Call initialize_models() first.")
|
196 |
with torch.inference_mode():
|
197 |
+
dualcliploader_94 = models["dualcliploader_94"]
|
198 |
+
vaeloader_95 = models["vaeloader_95"]
|
199 |
+
pulidfluxmodelloader_44 = models["pulidfluxmodelloader_44"]
|
200 |
+
pulidfluxevacliploader_45 = models["pulidfluxevacliploader_45"]
|
201 |
+
pulidfluxinsightfaceloader_46 = models["pulidfluxinsightfaceloader_46"]
|
202 |
+
controlnetloader_49 = models["controlnetloader_49"]
|
203 |
+
unetloader_93 = models["unetloader_93"]
|
204 |
|
205 |
cliptextencode = CLIPTextEncode()
|
206 |
cliptextencode_23 = cliptextencode.encode(
|
|
|
212 |
|
213 |
loadimage_40 = loadimage.load_image(image=input_image)
|
214 |
|
|
|
|
|
|
|
215 |
vaeencode = VAEEncode()
|
216 |
vaeencode_35 = vaeencode.encode(
|
217 |
pixels=get_value_at_index(loadimage_40, 0),
|
|
|
225 |
text=positive_prompt, clip=get_value_at_index(dualcliploader_94, 0)
|
226 |
)
|
227 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
228 |
ksamplerselect = NODE_CLASS_MAPPINGS["KSamplerSelect"]()
|
229 |
ksamplerselect_50 = ksamplerselect.get_sampler(sampler_name="euler")
|
230 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
applypulidflux = NODE_CLASS_MAPPINGS["ApplyPulidFlux"]()
|
232 |
setunioncontrolnettype = NODE_CLASS_MAPPINGS["SetUnionControlNetType"]()
|
233 |
controlnetapplyadvanced = ControlNetApplyAdvanced()
|
|
|
297 |
vae=get_value_at_index(vaeloader_95, 0),
|
298 |
)
|
299 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
300 |
save_comfy_images(get_value_at_index(vaedecode_114, 0), [output_image])
|
|
|
|
|
301 |
|
302 |
|
303 |
def save_comfy_images(images, output_dirs):
|
|
|
318 |
|
319 |
|
320 |
def enhance_face(face_image: str, input_image: str, output_image: str, dist_image: str = None, positive_prompt: str = ""):
|
321 |
+
initialize_models() # Ensure models are loaded
|
322 |
main(face_image, input_image, output_image, dist_image, positive_prompt)
|
323 |
|
324 |
if __name__ == "__main__":
|
325 |
+
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
README.md
CHANGED
@@ -5,7 +5,7 @@ Enhancing faces in AI generated images.
|
|
5 |
|
6 |
### Prerequisites
|
7 |
- Python 3.8 or higher
|
8 |
-
- At least 50GB of free disk space
|
9 |
|
10 |
### Setup
|
11 |
|
@@ -20,20 +20,16 @@ Enhancing faces in AI generated images.
|
|
20 |
```
|
21 |
export HF_HOME=/path/to/your/huggingface_cache
|
22 |
```
|
23 |
-
This
|
24 |
|
25 |
-
3. Create and activate a virtual environment:
|
26 |
```
|
27 |
python -m venv venv
|
28 |
source venv/bin/activate
|
|
|
29 |
```
|
30 |
|
31 |
-
4.
|
32 |
-
```
|
33 |
-
pip install -r requirements.txt
|
34 |
-
```
|
35 |
-
|
36 |
-
5. Run the installation script:
|
37 |
```
|
38 |
python install.py
|
39 |
```
|
@@ -56,30 +52,22 @@ These API keys are required for certain features of the application to work prop
|
|
56 |
|
57 |
# Face Enhancement Gradio Demo
|
58 |
|
59 |
-
A web interface for the face enhancement workflow using Gradio.
|
60 |
-
|
61 |
-
## Features
|
62 |
-
|
63 |
-
- Simple web interface for face enhancement
|
64 |
-
- Upload input image and reference face image
|
65 |
-
- Queue system to process jobs sequentially on a single GPU
|
66 |
-
- Approximately 60 seconds processing time per image
|
67 |
|
68 |
## Setup
|
69 |
|
70 |
-
1.
|
71 |
|
72 |
```bash
|
73 |
-
|
74 |
```
|
75 |
|
76 |
-
2.
|
77 |
-
|
78 |
```bash
|
79 |
-
|
80 |
```
|
81 |
|
82 |
-
3.
|
83 |
|
84 |
## Usage
|
85 |
|
@@ -91,6 +79,6 @@ python gradio_demo.py
|
|
91 |
|
92 |
## Notes
|
93 |
|
94 |
-
- The demo
|
95 |
-
- Processing takes approximately 60 seconds per image
|
96 |
- Temporary files are created during processing and cleaned up afterward
|
|
|
5 |
|
6 |
### Prerequisites
|
7 |
- Python 3.8 or higher
|
8 |
+
- At least 50GB of free disk space
|
9 |
|
10 |
### Setup
|
11 |
|
|
|
20 |
```
|
21 |
export HF_HOME=/path/to/your/huggingface_cache
|
22 |
```
|
23 |
+
This is where models will be downloaded and then symlinked to ComfyUI.
|
24 |
|
25 |
+
3. Create and activate a virtual environment with dependencies:
|
26 |
```
|
27 |
python -m venv venv
|
28 |
source venv/bin/activate
|
29 |
+
python -m pip install -r requirements.txt
|
30 |
```
|
31 |
|
32 |
+
4. Run the installation script:
|
|
|
|
|
|
|
|
|
|
|
33 |
```
|
34 |
python install.py
|
35 |
```
|
|
|
52 |
|
53 |
# Face Enhancement Gradio Demo
|
54 |
|
55 |
+
A web interface for the face enhancement workflow using Gradio. Between 45-60 seconds processing time per image.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
|
57 |
## Setup
|
58 |
|
59 |
+
1.
|
60 |
|
61 |
```bash
|
62 |
+
python gradio_demo.py
|
63 |
```
|
64 |
|
65 |
+
2. Port-forwarding
|
|
|
66 |
```bash
|
67 |
+
ssh -L 7860:localhost:7860 root@[IP_ADDRESS] -p [RUNPOD_PORT] -i ~/.ssh/[PRIVATE_KEY_NAME]
|
68 |
```
|
69 |
|
70 |
+
3. Go to http://localhost:7860
|
71 |
|
72 |
## Usage
|
73 |
|
|
|
79 |
|
80 |
## Notes
|
81 |
|
82 |
+
- The demo runs a ComfyUI server ephemerally
|
83 |
+
- Processing takes approximately 45-60 seconds per image
|
84 |
- Temporary files are created during processing and cleaned up afterward
|