import gradio as gr from PIL import Image, ImageEnhance, ImageDraw import cv2 import numpy as np # Map keywords in text prompt to colors COLOR_MAP = { "orange": (255, 150, 0, 180), "purple": (150, 0, 255, 180), "blue": (0, 150, 255, 180), "red": (255, 0, 0, 180), "green": (0, 255, 0, 180), "yellow": (255, 255, 0, 180) } def parse_colors(text): colors = [] text = text.lower() for key, value in COLOR_MAP.items(): if key in text: colors.append(value) if not colors: colors = [(255, 150, 0, 180)] # default orange return colors def detect_building_mask(pil_image): img = np.array(pil_image) gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) # Detect edges edges = cv2.Canny(gray, 50, 150) # Dilate edges to cover full building area mask = cv2.dilate(edges, np.ones((15,15),np.uint8), iterations=3) return mask # mask = 255 where building edges/windows exist def draw_lights_on_mask(pil_image, mask, colors): draw = ImageDraw.Draw(pil_image) width, height = pil_image.size mask_img = Image.fromarray(mask) mask_pixels = mask_img.load() # Step size smaller → lights cover full building step_x = max(width // 40, 5) step_y = max(height // 40, 5) for x in range(0, width, step_x): for y in range(0, height, step_y): if mask_pixels[x, y] > 0: color = colors[(x//step_x + y//step_y) % len(colors)] draw.rectangle([x, y, x+step_x, y+step_y], fill=color) return pil_image def facade_lighting(image, prompt): if not isinstance(image, Image.Image): image = Image.fromarray(image) # Darken building first dark_image = ImageEnhance.Brightness(image).enhance(0.3) # Parse colors from text colors = parse_colors(prompt) # Detect building structure mask = detect_building_mask(dark_image) # Draw facade lights on dark building output_image = draw_lights_on_mask(dark_image, mask, colors) return output_image def process(image, prompt): return facade_lighting(image, prompt) demo = gr.Interface( process, ["image", "text"], "image", examples=[["building.jpg", "orange and purple lights"]] ) demo.launch()