import cv2 import numpy as np import gradio as gr from PIL import Image, ImageDraw, ImageFont def generate_text_image(text, style, width, height): """Generate an image of the input text with the selected style.""" font_path = { "Bold": "arialbd.ttf", "Italic": "ariali.ttf", "Graffiti": "graffiti.ttf", # Provide custom font if needed "Calligraphy": "calligraphy.ttf" # Provide custom font if needed } img = Image.new("RGBA", (width, height), (255, 255, 255, 0)) draw = ImageDraw.Draw(img) # Dynamically calculate font size based on image dimensions font_size = int(min(width, height) * 0.1) # Adjust text to be proportional try: font = ImageFont.truetype(font_path[style], size=font_size) except: font = ImageFont.load_default() text_bbox = draw.textbbox((0, 0), text, font=font) text_width = text_bbox[2] - text_bbox[0] text_height = text_bbox[3] - text_bbox[1] position = ((width - text_width) // 2, (height - text_height) // 2) draw.text(position, text, font=font, fill=(0, 0, 0, 255)) return img def apply_displacement_map(text_img, clothing_img, strength=20): """Apply displacement map to blend text onto clothing.""" gray = cv2.cvtColor(clothing_img, cv2.COLOR_BGR2GRAY) grad_x = cv2.Sobel(gray, cv2.CV_32F, 1, 0, ksize=5) grad_y = cv2.Sobel(gray, cv2.CV_32F, 0, 1, ksize=5) grad_x = cv2.normalize(grad_x, None, 0, 1, cv2.NORM_MINMAX) grad_y = cv2.normalize(grad_y, None, 0, 1, cv2.NORM_MINMAX) displacement_map = np.zeros_like(clothing_img, dtype=np.float32) displacement_map[:, :, 0] = grad_x * strength displacement_map[:, :, 1] = grad_y * strength text_warped = cv2.remap(text_img, displacement_map[:, :, 0].astype(np.float32), displacement_map[:, :, 1].astype(np.float32), interpolation=cv2.INTER_LINEAR) return text_warped def overlay_text_on_clothing(clothing_image, text_input, style, strength=20, alpha=0.7, photo=None, blend_alpha=0.5): """Blend generated text and optional photo onto the clothing image.""" clothing_img = cv2.imread(clothing_image) # Read image from file path # Generate text image dynamically text_img_pil = generate_text_image(text_input, style, clothing_img.shape[1], clothing_img.shape[0]) text_img = cv2.cvtColor(np.array(text_img_pil), cv2.COLOR_RGBA2BGRA) alpha_channel = text_img[:, :, 3] / 255.0 text_img = text_img[:, :, :3] # Apply displacement map text_warped = apply_displacement_map(text_img, clothing_img, strength) for c in range(3): clothing_img[:, :, c] = (1 - alpha_channel) * clothing_img[:, :, c] + alpha_channel * text_warped[:, :, c] # Blend optional photo if provided if photo: photo_img = Image.open(photo).resize((clothing_img.shape[1], clothing_img.shape[0])) photo_img = cv2.cvtColor(np.array(photo_img), cv2.COLOR_RGBA2BGR) clothing_img = cv2.addWeighted(clothing_img, 1 - blend_alpha, photo_img, blend_alpha, 0) # Convert the final blended image back to a PIL Image and return blended_img = Image.fromarray(cv2.cvtColor(clothing_img, cv2.COLOR_BGR2RGB)) return blended_img interface = gr.Interface( fn=overlay_text_on_clothing, inputs=[ gr.Image(type="filepath", label="Upload Clothing Image", interactive=True), gr.Textbox(label="Enter Text for Design"), gr.Radio(["Bold", "Italic", "Graffiti", "Calligraphy"], label="Select Style", value="Bold"), gr.Slider(10, 50, step=5, value=20, label="Displacement Strength"), gr.Slider(0.1, 1.0, step=0.1, value=0.7, label="Alpha Blending"), gr.Image(type="filepath", label="Optional Photo for Blending", interactive=True), gr.Slider(0.0, 1.0, step=0.1, value=0.5, label="Photo Blend Alpha") ], outputs=gr.Image(type="pil", label="Final Design"), title="AI-Powered Clothing Text and Photo Overlay", description="Upload a clothing image, enter a text design, and select a style to blend the text onto the clothing. Optionally blend a photo for enhanced designs.", allow_flagging="never" ) if __name__ == "__main__": interface.launch()