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 # ✅ New Pixelcut API key pixelcut_api_key = "sk_3a15d5b79d5944f3995c54615f8928f8" # 🎯 Convert image to PNG format def convert_to_png(image): return cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 🔥 Encode image to base64 PNG format def encode_image(image): image = convert_to_png(image) _, buffer = cv2.imencode('.png', image) return base64.b64encode(buffer).decode('utf-8') # 🛠️ Upload images to a temporary hosting service def upload_image(image_data): files = {"file": ("image.png", image_data, "image/png")} upload_response = requests.post("https://tmpfiles.org/api/v1/upload", files=files) if upload_response.status_code == 200: return upload_response.json().get("data", {}).get("url", None) else: print("❌ Image upload failed:", upload_response.text) return None # 🚀 Main try-on function using Pixelcut API def tryon(person_img, garment_img, seed, randomize_seed): start_time = time.time() # 🛑 Check if images are provided if person_img is None or garment_img is None: return None, None, "Empty image" # 🎲 Handle seed randomization if randomize_seed: seed = random.randint(0, MAX_SEED) # 🔥 Convert images to base64 PNG _, person_encoded = cv2.imencode('.png', convert_to_png(person_img)) _, garment_encoded = cv2.imencode('.png', convert_to_png(garment_img)) # ✅ Upload person and garment images to get URLs person_url = upload_image(person_encoded) garment_url = upload_image(garment_encoded) if not person_url or not garment_url: return None, None, "Image upload failed" # 🌟 Setup Pixelcut API endpoint and headers url = "https://api.developer.pixelcut.ai/v1/remove-background" headers = { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-API-KEY': pixelcut_api_key } # 🔧 Use uploaded URLs in the payload person_data = { "image_url": person_url, "format": "png" } garment_data = { "image_url": garment_url, "format": "png" } result_img = None max_retries = 5 retry_delay = 3 # Faster retries now! try: session = requests.Session() # 🔁 Retry loop — smarter handling of "please try again later" for attempt in range(max_retries): response = session.post(url, headers=headers, json=person_data, timeout=60) print("Response code:", response.status_code) # ✅ Success — process the result if response.status_code == 200: result_url = response.json().get('result_url', '') print("✅ Success:", result_url) # Fetch the final image if result_url: result_img_data = requests.get(result_url).content result_np = np.frombuffer(result_img_data, np.uint8) result_img = cv2.imdecode(result_np, cv2.IMREAD_UNCHANGED) info = "✅ Success" break else: # 🔥 Handle "please try again later" or other errors error_response = response.json().get('error', '') if "please try again later" in error_response.lower(): print(f"Attempt {attempt + 1}/{max_retries}: API said 'please try again later'. Retrying in {retry_delay} seconds...") time.sleep(retry_delay) retry_delay += 2 # Exponential backoff — retries longer each time else: info = f"❌ Error: {response.status_code} - {response.text}" break else: # ❌ If all retries fail info = "API still says 'please try again later' — waited too long." # 🛑 Handle timeouts specifically except requests.exceptions.ReadTimeout: print("Timeout!") info = "⚡ Timeout — please try again later" raise gr.Error("Too many users, please try again later") # ❗ Handle any other unexpected errors except Exception as err: print(f"❌ Other error: {err}") info = "Error, please contact the admin" end_time = time.time() print(f"⏳ Time used: {end_time - start_time:.2f} seconds") return result_img, seed, info 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("""