update app
Browse files
app.py
CHANGED
|
@@ -151,19 +151,29 @@ def process_gallery_images(images):
|
|
| 151 |
|
| 152 |
return pil_images
|
| 153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
def update_style_selection(evt: gr.SelectData):
|
| 155 |
-
"""Update selected style based on gallery click
|
| 156 |
selected_style = LORA_STYLES[evt.index]
|
| 157 |
|
| 158 |
-
if selected_style["title"] == "None":
|
| 159 |
-
info_text = "### Selected: None (FLUX.2-klein-9B) ✅"
|
| 160 |
-
else:
|
| 161 |
-
info_text = f"### Selected: {selected_style['title']} ✅"
|
| 162 |
-
|
| 163 |
# Get default prompt if available
|
| 164 |
default_prompt = selected_style.get("default_prompt", None)
|
| 165 |
|
| 166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
|
| 168 |
def get_image_count_info(images):
|
| 169 |
"""Return info about uploaded images"""
|
|
@@ -182,7 +192,7 @@ def get_image_count_info(images):
|
|
| 182 |
def infer(
|
| 183 |
input_images,
|
| 184 |
prompt,
|
| 185 |
-
|
| 186 |
seed=42,
|
| 187 |
randomize_seed=True,
|
| 188 |
guidance_scale=1.0,
|
|
@@ -201,10 +211,11 @@ def infer(
|
|
| 201 |
if not pil_images:
|
| 202 |
raise gr.Error("Could not process uploaded images.")
|
| 203 |
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
|
|
|
| 208 |
|
| 209 |
# Check if Face Swap is selected and validate image count
|
| 210 |
if selected_style["adapter_name"] == "face-swap":
|
|
@@ -272,15 +283,14 @@ def infer(
|
|
| 272 |
torch.cuda.empty_cache()
|
| 273 |
|
| 274 |
@spaces.GPU
|
| 275 |
-
def infer_example(input_images, prompt,
|
|
|
|
| 276 |
if not input_images:
|
| 277 |
return None, 0
|
| 278 |
|
| 279 |
-
# Handle both single image path and list of paths for examples
|
| 280 |
if isinstance(input_images, str):
|
| 281 |
input_images = [input_images]
|
| 282 |
elif isinstance(input_images, list) and len(input_images) > 0:
|
| 283 |
-
# If it's already a list, keep it as is
|
| 284 |
pass
|
| 285 |
else:
|
| 286 |
return None, 0
|
|
@@ -288,7 +298,7 @@ def infer_example(input_images, prompt, style_index):
|
|
| 288 |
image, seed = infer(
|
| 289 |
input_images=input_images,
|
| 290 |
prompt=prompt,
|
| 291 |
-
|
| 292 |
seed=0,
|
| 293 |
randomize_seed=True,
|
| 294 |
guidance_scale=1.0,
|
|
@@ -308,7 +318,7 @@ with gr.Blocks() as demo:
|
|
| 308 |
gr.Markdown("# **FLUX.2-Klein-LoRA-Studio**", elem_id="main-title")
|
| 309 |
gr.Markdown("Perform diverse image edits using specialized [LoRAs](https://huggingface.co/models?other=base_model:adapter:black-forest-labs/FLUX.2-klein-9B) adapters for the [FLUX.2-Klein-Distilled](https://huggingface.co/black-forest-labs/FLUX.2-klein-9B) model.")
|
| 310 |
|
| 311 |
-
|
| 312 |
|
| 313 |
with gr.Row(equal_height=True):
|
| 314 |
with gr.Column():
|
|
@@ -335,7 +345,7 @@ with gr.Blocks() as demo:
|
|
| 335 |
with gr.Accordion("Advanced Settings", open=False, visible=False):
|
| 336 |
seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
|
| 337 |
randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
|
| 338 |
-
guidance_scale = gr.Slider(label="Guidance Scale", minimum=0.0, maximum=10.0, step=0.1, value=1.0)
|
| 339 |
steps = gr.Slider(label="Steps", minimum=1, maximum=50, value=4, step=1)
|
| 340 |
|
| 341 |
with gr.Column():
|
|
@@ -354,12 +364,19 @@ with gr.Blocks() as demo:
|
|
| 354 |
|
| 355 |
gr.Examples(
|
| 356 |
examples=[
|
| 357 |
-
|
| 358 |
-
[["examples/
|
| 359 |
-
|
| 360 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 361 |
],
|
| 362 |
-
inputs=[input_images, prompt,
|
| 363 |
outputs=[output_image, used_seed],
|
| 364 |
fn=infer_example,
|
| 365 |
cache_examples=False,
|
|
@@ -368,7 +385,6 @@ with gr.Blocks() as demo:
|
|
| 368 |
|
| 369 |
gr.Markdown("[*](https://huggingface.co/black-forest-labs/FLUX.2-klein-9B)This is still an experimental Space for FLUX.2-Klein-9B. More adapters will be added soon.")
|
| 370 |
|
| 371 |
-
# Update image count info when gallery changes
|
| 372 |
input_images.change(
|
| 373 |
fn=get_image_count_info,
|
| 374 |
inputs=[input_images],
|
|
@@ -376,12 +392,18 @@ with gr.Blocks() as demo:
|
|
| 376 |
|
| 377 |
style_gallery.select(
|
| 378 |
update_style_selection,
|
| 379 |
-
outputs=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 380 |
)
|
| 381 |
|
| 382 |
run_button.click(
|
| 383 |
fn=infer,
|
| 384 |
-
inputs=[input_images, prompt,
|
| 385 |
outputs=[output_image, used_seed]
|
| 386 |
)
|
| 387 |
|
|
|
|
| 151 |
|
| 152 |
return pil_images
|
| 153 |
|
| 154 |
+
def get_style_config(name):
|
| 155 |
+
"""Retrieve style configuration by title."""
|
| 156 |
+
for style in LORA_STYLES:
|
| 157 |
+
if style["title"] == name:
|
| 158 |
+
return style
|
| 159 |
+
return LORA_STYLES[0] # Default to None if not found
|
| 160 |
+
|
| 161 |
def update_style_selection(evt: gr.SelectData):
|
| 162 |
+
"""Update selected style based on gallery click"""
|
| 163 |
selected_style = LORA_STYLES[evt.index]
|
| 164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
# Get default prompt if available
|
| 166 |
default_prompt = selected_style.get("default_prompt", None)
|
| 167 |
|
| 168 |
+
# Return name (for State) and prompt
|
| 169 |
+
return selected_style["title"], default_prompt if default_prompt else gr.update()
|
| 170 |
+
|
| 171 |
+
def update_info_text(style_name):
|
| 172 |
+
"""Updates the info text when the style name changes (via Gallery or Example)"""
|
| 173 |
+
if style_name == "None" or not style_name:
|
| 174 |
+
return "### Selected: None (FLUX.2-klein-9B) ✅"
|
| 175 |
+
else:
|
| 176 |
+
return f"### Selected: {style_name} ✅"
|
| 177 |
|
| 178 |
def get_image_count_info(images):
|
| 179 |
"""Return info about uploaded images"""
|
|
|
|
| 192 |
def infer(
|
| 193 |
input_images,
|
| 194 |
prompt,
|
| 195 |
+
selected_style_name,
|
| 196 |
seed=42,
|
| 197 |
randomize_seed=True,
|
| 198 |
guidance_scale=1.0,
|
|
|
|
| 211 |
if not pil_images:
|
| 212 |
raise gr.Error("Could not process uploaded images.")
|
| 213 |
|
| 214 |
+
# Resolve Style Config from Name
|
| 215 |
+
if selected_style_name is None:
|
| 216 |
+
selected_style_name = "None"
|
| 217 |
+
|
| 218 |
+
selected_style = get_style_config(selected_style_name)
|
| 219 |
|
| 220 |
# Check if Face Swap is selected and validate image count
|
| 221 |
if selected_style["adapter_name"] == "face-swap":
|
|
|
|
| 283 |
torch.cuda.empty_cache()
|
| 284 |
|
| 285 |
@spaces.GPU
|
| 286 |
+
def infer_example(input_images, prompt, style_name):
|
| 287 |
+
"""Wrapper for examples to handle paths and names"""
|
| 288 |
if not input_images:
|
| 289 |
return None, 0
|
| 290 |
|
|
|
|
| 291 |
if isinstance(input_images, str):
|
| 292 |
input_images = [input_images]
|
| 293 |
elif isinstance(input_images, list) and len(input_images) > 0:
|
|
|
|
| 294 |
pass
|
| 295 |
else:
|
| 296 |
return None, 0
|
|
|
|
| 298 |
image, seed = infer(
|
| 299 |
input_images=input_images,
|
| 300 |
prompt=prompt,
|
| 301 |
+
selected_style_name=style_name,
|
| 302 |
seed=0,
|
| 303 |
randomize_seed=True,
|
| 304 |
guidance_scale=1.0,
|
|
|
|
| 318 |
gr.Markdown("# **FLUX.2-Klein-LoRA-Studio**", elem_id="main-title")
|
| 319 |
gr.Markdown("Perform diverse image edits using specialized [LoRAs](https://huggingface.co/models?other=base_model:adapter:black-forest-labs/FLUX.2-klein-9B) adapters for the [FLUX.2-Klein-Distilled](https://huggingface.co/black-forest-labs/FLUX.2-klein-9B) model.")
|
| 320 |
|
| 321 |
+
selected_style_name = gr.State("None")
|
| 322 |
|
| 323 |
with gr.Row(equal_height=True):
|
| 324 |
with gr.Column():
|
|
|
|
| 345 |
with gr.Accordion("Advanced Settings", open=False, visible=False):
|
| 346 |
seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
|
| 347 |
randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
|
| 348 |
+
guidance_scale = gr.Slider(label="Guidance Scale", minimum=0.0, maximum=10.0, step=0.1, value=1.0)
|
| 349 |
steps = gr.Slider(label="Steps", minimum=1, maximum=50, value=4, step=1)
|
| 350 |
|
| 351 |
with gr.Column():
|
|
|
|
| 364 |
|
| 365 |
gr.Examples(
|
| 366 |
examples=[
|
| 367 |
+
# Example 1: None
|
| 368 |
+
[["examples/2.jpg"], "Relight the image to remove all existing lighting conditions and replace them with neutral, uniform illumination. Apply soft, evenly distributed lighting with no directional shadows, no harsh highlights, and no dramatic contrast. Maintain the original identity of all subjects exactly—preserve facial structure, skin tone, proportions, expressions, hair, clothing, and textures. Do not alter pose, camera angle, background geometry, or image composition. Lighting should appear balanced, and studio-neutral, similar to diffuse overcast or a soft lightbox setup. Ensure consistent exposure across the entire image with realistic depth and subtle shading only where necessary for form.", "None"],
|
| 369 |
+
|
| 370 |
+
# Example 2: Klein-Delight-Style
|
| 371 |
+
[["examples/1.jpg"], "cinematic polaroid with soft grain subtle vignette gentle lighting white frame handwritten photographed by prithivMLmods preserving realistic texture and details", "Klein-Delight-Style"],
|
| 372 |
+
|
| 373 |
+
# Example 3: Klein-Delight-Style (Multiple images scenario)
|
| 374 |
+
[["examples/1.jpg", "examples/2.jpg"], "Apply the style from image 2 to image 1, preserving the subject's identity.", "Klein-Delight-Style"],
|
| 375 |
+
|
| 376 |
+
# Example 4: Best-Face-Swap
|
| 377 |
+
[["examples/face1.jpg", "examples/face2.jpg"], FACE_SWAP_PROMPT, "Best-Face-Swap"],
|
| 378 |
],
|
| 379 |
+
inputs=[input_images, prompt, selected_style_name],
|
| 380 |
outputs=[output_image, used_seed],
|
| 381 |
fn=infer_example,
|
| 382 |
cache_examples=False,
|
|
|
|
| 385 |
|
| 386 |
gr.Markdown("[*](https://huggingface.co/black-forest-labs/FLUX.2-klein-9B)This is still an experimental Space for FLUX.2-Klein-9B. More adapters will be added soon.")
|
| 387 |
|
|
|
|
| 388 |
input_images.change(
|
| 389 |
fn=get_image_count_info,
|
| 390 |
inputs=[input_images],
|
|
|
|
| 392 |
|
| 393 |
style_gallery.select(
|
| 394 |
update_style_selection,
|
| 395 |
+
outputs=[selected_style_name, prompt]
|
| 396 |
+
)
|
| 397 |
+
|
| 398 |
+
selected_style_name.change(
|
| 399 |
+
fn=update_info_text,
|
| 400 |
+
inputs=[selected_style_name],
|
| 401 |
+
outputs=[selected_style_info]
|
| 402 |
)
|
| 403 |
|
| 404 |
run_button.click(
|
| 405 |
fn=infer,
|
| 406 |
+
inputs=[input_images, prompt, selected_style_name, seed, randomize_seed, guidance_scale, steps],
|
| 407 |
outputs=[output_image, used_seed]
|
| 408 |
)
|
| 409 |
|