Spaces:
Running on Zero
Running on Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,26 +1,20 @@
|
|
| 1 |
import base64
|
| 2 |
from io import BytesIO
|
| 3 |
-
|
| 4 |
import gradio as gr
|
| 5 |
import torch
|
| 6 |
from PIL import Image, ImageChops
|
| 7 |
-
|
| 8 |
-
from
|
| 9 |
|
| 10 |
from utils import process_source, process_reference, paste_back, binarize_mask
|
| 11 |
|
| 12 |
-
pipe =
|
| 13 |
-
torch_dtype=torch.bfloat16
|
| 14 |
-
device="cuda",
|
| 15 |
-
model_configs=[
|
| 16 |
-
ModelConfig(model_id="black-forest-labs/FLUX.2-klein-base-4B", origin_file_pattern="text_encoder/*.safetensors"),
|
| 17 |
-
ModelConfig(model_id="black-forest-labs/FLUX.2-klein-base-4B", origin_file_pattern="transformer/*.safetensors"),
|
| 18 |
-
ModelConfig(model_id="black-forest-labs/FLUX.2-klein-base-4B", origin_file_pattern="vae/diffusion_pytorch_model.safetensors"),
|
| 19 |
-
],
|
| 20 |
-
tokenizer_config=ModelConfig(model_id="black-forest-labs/FLUX.2-klein-base-4B", origin_file_pattern="tokenizer/"),
|
| 21 |
)
|
|
|
|
| 22 |
|
| 23 |
-
pipe.
|
| 24 |
|
| 25 |
PROMPT = "Replace the white mask of image1 with the content in image2. Preserving the background, lighting, and surrounding elements, maintain a seamless and natural result."
|
| 26 |
|
|
@@ -211,12 +205,15 @@ def load_example(idx):
|
|
| 211 |
def load_ex1():
|
| 212 |
return load_example(0)
|
| 213 |
|
|
|
|
| 214 |
def load_ex2():
|
| 215 |
return load_example(1)
|
| 216 |
|
|
|
|
| 217 |
def load_ex3():
|
| 218 |
return load_example(2)
|
| 219 |
|
|
|
|
| 220 |
def load_ex4():
|
| 221 |
return load_example(3)
|
| 222 |
|
|
@@ -291,7 +288,7 @@ def run_local(base, ref, base_state, ref_state, seed, num_inference_steps, cfg_s
|
|
| 291 |
text-align: center; font-size: 18px; box-shadow: 0 0 15px rgba(0,0,0,0.3);
|
| 292 |
">
|
| 293 |
<p style="color: red; margin-bottom: 20px;">
|
| 294 |
-
⚠️ Please
|
| 295 |
</p>
|
| 296 |
<button onclick="this.closest('.error-overlay').remove()"
|
| 297 |
style="padding: 8px 20px; cursor: pointer; border: none;
|
|
@@ -306,16 +303,16 @@ def run_local(base, ref, base_state, ref_state, seed, num_inference_steps, cfg_s
|
|
| 306 |
background_image, _, crop_box, source_mask_cropped = process_source(pil_bg, pil_mask, CANVAS_W)
|
| 307 |
ref_image = process_reference(pil_ref, pil_ref_mask, CANVAS_W)
|
| 308 |
|
|
|
|
| 309 |
generated_image = pipe(
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
num_inference_steps=int(num_inference_steps),
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
)
|
| 319 |
result_img = paste_back(generated_image, pil_bg, crop_box, source_mask_cropped, feather=0)
|
| 320 |
|
| 321 |
return result_img, gr.update(visible=False)
|
|
@@ -454,25 +451,21 @@ with gr.Blocks(css="""
|
|
| 454 |
""") as demo:
|
| 455 |
|
| 456 |
gr.Markdown(
|
| 457 |
-
"<h1 style='text-align: center;'>Reference-Based Object Insertion
|
| 458 |
-
"<h3 style='text-align: center;'>Insert
|
| 459 |
-
"<p style='text-align: center;'>"
|
| 460 |
-
"<a href='https://github.com/huan-yin/Easy-Insert' target='_blank' "
|
| 461 |
-
"style='color: #3b82f6; text-decoration: none; font-weight: 500;'>"
|
| 462 |
-
"GitHub Repo: huan-yin/Easy-Insert</a></p>"
|
| 463 |
)
|
| 464 |
gr.Markdown(
|
| 465 |
"""
|
| 466 |
**Instructions:**
|
| 467 |
-
1. Upload a background image
|
| 468 |
-
2. Or click any
|
| 469 |
-
3. Click the "Generate" button
|
| 470 |
"""
|
| 471 |
)
|
| 472 |
|
| 473 |
with gr.Row(elem_classes="input-row"):
|
| 474 |
base = gr.ImageEditor(
|
| 475 |
-
label="Background Image (
|
| 476 |
type="pil",
|
| 477 |
format="png",
|
| 478 |
width=420,
|
|
@@ -489,7 +482,7 @@ with gr.Blocks(css="""
|
|
| 489 |
eraser=gr.Eraser(default_size=30),
|
| 490 |
)
|
| 491 |
ref = gr.ImageEditor(
|
| 492 |
-
label="Reference Image (
|
| 493 |
type="pil",
|
| 494 |
format="png",
|
| 495 |
width=420,
|
|
@@ -507,7 +500,7 @@ with gr.Blocks(css="""
|
|
| 507 |
)
|
| 508 |
|
| 509 |
with gr.Row():
|
| 510 |
-
seed = gr.Number(label="
|
| 511 |
num_inference_steps = gr.Slider(label="Inference Steps", minimum=1, maximum=50, step=1, value=15)
|
| 512 |
cfg_scale = gr.Slider(label="CFG Scale", minimum=1, maximum=10, step=0.1, value=4)
|
| 513 |
|
|
@@ -526,7 +519,7 @@ with gr.Blocks(css="""
|
|
| 526 |
with gr.Row():
|
| 527 |
error_dialog = gr.HTML(visible=False)
|
| 528 |
|
| 529 |
-
gr.HTML('<div class="ex-section-header"><span style="font-weight:700;font-size:16px;color:#374151;">Examples (click to load background
|
| 530 |
|
| 531 |
base_state = gr.State(None)
|
| 532 |
ref_state = gr.State(None)
|
|
@@ -555,7 +548,3 @@ with gr.Blocks(css="""
|
|
| 555 |
)
|
| 556 |
|
| 557 |
demo.launch(server_name="0.0.0.0", server_port=7860)
|
| 558 |
-
|
| 559 |
-
|
| 560 |
-
|
| 561 |
-
|
|
|
|
| 1 |
import base64
|
| 2 |
from io import BytesIO
|
| 3 |
+
import spaces
|
| 4 |
import gradio as gr
|
| 5 |
import torch
|
| 6 |
from PIL import Image, ImageChops
|
| 7 |
+
|
| 8 |
+
from diffusers import Flux2KleinPipeline
|
| 9 |
|
| 10 |
from utils import process_source, process_reference, paste_back, binarize_mask
|
| 11 |
|
| 12 |
+
pipe = Flux2KleinPipeline.from_pretrained(
|
| 13 |
+
"black-forest-labs/FLUX.2-klein-base-4B", torch_dtype=torch.bfloat16
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
)
|
| 15 |
+
pipe.to("cuda")
|
| 16 |
|
| 17 |
+
pipe.load_lora_weights("LiXiY/Easy-Insert")
|
| 18 |
|
| 19 |
PROMPT = "Replace the white mask of image1 with the content in image2. Preserving the background, lighting, and surrounding elements, maintain a seamless and natural result."
|
| 20 |
|
|
|
|
| 205 |
def load_ex1():
|
| 206 |
return load_example(0)
|
| 207 |
|
| 208 |
+
|
| 209 |
def load_ex2():
|
| 210 |
return load_example(1)
|
| 211 |
|
| 212 |
+
|
| 213 |
def load_ex3():
|
| 214 |
return load_example(2)
|
| 215 |
|
| 216 |
+
|
| 217 |
def load_ex4():
|
| 218 |
return load_example(3)
|
| 219 |
|
|
|
|
| 288 |
text-align: center; font-size: 18px; box-shadow: 0 0 15px rgba(0,0,0,0.3);
|
| 289 |
">
|
| 290 |
<p style="color: red; margin-bottom: 20px;">
|
| 291 |
+
⚠️ Please draw the mask on BOTH the background image and the reference image first, or click an example!
|
| 292 |
</p>
|
| 293 |
<button onclick="this.closest('.error-overlay').remove()"
|
| 294 |
style="padding: 8px 20px; cursor: pointer; border: none;
|
|
|
|
| 303 |
background_image, _, crop_box, source_mask_cropped = process_source(pil_bg, pil_mask, CANVAS_W)
|
| 304 |
ref_image = process_reference(pil_ref, pil_ref_mask, CANVAS_W)
|
| 305 |
|
| 306 |
+
generator = torch.Generator(device="cuda").manual_seed(int(seed))
|
| 307 |
generated_image = pipe(
|
| 308 |
+
image=[background_image, ref_image],
|
| 309 |
+
prompt=PROMPT,
|
| 310 |
+
height=CANVAS_H,
|
| 311 |
+
width=CANVAS_W,
|
| 312 |
num_inference_steps=int(num_inference_steps),
|
| 313 |
+
guidance_scale=float(cfg_scale),
|
| 314 |
+
generator=generator,
|
| 315 |
+
).images[0]
|
|
|
|
| 316 |
result_img = paste_back(generated_image, pil_bg, crop_box, source_mask_cropped, feather=0)
|
| 317 |
|
| 318 |
return result_img, gr.update(visible=False)
|
|
|
|
| 451 |
""") as demo:
|
| 452 |
|
| 453 |
gr.Markdown(
|
| 454 |
+
"<h1 style='text-align: center;'>Reference-Based Object Insertion (FLUX.2-klein, diffusers)</h1>"
|
| 455 |
+
"<h3 style='text-align: center;'>Insert the object from the reference image into the masked region of the background image</h3>"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 456 |
)
|
| 457 |
gr.Markdown(
|
| 458 |
"""
|
| 459 |
**Instructions:**
|
| 460 |
+
1. Upload a background image, then use the brush/eraser tools below the image to mark or refine the insertion region (mask); upload a reference image and brush/erase over the object to be inserted (ref mask).
|
| 461 |
+
2. Or click any row of thumbnails in the "Examples" section below to automatically load background + mask + reference + ref mask.
|
| 462 |
+
3. Click the "Generate" button, and the result will be displayed below.
|
| 463 |
"""
|
| 464 |
)
|
| 465 |
|
| 466 |
with gr.Row(elem_classes="input-row"):
|
| 467 |
base = gr.ImageEditor(
|
| 468 |
+
label="Background Image (brush the insertion region)",
|
| 469 |
type="pil",
|
| 470 |
format="png",
|
| 471 |
width=420,
|
|
|
|
| 482 |
eraser=gr.Eraser(default_size=30),
|
| 483 |
)
|
| 484 |
ref = gr.ImageEditor(
|
| 485 |
+
label="Reference Image (brush the object to insert)",
|
| 486 |
type="pil",
|
| 487 |
format="png",
|
| 488 |
width=420,
|
|
|
|
| 500 |
)
|
| 501 |
|
| 502 |
with gr.Row():
|
| 503 |
+
seed = gr.Number(label="Seed", value=1, precision=0)
|
| 504 |
num_inference_steps = gr.Slider(label="Inference Steps", minimum=1, maximum=50, step=1, value=15)
|
| 505 |
cfg_scale = gr.Slider(label="CFG Scale", minimum=1, maximum=10, step=0.1, value=4)
|
| 506 |
|
|
|
|
| 519 |
with gr.Row():
|
| 520 |
error_dialog = gr.HTML(visible=False)
|
| 521 |
|
| 522 |
+
gr.HTML('<div class="ex-section-header"><span style="font-weight:700;font-size:16px;color:#374151;">Examples (click to load background + mask + reference + ref mask)</span></div>')
|
| 523 |
|
| 524 |
base_state = gr.State(None)
|
| 525 |
ref_state = gr.State(None)
|
|
|
|
| 548 |
)
|
| 549 |
|
| 550 |
demo.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
|
|
|
|
|
|
|
|
|