# -*- 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 = """