Spaces:
Running
Running
File size: 6,389 Bytes
7f3eee3 e141d0d f075312 47ed5fc f075312 47ed5fc f075312 e141d0d 47ed5fc f983a39 7f7d839 f983a39 048180e c6266b0 47ed5fc 7f7d839 47ed5fc f075312 47ed5fc 7f7d839 47ed5fc 7f7d839 f075312 47ed5fc f075312 47ed5fc 7f7d839 47ed5fc 9d1fa89 47ed5fc c6266b0 7f7d839 c6266b0 47ed5fc 15820e1 7f3eee3 ca81d56 47ed5fc 7f7d839 47ed5fc ca81d56 47ed5fc ca81d56 c6266b0 7f3eee3 47ed5fc 15820e1 47ed5fc c6266b0 15820e1 47ed5fc c6266b0 15820e1 47ed5fc f983a39 47ed5fc c6266b0 f983a39 f075312 47ed5fc 7f7d839 f983a39 7f7d839 47ed5fc 7f7d839 f983a39 7f7d839 f983a39 7f3eee3 c6266b0 47ed5fc c6266b0 7f3eee3 d977ccc | 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 164 165 166 167 168 169 170 171 172 173 | import gradio as gr
from gradio_client import Client, handle_file
from PIL import Image
import tempfile, os, time, random
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# More VTON spaces to try β updated 2026 list
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
SPACES = [
("yisol/IDM-VTON", "idmvton"),
("yisol/IDM-VTON-DC", "idmvton-dc"),
("Kwai-Kolors/Kolors-Virtual-Try-On", "kolors"),
("Nymbo/Virtual-Try-On", "nymbo"),
("multimodalart/idm-vton", "multimodal"),
]
def save_tmp(img):
p = tempfile.mktemp(suffix=".jpg")
img.save(p, quality=95)
return p
def cleanup(*paths):
for p in paths:
try:
if p and os.path.exists(p): os.remove(p)
except: pass
def try_kolors(client, p_path, c_path, steps, seed):
"""Kwai Kolors has different API signature."""
result = client.predict(
human_img = handle_file(p_path),
garm_img = handle_file(c_path),
garment_des = "clothing item",
api_name = "/tryon"
)
return result[0]
def try_idmvton(client, p_path, c_path, steps, seed, is_dress):
"""Standard IDM-VTON API signature."""
result = client.predict(
dict = {"background": handle_file(p_path), "layers": [], "composite": None},
garm_img = handle_file(c_path),
garment_des = "dress" if is_dress else "shirt",
is_checked = True,
is_checked_crop = is_dress,
denoise_steps = steps,
seed = seed,
api_name = "/tryon"
)
return result[0]
def virtual_tryon(person_img, cloth_img, quality):
if person_img is None:
return None, "β οΈ Please upload your photo!"
if cloth_img is None:
return None, "β οΈ Please upload a clothing image!"
steps = {"Fast β‘": 20, "Balanced βοΈ": 30, "Best Quality π": 40}.get(quality, 30)
seed = random.randint(0, 9999)
t0 = time.time()
is_dress = (cloth_img.height / max(cloth_img.width, 1)) > 1.3
p_path = save_tmp(person_img)
c_path = save_tmp(cloth_img)
errors = []
for space_id, space_type in SPACES:
try:
print(f"π Trying {space_id}...")
client = Client(space_id, verbose=False)
if space_type == "kolors":
result_path = try_kolors(client, p_path, c_path, steps, seed)
else:
result_path = try_idmvton(client, p_path, c_path, steps, seed, is_dress)
result_img = Image.open(result_path).convert("RGB")
cleanup(p_path, c_path)
elapsed = time.time() - t0
name = space_id.split("/")[-1]
return result_img, f"β
Done in {elapsed:.1f}s via {name}!"
except Exception as e:
err = str(e)
errors.append(f"{space_id}: {err[:60]}")
print(f"β {space_id} β {err[:80]}")
time.sleep(2)
continue
cleanup(p_path, c_path)
# Show which spaces were tried
print("All spaces failed:\n" + "\n".join(errors))
return None, (
"β³ All servers are currently busy.\n\n"
"Please try again in 2-3 minutes.\n"
"π‘ Best time to use: early morning or late night (India time)"
)
# ββ UI ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
with gr.Blocks(
title="AI Virtual Try-On",
theme=gr.themes.Soft(primary_hue="violet", secondary_hue="pink"),
css="""
footer { display:none !important }
.tip { background:#f5f0ff; border-radius:12px;
padding:10px 14px; font-size:.85em;
color:#555; margin-top:8px;
border:1px solid #e0d0ff }
"""
) as demo:
gr.HTML("""
<div style='text-align:center;padding:20px 0 10px'>
<h1 style='font-size:2.3em;font-weight:900;
background:linear-gradient(90deg,#7c3aed,#db2777);
-webkit-background-clip:text;-webkit-text-fill-color:transparent'>
AI Virtual Try-On
</h1>
<p style='color:#888;margin-top:4px'>
Upload your photo + clothing β see how it looks on you instantly!
</p>
</div>
""")
with gr.Row(equal_height=True):
with gr.Column():
gr.Markdown("### Step 1 β Your Photo")
p_in = gr.Image(label="Upload full-body photo", type="pil", height=380)
gr.HTML('<div class="tip">Stand straight Β· Full body Β· Good lighting Β· Plain background</div>')
with gr.Column():
gr.Markdown("### Step 2 β Clothing Item")
c_in = gr.Image(label="Upload clothing product photo", type="pil", height=380)
gr.HTML('<div class="tip">White background product photo Β· AI detects garment type automatically</div>')
with gr.Column():
gr.Markdown("### Step 3 β Result")
r_out = gr.Image(label="Try-On Result", type="pil", height=380)
status = gr.Textbox(
label="Status",
interactive=False,
placeholder="Your result will appear here after clicking Generateβ¦"
)
with gr.Row():
quality = gr.Radio(
["Fast β‘", "Balanced βοΈ", "Best Quality π"],
value="Balanced βοΈ",
label="Quality",
info="Fast = quicker Β· Best Quality = slower but sharper",
scale=2
)
gr.Button(
"Generate Try-On!", variant="primary", size="lg", scale=1
).click(
fn=virtual_tryon,
inputs=[p_in, c_in, quality],
outputs=[r_out, status]
)
gr.HTML("""
<div style='text-align:center;margin-top:16px;padding:12px 16px;
background:linear-gradient(135deg,#f5f0ff,#fff0f8);
border-radius:12px;color:#666;font-size:.83em;
border:1px solid #e8d8ff'>
Tries 5 different AI servers automatically Β·
Auto-detects dress vs top Β· 100% Free
</div>
""")
demo.launch() |