Spaces:
Running
Running
File size: 6,984 Bytes
bc870ea ed52ef5 bc870ea ed52ef5 bc870ea ed52ef5 bc870ea ed52ef5 bc870ea |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# -*- coding: utf-8 -*-
# ZenCtrl Inpainting Playground (Baseten backend)
import os, json, base64, requests
from io import BytesIO
from PIL import Image, ImageDraw
import gradio as gr
# ββββββββββ Secrets & endpoints ββββββββββ
BASETEN_MODEL_URL = "https://app.baseten.co/models/YOUR_MODEL_ID/predict"
BASETEN_API_KEY = os.getenv("BASETEN_API_KEY")
REPLICATE_TOKEN = os.getenv("REPLICATE_API_TOKEN")
from florence_sam.detect_and_segment import fill_detected_bboxes
# ββββββββββ Globals ββββββββββ
ADAPTER_NAME = "inpaint"
ADAPTER_SIZE = 1024
model_config = dict(union_cond_attn=True, add_cond_attn=False,
latent_lora=False, independent_condition=False)
css = "#col-container {margin:0 auto; max-width:960px;}"
#Background prompt via Replicate
def _gen_bg(prompt: str):
url = replicate.run(
"google/imagen-4-fast",
input={"prompt": prompt or "cinematic background", "aspect_ratio": "1:1"},
)
url = url[0] if isinstance(url, list) else url
return Image.open(BytesIO(requests.get(url, timeout=120).content)).convert("RGB")
# Core generation
def process_image_and_text(subject_image, adapter_dict, prompt, use_detect, detect_prompt, size=ADAPTER_SIZE, rank=10.0):
seed, guidance_scale, steps = 42, 2.5, 28
if use_detect:
base_img = adapter_dict["image"] if isinstance(adapter_dict, dict) else adapter_dict
if base_img is None:
raise gr.Error("Upload a background image first.")
adapter_image, _ = fill_detected_bboxes(
image=base_img, text=detect_prompt,
inflate_pct=0.15, fill_color="#00FF00"
)
else:
adapter_image = adapter_dict["image"] if isinstance(adapter_dict, dict) else adapter_dict
if isinstance(adapter_dict, dict) and adapter_dict.get("mask") is not None:
m = adapter_dict["mask"].convert("L").point(lambda p: 255 if p else 0)
if bbox := m.getbbox():
rect = Image.new("L", m.size, 0)
ImageDraw.Draw(rect).rectangle(bbox, fill=255)
m = rect
green = Image.new("RGB", adapter_image.size, "#00FF00")
adapter_image = Image.composite(green, adapter_image, m)
def prep(img: Image.Image):
w, h = img.size
m = min(w, h)
return img.crop(((w-m)//2, (h-m)//2, (w+m)//2, (h+m)//2)).resize((size, size), Image.LANCZOS)
subj_proc = prep(subject_image)
adap_proc = prep(adapter_image)
def b64(img):
buf = BytesIO(); img.save(buf, format="PNG")
return base64.b64encode(buf.getvalue()).decode()
payload = {
"prompt": prompt,
"subject_image": b64(subj_proc),
"adapter_image": b64(adap_proc),
"height": size, "width": size,
"steps": steps, "seed": seed,
"guidance_scale": guidance_scale, "rank": rank,
}
headers = {"Content-Type": "application/json"}
if BASETEN_API_KEY:
headers["Authorization"] = f"Api-Key {BASETEN_API_KEY}"
resp = requests.post(BASETEN_MODEL_URL, headers=headers, json=payload, timeout=120)
resp.raise_for_status()
if resp.headers.get("content-type", "").startswith("image/"):
raw_img = Image.open(BytesIO(resp.content))
else:
url = resp.json().get("image_url")
if not url:
raise gr.Error("Baseten response missing image data.")
raw_img = Image.open(BytesIO(requests.get(url, timeout=120).content))
return [[raw_img]], raw_img
# ββββββββββ Header HTML ββββββββββ
header_html = """
<h1>ZenCtrl Inpainting</h1>
<div align="center" style="line-height:1;">
<a href="https://discord.com/invite/b9RuYQ3F8k" target="_blank" style="margin:10px;">
<img src="https://img.shields.io/badge/Discord-Join-7289da.svg?logo=discord" alt="Discord">
</a>
<a href="https://fotographer.ai/zen-control" target="_blank" style="margin:10px;">
<img src="https://img.shields.io/badge/Website-Landing_Page-blue" alt="LP">
</a>
<a href="https://x.com/FotographerAI" target="_blank" style="margin:10px;">
<img src="https://img.shields.io/twitter/follow/FotographerAI?style=social" alt="X">
</a>
</div>
"""
# ββββββββββ Gradio UI ββββββββββ
with gr.Blocks(css=css, title="ZenCtrl Playground") as demo:
raw_state = gr.State()
gr.HTML(header_html)
gr.Markdown("""
**Generate context-aware images of your subject with ZenCtrlβs inpainting playground.**
Upload a subject + optional mask, write a prompt, and hit **Generate**.
Open *Advanced Settings* to fetch an AI-generated background.
""")
with gr.Row():
with gr.Column(scale=2, elem_id="col-container"):
subj_img = gr.Image(type="pil", label="Subject image")
ref_img = gr.Image(type="pil", label="Background / Mask image", tool="sketch", brush_color="#00FF00", sources=["upload", "clipboard"])
use_detect_ck = gr.Checkbox(False, label="Detect with Florence-SAM")
detect_box = gr.Textbox(label="Detection prompt", value="person, chair", visible=False)
promptbox = gr.Textbox(label="Generation prompt", value="furniture", lines=2)
run_btn = gr.Button("Generate", variant="primary")
with gr.Accordion("Advanced Settings", open=False):
bgprompt = gr.Textbox(label="Background Prompt", value="Scandinavian living room β¦")
bg_btn = gr.Button("Generate BG")
with gr.Column(scale=2):
gallery = gr.Gallery(columns=[1], rows=[1], object_fit="contain", height="auto")
bg_img = gr.Image(label="Background", visible=False)
gr.Examples(
examples=[
["examples/subject1.png", "examples/bg1.png", "Make the toy sit on a marble table", "examples/out1.png"],
["examples/subject2.png", "examples/bg2.png", "Turn the flowers into sunflowers", "examples/out2.png"],
["examples/subject3.png", "examples/bg3.png", "Make this monster ride a skateboard on the beach", "examples/out3.png"],
["examples/subject4.png", "examples/bg4.png", "Make this cat happy", "examples/out4.png"],
],
inputs=[subj_img, ref_img, promptbox],
outputs=[gallery],
fn=process_image_and_text,
examples_per_page="all",
label="Presets (Input Β· Background Β· Prompt Β· Output)",
cache_examples="lazy"
)
run_btn.click(
process_image_and_text,
inputs=[subj_img, ref_img, promptbox, use_detect_ck, detect_box],
outputs=[gallery, raw_state]
)
bg_btn.click(_gen_bg, inputs=[bgprompt], outputs=[bg_img])
use_detect_ck.change(lambda v: gr.update(visible=v), inputs=use_detect_ck, outputs=detect_box)
# ββββββββββ Launch ββββββββββ
demo.launch(show_api=False, share=True)
|