Spaces:
Running
on
Zero
Running
on
Zero
Update app_local.py
Browse files- app_local.py +77 -23
app_local.py
CHANGED
|
@@ -84,6 +84,21 @@ Please provide the rewritten instruction in a clean `json` format as:
|
|
| 84 |
'''
|
| 85 |
|
| 86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
def extract_json_response(model_output: str) -> str:
|
| 88 |
"""Extract rewritten instruction from potentially messy JSON output"""
|
| 89 |
# Remove code block markers first
|
|
@@ -254,10 +269,8 @@ def infer(
|
|
| 254 |
if device == "cuda":
|
| 255 |
torch.cuda.empty_cache()
|
| 256 |
gc.collect()
|
| 257 |
-
|
| 258 |
original_prompt = prompt
|
| 259 |
prompt_info = ""
|
| 260 |
-
|
| 261 |
# Handle prompt rewriting
|
| 262 |
if rewrite_prompt:
|
| 263 |
try:
|
|
@@ -295,47 +308,88 @@ def infer(
|
|
| 295 |
f"</div>"
|
| 296 |
)
|
| 297 |
|
| 298 |
-
#
|
| 299 |
-
|
| 300 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
|
| 302 |
try:
|
| 303 |
-
# Generate images
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 313 |
|
| 314 |
# Clear cache after generation
|
| 315 |
if device == "cuda":
|
| 316 |
torch.cuda.empty_cache()
|
| 317 |
gc.collect()
|
| 318 |
-
|
| 319 |
-
return edited_images, seed_val, prompt_info
|
| 320 |
except Exception as e:
|
| 321 |
# Clear cache on error
|
| 322 |
if device == "cuda":
|
| 323 |
torch.cuda.empty_cache()
|
| 324 |
gc.collect()
|
| 325 |
gr.Error(f"Image generation failed: {str(e)}")
|
| 326 |
-
return [],
|
| 327 |
f"<div style='margin:10px; padding:15px; border-radius:8px; border-left:4px solid #dd2c00; background: #fef5f5'>"
|
| 328 |
f"<h4 style='margin-top: 0;'>⚠️ Processing Error</h4>"
|
| 329 |
f"<p>{str(e)[:200]}</p>"
|
| 330 |
f"</div>"
|
| 331 |
)
|
| 332 |
-
|
| 333 |
-
with gr.Blocks(title="Qwen Image
|
| 334 |
gr.Markdown("""
|
| 335 |
<div style="text-align: center; background: linear-gradient(to right, #3a7bd5, #00d2ff); color: white; padding: 20px; border-radius: 8px;">
|
| 336 |
<h1 style="margin-bottom: 5px;">⚡️ Qwen-Image-Edit Lightning</h1>
|
| 337 |
-
<p>✨ 8-step inferencing with lightx2v's LoRA
|
| 338 |
-
<p>📝 Local Prompt Enhancement</p>
|
| 339 |
</div>
|
| 340 |
""")
|
| 341 |
|
|
@@ -399,7 +453,7 @@ with gr.Blocks(title="Qwen Image Editor Fast") as demo:
|
|
| 399 |
minimum=1,
|
| 400 |
maximum=4,
|
| 401 |
step=1,
|
| 402 |
-
value=
|
| 403 |
)
|
| 404 |
|
| 405 |
# Output Column
|
|
|
|
| 84 |
'''
|
| 85 |
|
| 86 |
|
| 87 |
+
def add_noise_to_image(pil_image, noise_level=0.02):
|
| 88 |
+
"""Add slight noise to image to create variation in outputs"""
|
| 89 |
+
try:
|
| 90 |
+
img_array = np.array(pil_image).astype(np.float32) / 255.0
|
| 91 |
+
noise = np.random.normal(0, noise_level, img # Clip values to valid range
|
| 92 |
+
noisy_array = np.clip(noisy_array, 0, 1)
|
| 93 |
+
|
| 94 |
+
# Convert back to PIL
|
| 95 |
+
noisy_array = (noisy_array * 255).astype(np.uint8)
|
| 96 |
+
return Image.fromarray(noisy_array)
|
| 97 |
+
except Exception as e:
|
| 98 |
+
print(f"Warning: Could not add noise to image: {e}")
|
| 99 |
+
return pil_image # Return original if noise addition fails
|
| 100 |
+
|
| 101 |
+
|
| 102 |
def extract_json_response(model_output: str) -> str:
|
| 103 |
"""Extract rewritten instruction from potentially messy JSON output"""
|
| 104 |
# Remove code block markers first
|
|
|
|
| 269 |
if device == "cuda":
|
| 270 |
torch.cuda.empty_cache()
|
| 271 |
gc.collect()
|
|
|
|
| 272 |
original_prompt = prompt
|
| 273 |
prompt_info = ""
|
|
|
|
| 274 |
# Handle prompt rewriting
|
| 275 |
if rewrite_prompt:
|
| 276 |
try:
|
|
|
|
| 308 |
f"</div>"
|
| 309 |
)
|
| 310 |
|
| 311 |
+
# Add noise function
|
| 312 |
+
def add_noise_to_image(pil_image, noise_level=0.02):
|
| 313 |
+
"""Add slight noise to image to create variation in outputs"""
|
| 314 |
+
try:
|
| 315 |
+
img_array = np.array(pil_image).astype(np.float32) / 255.0
|
| 316 |
+
noise = np.random.normal(0, noise_level, img_array.shape)
|
| 317 |
+
noisy_array = img_array + noise
|
| 318 |
+
# Clip values to valid range
|
| 319 |
+
noisy_array = np.clip(noisy_array, 0, 1)
|
| 320 |
+
# Convert back to PIL
|
| 321 |
+
noisy_array = (noisy_array * 255).astype(np.uint8)
|
| 322 |
+
return Image.fromarray(noisy_array)
|
| 323 |
+
except Exception as e:
|
| 324 |
+
print(f"Warning: Could not add noise to image: {e}")
|
| 325 |
+
return pil_image # Return original if noise addition fails
|
| 326 |
+
|
| 327 |
+
# Set base seed for reproducibility
|
| 328 |
+
base_seed = seed if not randomize_seed else random.randint(0, MAX_SEED)
|
| 329 |
|
| 330 |
try:
|
| 331 |
+
# Generate images with variation for batch mode
|
| 332 |
+
if num_images_per_prompt > 1:
|
| 333 |
+
edited_images = []
|
| 334 |
+
for i in range(num_images_per_prompt):
|
| 335 |
+
# Create unique seed for each image
|
| 336 |
+
generator = torch.Generator(device=device).manual_seed(base_seed + i*1000)
|
| 337 |
+
|
| 338 |
+
# Add slight noise to the image for variation
|
| 339 |
+
noisy_image = add_noise_to_image(image, noise_level=0.01 + i*0.003)
|
| 340 |
+
|
| 341 |
+
# Slightly vary guidance scale
|
| 342 |
+
varied_guidance = true_guidance_scale + random.uniform(-0.2, 0.2)
|
| 343 |
+
varied_guidance = max(1.0, min(10.0, varied_guidance))
|
| 344 |
+
|
| 345 |
+
# Generate single image with variations
|
| 346 |
+
result = pipe(
|
| 347 |
+
image=noisy_image,
|
| 348 |
+
prompt=prompt,
|
| 349 |
+
negative_prompt=" ",
|
| 350 |
+
num_inference_steps=num_inference_steps,
|
| 351 |
+
generator=generator,
|
| 352 |
+
true_cfg_scale=varied_guidance,
|
| 353 |
+
num_images_per_prompt=1
|
| 354 |
+
).images
|
| 355 |
+
edited_images.extend(result)
|
| 356 |
+
else:
|
| 357 |
+
# Single image generation (unchanged)
|
| 358 |
+
generator = torch.Generator(device=device).manual_seed(base_seed)
|
| 359 |
+
edited_images = pipe(
|
| 360 |
+
image=image,
|
| 361 |
+
prompt=prompt,
|
| 362 |
+
negative_prompt=" ",
|
| 363 |
+
num_inference_steps=num_inference_steps,
|
| 364 |
+
generator=generator,
|
| 365 |
+
true_cfg_scale=true_guidance_scale,
|
| 366 |
+
num_images_per_prompt=num_images_per_prompt
|
| 367 |
+
).images
|
| 368 |
|
| 369 |
# Clear cache after generation
|
| 370 |
if device == "cuda":
|
| 371 |
torch.cuda.empty_cache()
|
| 372 |
gc.collect()
|
| 373 |
+
return edited_images, base_seed, prompt_info
|
|
|
|
| 374 |
except Exception as e:
|
| 375 |
# Clear cache on error
|
| 376 |
if device == "cuda":
|
| 377 |
torch.cuda.empty_cache()
|
| 378 |
gc.collect()
|
| 379 |
gr.Error(f"Image generation failed: {str(e)}")
|
| 380 |
+
return [], base_seed, (
|
| 381 |
f"<div style='margin:10px; padding:15px; border-radius:8px; border-left:4px solid #dd2c00; background: #fef5f5'>"
|
| 382 |
f"<h4 style='margin-top: 0;'>⚠️ Processing Error</h4>"
|
| 383 |
f"<p>{str(e)[:200]}</p>"
|
| 384 |
f"</div>"
|
| 385 |
)
|
| 386 |
+
|
| 387 |
+
with gr.Blocks(title="Qwen Image Edit - Fast Lightning Mode w/ Batch") as demo:
|
| 388 |
gr.Markdown("""
|
| 389 |
<div style="text-align: center; background: linear-gradient(to right, #3a7bd5, #00d2ff); color: white; padding: 20px; border-radius: 8px;">
|
| 390 |
<h1 style="margin-bottom: 5px;">⚡️ Qwen-Image-Edit Lightning</h1>
|
| 391 |
+
<p>✨ 8-step inferencing with lightx2v's LoRA.</p>
|
| 392 |
+
<p>📝 Local Prompt Enhancement, Batched Multi-image Generation</p>
|
| 393 |
</div>
|
| 394 |
""")
|
| 395 |
|
|
|
|
| 453 |
minimum=1,
|
| 454 |
maximum=4,
|
| 455 |
step=1,
|
| 456 |
+
value=2
|
| 457 |
)
|
| 458 |
|
| 459 |
# Output Column
|