""" 🎨 Style Transfer Versão otimizada para Hugging Face Spaces """ import gradio as gr from PIL import Image, ImageFilter, ImageOps, ImageEnhance, ImageDraw import numpy as np import tempfile import time print("🚀 Iniciando Style Transfer...") MAX_IMAGE_SIZE = 1024 STYLES = { "van_gogh": "🎨 Van Gogh", "monet": "🌅 Monet", "picasso": "🧑‍🎨 Picasso", "warhol": "👑 Warhol", "hokusai": "🌊 Hokusai", "starry_night": "✨ Noite Estrelada", "oil_painting": "🖼️ Pintura a Óleo", "watercolor": "🎨 Aquarela", "sketch": "✏️ Desenho a Lápis", "comic": "💥 Estilo HQ" } def log_message(message): timestamp = time.strftime("%H:%M:%S") print(f"[{timestamp}] {message}") def validate_image(image): try: if image is None: return None, "❌ Nenhuma imagem fornecida" if isinstance(image, np.ndarray): img = Image.fromarray(image.astype('uint8')) else: img = image if max(img.size) > 4000: return None, "❌ Imagem muito grande" if min(img.size) < 32: return None, "❌ Imagem muito pequena" log_message(f"✅ Imagem válida: {img.size}px") return img, "ok" except Exception as e: return None, str(e) def resize_image(image, max_size): if max(image.size) <= max_size: return image ratio = max_size / max(image.size) new_size = (int(image.width * ratio), int(image.height * ratio)) return image.resize(new_size, Image.Resampling.LANCZOS) def apply_van_gogh_style(image, intensity=0.8): try: img = image.convert('RGB') enhancer = ImageEnhance.Color(img) img = enhancer.enhance(1.0 + intensity * 0.5) enhancer = ImageEnhance.Contrast(img) img = enhancer.enhance(1.0 + intensity * 0.3) result = img.copy() for angle in [0, 45, 90, 135]: motion = img.filter(ImageFilter.GaussianBlur(radius=1)) motion = motion.rotate(angle, expand=False) result = Image.blend(result, motion, alpha=0.1) return result except Exception as e: log_message(f"Erro Van Gogh: {e}") return image def apply_monet_style(image, intensity=0.8): try: img = image.convert('RGB') img = img.filter(ImageFilter.GaussianBlur(radius=1 + intensity)) enhancer = ImageEnhance.Brightness(img) img = enhancer.enhance(1.0 + intensity * 0.2) enhancer = ImageEnhance.Color(img) return enhancer.enhance(0.8 + intensity * 0.3) except Exception as e: return image def apply_picasso_style(image, intensity=0.8): try: img = image.convert('RGB') width, height = img.size result = Image.new('RGB', (width, height)) draw = ImageDraw.Draw(result) block_size = max(10, int(50 * (1 - intensity * 0.5))) for y in range(0, height, block_size): for x in range(0, width, block_size): block = img.crop((x, y, min(x + block_size, width), min(y + block_size, height))) avg_color = block.resize((1, 1)).getpixel((0, 0)) shape = (x + y) % 3 if shape == 0: points = [(x, y), (x + block_size, y), (x + block_size // 2, y + block_size)] draw.polygon(points, fill=avg_color) elif shape == 1: offset = block_size // 4 points = [(x + offset, y), (x + block_size, y), (x + block_size - offset, y + block_size), (x, y + block_size)] draw.polygon(points, fill=avg_color) else: draw.ellipse([x, y, x + block_size, y + block_size], fill=avg_color) return Image.blend(result, img, alpha=0.3) except Exception as e: return image def apply_warhol_style(image, intensity=0.8): try: img = image.convert('RGB') gray = img.convert('L') gray = gray.point(lambda x: 0 if x < 64 else 85 if x < 128 else 170 if x < 192 else 255) width, height = img.size result = Image.new('RGB', (width, height)) palettes = [ [(255, 0, 0), (255, 255, 0), (0, 255, 255), (255, 255, 255)], [(0, 255, 0), (255, 0, 255), (255, 255, 0), (0, 0, 0)], [(0, 0, 255), (255, 165, 0), (255, 192, 203), (255, 255, 255)], [(148, 0, 211), (255, 20, 147), (0, 255, 127), (255, 255, 0)] ] palette = palettes[int(intensity * 3) % 4] for y in range(height): for x in range(width): pixel = gray.getpixel((x, y)) color = palette[0 if pixel < 64 else 1 if pixel < 128 else 2 if pixel < 192 else 3] result.putpixel((x, y), color) enhancer = ImageEnhance.Contrast(result) return enhancer.enhance(1.5) except Exception as e: return image def apply_hokusai_style(image, intensity=0.8): try: img = image.convert('RGB') img = img.convert('P', palette=Image.ADAPTIVE, colors=32).convert('RGB') img = img.filter(ImageFilter.SMOOTH_MORE) r, g, b = img.split() b = b.point(lambda x: min(255, int(x * 1.3))) r = r.point(lambda x: int(x * 0.8)) return Image.merge('RGB', (r, g, b)) except Exception as e: return image def apply_starry_night_style(image, intensity=0.8): try: img = image.convert('RGB') enhancer = ImageEnhance.Brightness(img) img = enhancer.enhance(0.7) enhancer = ImageEnhance.Contrast(img) img = enhancer.enhance(1.3) r, g, b = img.split() b = b.point(lambda x: min(255, int(x * 1.2))) r = r.point(lambda x: int(x * 0.9)) return Image.merge('RGB', (r, g, b)) except Exception as e: return image def apply_oil_painting_style(image, intensity=0.8): try: img = image.convert('RGB') img = img.filter(ImageFilter.GaussianBlur(radius=0.5)) enhancer = ImageEnhance.Color(img) img = enhancer.enhance(1.0 + intensity * 0.4) enhancer = ImageEnhance.Contrast(img) return enhancer.enhance(1.0 + intensity * 0.3) except Exception as e: return image def apply_watercolor_style(image, intensity=0.8): try: img = image.convert('RGB') img = img.filter(ImageFilter.GaussianBlur(radius=1 + intensity)) enhancer = ImageEnhance.Color(img) img = enhancer.enhance(0.8 + intensity * 0.2) enhancer = ImageEnhance.Brightness(img) return enhancer.enhance(1.1) except Exception as e: return image def apply_sketch_style(image, intensity=0.8): try: img = image.convert('RGB') gray = img.convert('L') inverted = ImageOps.invert(gray) blurred = inverted.filter(ImageFilter.GaussianBlur(radius=2 + intensity)) result = Image.new('L', img.size) for y in range(img.height): for x in range(img.width): a = gray.getpixel((x, y)) b = blurred.getpixel((x, y)) result.putpixel((x, y), min(255, (a * 255) // (255 - b) if b < 255 else 255)) return result.convert('RGB') except Exception as e: return image def apply_comic_style(image, intensity=0.8): try: img = image.convert('RGB') enhancer = ImageEnhance.Contrast(img) img = enhancer.enhance(2.0) enhancer = ImageEnhance.Color(img) img = enhancer.enhance(1.5) edges = img.filter(ImageFilter.FIND_EDGES).convert('L') edges = edges.point(lambda x: 0 if x < 50 else 255) return Image.composite(Image.new('RGB', img.size, (0, 0, 0)), img, edges) except Exception as e: return image def apply_style(image, style_name, intensity=0.8): styles = { "van_gogh": apply_van_gogh_style, "monet": apply_monet_style, "picasso": apply_picasso_style, "warhol": apply_warhol_style, "hokusai": apply_hokusai_style, "starry_night": apply_starry_night_style, "oil_painting": apply_oil_painting_style, "watercolor": apply_watercolor_style, "sketch": apply_sketch_style, "comic": apply_comic_style } return styles.get(style_name, lambda i, _: i)(image, intensity) def create_comparison(original, styled, style_name): try: if original is None or styled is None: return None target_height = 400 orig_w = int(original.width * (target_height / original.height)) styled_w = int(styled.width * (target_height / styled.height)) orig_r = original.resize((orig_w, target_height), Image.Resampling.LANCZOS) styled_r = styled.resize((styled_w, target_height), Image.Resampling.LANCZOS) total_w = orig_r.width + styled_r.width + 20 comp = Image.new('RGB', (total_w, target_height + 60), (240, 240, 240)) draw = ImageDraw.Draw(comp) draw.text((10, 10), "ORIGINAL", fill=(100, 100, 100)) draw.text((orig_r.width + 30, 10), f"ESTILO: {style_name.upper()}", fill=(0, 100, 200)) comp.paste(orig_r, (0, 40)) comp.paste(styled_r, (orig_r.width + 20, 40)) return comp except Exception as e: return None def save_image(image): try: if image is None: return None temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png") image.save(temp_file.name, "PNG", optimize=True) return temp_file.name except Exception as e: return None # Interface Gradio with gr.Blocks(title="🎨 Style Transfer", theme=gr.themes.Soft()) as demo: gr.HTML("""

🎨 Style Transfer

Transforme suas fotos em obras de arte

""") with gr.Row(): with gr.Column(scale=1): gr.Markdown("### 📤 Upload") image_input = gr.Image(type="pil", label="Sua imagem") gr.Markdown("### 🎨 Estilo") with gr.Row(): s1 = gr.Button("🎨 Van Gogh", size="sm") s2 = gr.Button("🌅 Monet", size="sm") with gr.Row(): s3 = gr.Button("🧑‍🎨 Picasso", size="sm") s4 = gr.Button("👑 Warhol", size="sm") with gr.Row(): s5 = gr.Button("🌊 Hokusai", size="sm") s6 = gr.Button("✨ Noite Estrelada", size="sm") with gr.Row(): s7 = gr.Button("🖼️ Óleo", size="sm") s8 = gr.Button("🎨 Aquarela", size="sm") with gr.Row(): s9 = gr.Button("✏️ Lápis", size="sm") s10 = gr.Button("💥 HQ", size="sm") style_selected = gr.Textbox(value="van_gogh", visible=False) gr.Markdown("### ⚙️ Intensidade") intensity = gr.Slider(0.1, 1.0, 0.8, step=0.1, label="") apply_btn = gr.Button("✨ Aplicar Estilo", variant="primary", size="lg") with gr.Column(scale=1): status = gr.Markdown("**Status:** Aguardando imagem...") with gr.Tabs(): with gr.TabItem("🔄 Comparação"): comp_out = gr.Image(type="pil", label="Antes/Depois") with gr.TabItem("📷 Original"): orig_out = gr.Image(type="pil", label="Original") with gr.TabItem("🎨 Estilizada"): styled_out = gr.Image(type="pil", label="Estilizada") gr.Markdown("### 💾 Download") with gr.Row(): dl_styled = gr.Button("📥 Baixar Estilizada") dl_comp = gr.Button("📊 Baixar Comparação") dl_file = gr.File(label="Arquivo", interactive=False) with gr.Accordion("📖 Guia", open=False): gr.Markdown(""" ## Estilos Disponíveis: - **Van Gogh**: Pinceladas expressivas - **Monet**: Impressionismo suave - **Picasso**: Cubismo geométrico - **Warhol**: Pop Art vibrante - **Hokusai**: Ukiyo-e japonês - **Noite Estrelada**: Tons azulados - **Pintura a Óleo**: Textura clássica - **Aquarela**: Suave e transparente - **Desenho a Lápis**: Contornos - **Estilo HQ**: Bordas e cores planas """) # Eventos s1.click(fn=lambda: "van_gogh", outputs=[style_selected]) s2.click(fn=lambda: "monet", outputs=[style_selected]) s3.click(fn=lambda: "picasso", outputs=[style_selected]) s4.click(fn=lambda: "warhol", outputs=[style_selected]) s5.click(fn=lambda: "hokusai", outputs=[style_selected]) s6.click(fn=lambda: "starry_night", outputs=[style_selected]) s7.click(fn=lambda: "oil_painting", outputs=[style_selected]) s8.click(fn=lambda: "watercolor", outputs=[style_selected]) s9.click(fn=lambda: "sketch", outputs=[style_selected]) s10.click(fn=lambda: "comic", outputs=[style_selected]) def process(image, style, inten): if image is None: return None, None, None, "❌ Carregue uma imagem" valid_img, msg = validate_image(image) if valid_img is None: return None, None, None, f"❌ {msg}" if max(valid_img.size) > MAX_IMAGE_SIZE: valid_img = resize_image(valid_img, MAX_IMAGE_SIZE) styled = apply_style(valid_img, style, inten) comp = create_comparison(valid_img, styled, style) st = f"✅ Estilo {STYLES.get(style, style)} aplicado! Intensidade: {int(inten*100)}%" return valid_img, styled, comp, st apply_btn.click( fn=process, inputs=[image_input, style_selected, intensity], outputs=[orig_out, styled_out, comp_out, status] ) dl_styled.click(fn=save_image, inputs=[styled_out], outputs=[dl_file]) dl_comp.click(fn=save_image, inputs=[comp_out], outputs=[dl_file]) def on_upload(image): if image is None: return None, None, None, "**Status:** Aguardando..." valid, msg = validate_image(image) if valid is None: return None, None, None, f"❌ {msg}" return None, None, None, f"✅ Imagem carregada! Escolha um estilo." image_input.change(fn=on_upload, inputs=[image_input], outputs=[orig_out, styled_out, comp_out, status]) if __name__ == "__main__": log_message("✅ Iniciando...") demo.launch()