""" šØ Image Colorizer VersĆ£o otimizada para Hugging Face Spaces """ import gradio as gr from PIL import Image, ImageEnhance, ImageFilter, ImageDraw import numpy as np import tempfile import time import os print("š Iniciando Image Colorizer...") MAX_IMAGE_SIZE = 1024 def log_message(message): """Log para debug""" timestamp = time.strftime("%H:%M:%S") print(f"[{timestamp}] {message}") def validate_image(image): """Valida e prepara imagem""" try: if image is None: return None, "ā Nenhuma imagem fornecida" # Converter para PIL Image se necessĆ”rio if isinstance(image, np.ndarray): img = Image.fromarray(image.astype('uint8')) else: img = image # Verificar tamanho if max(img.size) > 4000: return None, "ā Imagem muito grande (>4000px)" if min(img.size) < 32: return None, "ā Imagem muito pequena (<32px)" log_message(f"ā Imagem vĆ”lida: {img.size}px, {img.mode}") return img, "ok" except Exception as e: log_message(f"ā Erro na validação: {str(e)}") return None, str(e) def resize_image(image, max_size): """Redimensiona mantendo aspect ratio""" if max(image.size) <= max_size: return image ratio = max_size / max(image.size) new_width = int(image.width * ratio) new_height = int(image.height * ratio) return image.resize((new_width, new_height), Image.Resampling.LANCZOS) def apply_colorization(image, style="realistic", intensity=0.8): """Aplica colorização Ć imagem""" try: log_message(f"Aplicando colorização - Estilo: {style}, Intensidade: {intensity}") # Converter para RGB if image.mode != 'RGB': rgb_img = image.convert('RGB') else: rgb_img = image.copy() gray_img = rgb_img.convert('L') # Aplicar efeitos baseados no estilo if style == "realistic": result = rgb_img.copy() enhancer = ImageEnhance.Color(result) result = enhancer.enhance(1.0 + (intensity * 0.5)) r, g, b = result.split() r = r.point(lambda x: min(255, int(x * (1.0 + intensity * 0.1)))) b = b.point(lambda x: max(0, int(x * (1.0 - intensity * 0.05)))) result = Image.merge('RGB', (r, g, b)) elif style == "vibrant": result = rgb_img.copy() enhancer = ImageEnhance.Color(result) result = enhancer.enhance(1.0 + (intensity * 1.0)) enhancer = ImageEnhance.Contrast(result) result = enhancer.enhance(1.0 + (intensity * 0.3)) result = result.filter(ImageFilter.UnsharpMask(radius=1, percent=50, threshold=0)) elif style == "vintage": result = rgb_img.copy() r, g, b = result.split() r = r.point(lambda x: min(255, int(x * 1.1))) g = g.point(lambda x: int(x * 0.9)) b = b.point(lambda x: int(x * 0.8)) result = Image.merge('RGB', (r, g, b)) enhancer = ImageEnhance.Color(result) result = enhancer.enhance(0.7 + (intensity * 0.3)) elif style == "cinematic": result = rgb_img.copy() r, g, b = result.split() r = r.point(lambda x: int(x * 0.9)) g = g.point(lambda x: int(x * 1.0)) b = b.point(lambda x: min(255, int(x * 1.1))) result = Image.merge('RGB', (r, g, b)) enhancer = ImageEnhance.Contrast(result) result = enhancer.enhance(1.0 + (intensity * 0.4)) else: # balanced result = rgb_img.copy() enhancer = ImageEnhance.Color(result) result = enhancer.enhance(1.0 + (intensity * 0.6)) enhancer = ImageEnhance.Contrast(result) result = enhancer.enhance(1.0 + (intensity * 0.2)) # Misturar se imagem era grayscale if image.mode in ['L', 'LA', 'P']: gray_array = np.array(gray_img).astype(np.float32) / 255.0 original_array = np.array(rgb_img).astype(np.float32) colorized_array = np.array(result).astype(np.float32) mixed = (1 - intensity) * original_array + intensity * colorized_array for i in range(3): mixed[:,:,i] = mixed[:,:,i] * (0.7 + 0.3 * gray_array) result = Image.fromarray(mixed.astype(np.uint8)) log_message("ā Colorização concluĆda") return result except Exception as e: log_message(f"ā Erro na colorização: {str(e)}") return image def create_comparison(original, colorized): """Cria comparação lado a lado""" try: if original is None or colorized is None: return None target_height = 400 target_width_orig = int(original.width * (target_height / original.height)) target_width_color = int(colorized.width * (target_height / colorized.height)) original_resized = original.resize((target_width_orig, target_height), Image.Resampling.LANCZOS) colorized_resized = colorized.resize((target_width_color, target_height), Image.Resampling.LANCZOS) total_width = original_resized.width + colorized_resized.width + 20 total_height = target_height + 60 comparison = Image.new('RGB', (total_width, total_height), color=(240, 240, 240)) draw = ImageDraw.Draw(comparison) draw.text((10, 10), "ORIGINAL", fill=(100, 100, 100)) draw.text((original_resized.width + 30, 10), "COLORIZED", fill=(0, 150, 0)) comparison.paste(original_resized, (0, 40)) comparison.paste(colorized_resized, (original_resized.width + 20, 40)) log_message("ā Comparação criada") return comparison except Exception as e: log_message(f"ā Erro na comparação: {str(e)}") return None def save_image(image, prefix="colorized"): """Salva imagem para download""" try: if image is None: return None temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png", prefix=f"{prefix}_") image.save(temp_file.name, "PNG", optimize=True) log_message(f"Imagem salva: {temp_file.name}") return temp_file.name except Exception as e: log_message(f"ā Erro ao salvar: {str(e)}") return None # Interface Gradio with gr.Blocks(title="šØ Image Colorizer", theme=gr.themes.Soft()) as demo: gr.HTML("""
Colorize fotos preto e branco automaticamente
šØ Image Colorizer - Photoshop AI Ecosystem