import os import requests import json import time import cv2 import base64 import random import numpy as np import gradio as gr MAX_SEED = 999999 # ✅ Pixelcut API Key pixelcut_api_key = "sk_299d9c6e36d240cbb3dd65fcbac947a4" # ✅ ImgBB API Key (for uploading images to get valid URLs) imgbb_api_key = "03a2ddf1ffa5df33a3999cf20c2fb20f" # 🎯 Convert image to PNG format (keeps the blue tint glitch!) def convert_to_png(image): return cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 🔥 Resize large images to prevent upload failures (ImgBB limit: 32MB) def resize_image(image, max_size=1024): height, width = image.shape[:2] if max(height, width) > max_size: scale = max_size / max(height, width) return cv2.resize(image, (int(width * scale), int(height * scale))) return image # 🛠️ Upload images to ImgBB (fixed payload!) def upload_image_to_imgbb(image_data): url = f"https://api.imgbb.com/1/upload?key={imgbb_api_key}" files = {"image": image_data} response = requests.post(url, files=files) if response.status_code == 200: return response.json().get("data", {}).get("url") else: print("❌ ImgBB upload failed:", response.text) return None # 🚀 Main try-on function (with blue tint + garment overlay) def tryon(person_img, cloth_img, seed, random_seed): import cv2 import numpy as np # 🎲 Handle seed if random_seed: seed = random.randint(0, 1000000) try: # ✅ Convert images to RGB (fixing blue tint) person_img = cv2.cvtColor(person_img, cv2.COLOR_BGR2RGB) cloth_img = cv2.cvtColor(cloth_img, cv2.COLOR_BGR2RGB) # ✂️ Resize both images to 256x256 (keep consistent sizes) person_img = cv2.resize(person_img, (256, 256)) # ✅ Resize garment to fit person size g_h, g_w = person_img.shape[:2] cloth_img = cv2.resize(cloth_img, (g_w, g_h)) # 🔥 Blend garment onto person (centered overlay) output_img = person_img.copy() h, w, _ = person_img.shape # Center garment on the torso (adjust the offset if needed) x_offset = (w - g_w) // 2 y_offset = int(h * 0.35) # ✅ Ensure garment fits the person image if y_offset + g_h > h or x_offset + g_w > w: raise ValueError("❗ Garment image is too large for the person image!") # 🛠️ Overlay garment on the person (with transparency support) alpha = 0.7 # Adjust transparency level (0 = invisible, 1 = solid) output_img[y_offset:y_offset + g_h, x_offset:x_offset + g_w] = cv2.addWeighted( person_img[y_offset:y_offset + g_h, x_offset:x_offset + g_w], 1 - alpha, cloth_img, alpha, 0 ) return output_img, seed, "✅ Success (Blue tint removed + Garment added)" except Exception as e: print(f"❌ Error in tryon function: {e}") return person_img, seed, f"❌ Error: {e}" # 🔧 Paths for examples example_path = os.path.join(os.path.dirname(__file__), "assets") garm_list = os.listdir(os.path.join(example_path, "cloth")) garm_list_path = [os.path.join(example_path, "cloth", garm) for garm in garm_list] human_list = os.listdir(os.path.join(example_path, "human")) human_list_path = [os.path.join(example_path, "human", human) for human in human_list] # 🔧 Paths for examples example_path = os.path.join(os.path.dirname(__file__), "assets") garm_list = os.listdir(os.path.join(example_path, "cloth")) garm_list_path = [os.path.join(example_path, "cloth", garm) for garm in garm_list] human_list = os.listdir(os.path.join(example_path, "human")) human_list_path = [os.path.join(example_path, "human", human) for human in human_list] css=""" #col-left { margin: 0 auto; max-width: 430px; } #col-mid { margin: 0 auto; max-width: 430px; } #col-right { margin: 0 auto; max-width: 430px; } #col-showcase { margin: 0 auto; max-width: 1100px; } #button { color: blue; } """ def load_description(fp): with open(fp, 'r', encoding='utf-8') as f: content = f.read() return content def change_imgs(image1, image2): return image1, image2 with gr.Blocks(css=css) as Tryon: gr.HTML(load_description("assets/new_title.md")) with gr.Row(): with gr.Column(elem_id = "col-left"): gr.HTML("""
Step 1. Upload a person image ⬇️
""") with gr.Column(elem_id = "col-mid"): gr.HTML("""
Step 2. Upload a garment image ⬇️
""") with gr.Column(elem_id = "col-right"): gr.HTML("""
Step 3. Press “Run” to get try-on results
""") with gr.Row(): with gr.Column(elem_id = "col-left"): imgs = gr.Image(label="Person image", sources='upload', type="numpy") # category = gr.Dropdown(label="Garment category", choices=['upper_body', 'lower_body', 'dresses'], value="upper_body") example = gr.Examples( inputs=imgs, examples_per_page=12, examples=human_list_path ) with gr.Column(elem_id = "col-mid"): garm_img = gr.Image(label="Garment image", sources='upload', type="numpy") example = gr.Examples( inputs=garm_img, examples_per_page=12, examples=garm_list_path ) with gr.Column(elem_id = "col-right"): image_out = gr.Image(label="Result", show_share_button=False) with gr.Row(): seed = gr.Slider( label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0, ) randomize_seed = gr.Checkbox(label="Random seed", value=True) with gr.Row(): seed_used = gr.Number(label="Seed used") result_info = gr.Text(label="Response") # try_button = gr.Button(value="Run", elem_id="button") test_button = gr.Button(value="Run", elem_id="button") # try_button.click(fn=start_tryon, inputs=[imgs, garm_img, seed, randomize_seed], outputs=[image_out, seed_used, result_info], api_name='tryon',concurrency_limit=10) test_button.click(fn=tryon, inputs=[imgs, garm_img, seed, randomize_seed], outputs=[image_out, seed_used, result_info], api_name=False, concurrency_limit=45) with gr.Column(elem_id = "col-showcase"): gr.HTML("""

Virtual try-on examples in pairs of person and garment images
""") show_case = gr.Examples( examples=[ ["assets/examples/model2.png", "assets/examples/garment2.png", "assets/examples/result2.png"], ["assets/examples/model3.png", "assets/examples/garment3.png", "assets/examples/result3.png"], ["assets/examples/model1.png", "assets/examples/garment1.png", "assets/examples/result1.png"], ], inputs=[imgs, garm_img, image_out], label=None ) Tryon.queue(api_open=False).launch(show_api=False)