Spaces:
Paused
Paused
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
|