Gerando Imagens com Stable Diffusion via Python
Exemplo completo de geração de imagens com Stable Diffusion usando Python: instalação, prompts, parâmetros, img2img e otimizações.
O que vamos construir
Um gerador de imagens com IA que:
- Gera imagens a partir de descrições textuais (text-to-image)
- Modifica imagens existentes (image-to-image)
- Suporta estilos artísticos variados
- Funciona com GPU ou CPU (com otimizações)
- Inclui interface de linha de comando
Pré-requisitos
# Instalar dependências
pip install diffusers transformers accelerate torch
pip install Pillow safetensors
Código Completo
1. Gerador Básico (Text-to-Image)
"""
gerador_imagens.py - Geração de imagens com Stable Diffusion
"""
import torch
from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler
from PIL import Image
from pathlib import Path
from datetime import datetime
from dataclasses import dataclass
from typing import Optional
@dataclass
class ImageConfig:
"""Configuração para geração de imagem."""
prompt: str
negative_prompt: str = (
"blurry, bad quality, distorted, deformed, ugly, "
"low resolution, pixelated, watermark, text"
)
width: int = 512
height: int = 512
num_steps: int = 30
guidance_scale: float = 7.5
seed: Optional[int] = None
num_images: int = 1
class ImageGenerator:
"""Gerador de imagens com Stable Diffusion."""
def __init__(
self,
model_id: str = "stabilityai/stable-diffusion-2-1",
device: str = "auto",
use_fp16: bool = True,
):
# Detectar dispositivo
if device == "auto":
self.device = "cuda" if torch.cuda.is_available() else "cpu"
else:
self.device = device
print(f"🖥️ Dispositivo: {self.device}")
print(f"📥 Carregando modelo {model_id}...")
# Configurar precisão
dtype = torch.float16 if (use_fp16 and self.device == "cuda") else torch.float32
# Carregar pipeline
self.pipe = StableDiffusionPipeline.from_pretrained(
model_id,
torch_dtype=dtype,
safety_checker=None, # Desabilitar para uso local
)
# Otimizações
self.pipe.to(self.device)
if self.device == "cuda":
# Attention slicing para reduzir uso de VRAM
self.pipe.enable_attention_slicing()
# xformers se disponível
try:
self.pipe.enable_xformers_memory_efficient_attention()
print("✅ xformers ativado")
except Exception:
print("ℹ️ xformers não disponível")
# Scheduler mais rápido
self.pipe.scheduler = DPMSolverMultistepScheduler.from_config(
self.pipe.scheduler.config
)
print("✅ Modelo carregado!")
def gerar(self, config: ImageConfig) -> list[Image.Image]:
"""Gera imagens a partir de uma configuração."""
print(f"\n🎨 Gerando {config.num_images} imagem(ns)...")
print(f" Prompt: {config.prompt[:80]}...")
print(f" Tamanho: {config.width}x{config.height}")
print(f" Steps: {config.num_steps}")
# Configurar seed para reprodutibilidade
generator = None
if config.seed is not None:
generator = torch.Generator(device=self.device).manual_seed(config.seed)
print(f" Seed: {config.seed}")
# Gerar
start = datetime.now()
result = self.pipe(
prompt=config.prompt,
negative_prompt=config.negative_prompt,
width=config.width,
height=config.height,
num_inference_steps=config.num_steps,
guidance_scale=config.guidance_scale,
generator=generator,
num_images_per_prompt=config.num_images,
)
elapsed = (datetime.now() - start).total_seconds()
print(f" ⏱️ Tempo: {elapsed:.1f}s")
return result.images
def gerar_e_salvar(
self,
config: ImageConfig,
output_dir: str = "imagens_geradas",
prefix: str = "img",
) -> list[str]:
"""Gera e salva imagens em disco."""
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
images = self.gerar(config)
paths = []
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
for i, img in enumerate(images):
filename = f"{prefix}_{timestamp}_{i}.png"
filepath = output_path / filename
img.save(filepath)
paths.append(str(filepath))
print(f" 💾 Salvo: {filepath}")
return paths
2. Image-to-Image (Transformação)
"""
Transformação de imagens existentes com Stable Diffusion
"""
from diffusers import StableDiffusionImg2ImgPipeline
class ImageTransformer:
"""Transforma imagens existentes usando Stable Diffusion."""
def __init__(self, model_id: str = "stabilityai/stable-diffusion-2-1"):
self.device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.float16 if self.device == "cuda" else torch.float32
self.pipe = StableDiffusionImg2ImgPipeline.from_pretrained(
model_id,
torch_dtype=dtype,
safety_checker=None,
)
self.pipe.to(self.device)
if self.device == "cuda":
self.pipe.enable_attention_slicing()
def transformar(
self,
image: Image.Image,
prompt: str,
strength: float = 0.75,
guidance_scale: float = 7.5,
num_steps: int = 30,
) -> Image.Image:
"""
Transforma uma imagem existente.
strength: 0.0 = sem mudança, 1.0 = completamente nova
"""
# Redimensionar para múltiplo de 8
w, h = image.size
w = (w // 8) * 8
h = (h // 8) * 8
image = image.resize((w, h))
result = self.pipe(
prompt=prompt,
image=image,
strength=strength,
guidance_scale=guidance_scale,
num_inference_steps=num_steps,
)
return result.images[0]
# Exemplo de uso
def exemplo_img2img():
"""Transforma uma foto em pintura."""
transformer = ImageTransformer()
# Carregar imagem original
original = Image.open("foto_paisagem.jpg")
# Transformar em diferentes estilos
estilos = [
("Pintura a óleo impressionista, cores vibrantes, Monet", 0.6),
("Anime japonês, estilo studio ghibli, colorido", 0.7),
("Pixel art retro, 16-bit, colorido", 0.8),
]
for prompt, strength in estilos:
resultado = transformer.transformar(
image=original,
prompt=prompt,
strength=strength,
)
nome = prompt.split(",")[0].replace(" ", "_").lower()
resultado.save(f"resultado_{nome}.png")
print(f"✅ Salvo: resultado_{nome}.png")
3. Gerador com Estilos Predefinidos
class StylePresets:
"""Presets de estilos artísticos para geração de imagens."""
ESTILOS = {
"fotorrealista": {
"suffix": ", photorealistic, 8k resolution, highly detailed, professional photography, sharp focus, natural lighting",
"negative": "cartoon, anime, painting, drawing, illustration, cgi",
"steps": 40,
"guidance": 8.0,
},
"anime": {
"suffix": ", anime style, studio ghibli, vibrant colors, detailed, beautiful, masterpiece",
"negative": "realistic, photo, 3d render, ugly, bad anatomy",
"steps": 30,
"guidance": 7.0,
},
"oleo": {
"suffix": ", oil painting, classical art, detailed brushstrokes, rich colors, masterpiece, museum quality",
"negative": "photo, digital, modern, cartoon",
"steps": 35,
"guidance": 7.5,
},
"cyberpunk": {
"suffix": ", cyberpunk style, neon lights, futuristic, dark atmosphere, rain, detailed, cinematic",
"negative": "nature, bright, sunny, cartoon",
"steps": 30,
"guidance": 8.0,
},
"aquarela": {
"suffix": ", watercolor painting, soft colors, gentle brushstrokes, artistic, delicate, beautiful",
"negative": "photo, digital, sharp, 3d",
"steps": 25,
"guidance": 6.5,
},
"pixel_art": {
"suffix": ", pixel art, 16-bit, retro game style, colorful, nostalgic",
"negative": "realistic, 3d, blurry, smooth",
"steps": 25,
"guidance": 7.0,
},
"minimalista": {
"suffix": ", minimalist illustration, clean lines, simple shapes, modern design, flat colors",
"negative": "complex, detailed, realistic, noisy",
"steps": 25,
"guidance": 7.0,
},
}
@classmethod
def aplicar(cls, prompt: str, estilo: str) -> ImageConfig:
"""Aplica um estilo predefinido ao prompt."""
if estilo not in cls.ESTILOS:
estilos_disponiveis = ", ".join(cls.ESTILOS.keys())
raise ValueError(f"Estilo '{estilo}' não encontrado. Disponíveis: {estilos_disponiveis}")
preset = cls.ESTILOS[estilo]
return ImageConfig(
prompt=prompt + preset["suffix"],
negative_prompt=preset["negative"],
num_steps=preset["steps"],
guidance_scale=preset["guidance"],
)
@classmethod
def listar(cls):
"""Lista estilos disponíveis."""
print("\n🎨 Estilos disponíveis:")
for nome, config in cls.ESTILOS.items():
print(f" • {nome}: steps={config['steps']}, guidance={config['guidance']}")
4. CLI Interativo
def cli_interativo():
"""Interface de linha de comando para geração de imagens."""
print("=" * 60)
print("🎨 GERADOR DE IMAGENS COM IA")
print("=" * 60)
generator = ImageGenerator()
StylePresets.listar()
while True:
print("\n" + "-" * 40)
prompt = input("📝 Descreva a imagem (ou 'sair'): ").strip()
if prompt.lower() in ('sair', 'exit', 'quit'):
print("👋 Até mais!")
break
if not prompt:
continue
# Escolher estilo
estilo = input("🎨 Estilo (enter para fotorrealista): ").strip() or "fotorrealista"
# Configurar
try:
config = StylePresets.aplicar(prompt, estilo)
except ValueError as e:
print(f"❌ {e}")
continue
# Seed opcional
seed_input = input("🎲 Seed (enter para aleatório): ").strip()
if seed_input:
config.seed = int(seed_input)
# Gerar
paths = generator.gerar_e_salvar(config)
print(f"\n✅ {len(paths)} imagem(ns) gerada(s)!")
for p in paths:
print(f" 📁 {p}")
5. Geração via API
"""
Alternativa: usar API para geração sem GPU local
"""
import requests
import base64
from io import BytesIO
class APIImageGenerator:
"""Gera imagens via API (Stability AI, DALL-E, etc.)."""
def __init__(self, api_key: str, provider: str = "stability"):
self.api_key = api_key
self.provider = provider
def gerar_stability(self, prompt: str, **kwargs) -> Image.Image:
"""Gera imagem via Stability AI API."""
response = requests.post(
"https://api.stability.ai/v1/generation/stable-diffusion-xl-1024-v1-0/text-to-image",
headers={
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
},
json={
"text_prompts": [{"text": prompt, "weight": 1.0}],
"cfg_scale": kwargs.get("guidance", 7),
"height": kwargs.get("height", 1024),
"width": kwargs.get("width", 1024),
"steps": kwargs.get("steps", 30),
"samples": 1,
},
)
if response.status_code != 200:
raise Exception(f"Erro na API: {response.text}")
data = response.json()
img_data = base64.b64decode(data["artifacts"][0]["base64"])
return Image.open(BytesIO(img_data))
def gerar_openai(self, prompt: str, **kwargs) -> Image.Image:
"""Gera imagem via OpenAI DALL-E API."""
from openai import OpenAI
client = OpenAI(api_key=self.api_key)
response = client.images.generate(
model="dall-e-3",
prompt=prompt,
size=kwargs.get("size", "1024x1024"),
quality=kwargs.get("quality", "standard"),
n=1,
)
# Baixar imagem
img_url = response.data[0].url
img_response = requests.get(img_url)
return Image.open(BytesIO(img_response.content))
6. Exemplo Principal
def main():
"""Demonstração completa do gerador de imagens."""
print("🎨 Gerador de Imagens com Stable Diffusion\n")
generator = ImageGenerator()
# Exemplo 1: Paisagem fotorrealista
config1 = StylePresets.aplicar(
"A beautiful tropical beach in Brazil with palm trees and crystal clear water",
"fotorrealista"
)
config1.seed = 42
generator.gerar_e_salvar(config1, prefix="praia")
# Exemplo 2: Personagem anime
config2 = StylePresets.aplicar(
"A young programmer coding on a laptop in a cozy room",
"anime"
)
generator.gerar_e_salvar(config2, prefix="programador")
# Exemplo 3: Cidade cyberpunk
config3 = StylePresets.aplicar(
"A futuristic São Paulo skyline with flying cars and neon signs",
"cyberpunk"
)
generator.gerar_e_salvar(config3, prefix="sp_futuro")
print("\n✅ Todas as imagens foram geradas!")
print("📁 Verifique a pasta 'imagens_geradas/'")
if __name__ == "__main__":
# CLI interativo ou exemplos
import sys
if "--cli" in sys.argv:
cli_interativo()
else:
main()
Como Rodar
# Com GPU NVIDIA (recomendado)
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121
pip install diffusers transformers accelerate
# Apenas CPU (mais lento)
pip install torch torchvision
pip install diffusers transformers accelerate
# Executar exemplos
python gerador_imagens.py
# Modo interativo
python gerador_imagens.py --cli
Dicas de Prompts
| Objetivo | Prompt | |----------|--------| | Mais detalhe | Adicione "highly detailed, 8k, sharp focus" | | Iluminação | "golden hour lighting", "studio lighting", "dramatic shadows" | | Composição | "rule of thirds", "centered composition", "wide angle" | | Qualidade | "masterpiece, best quality, professional" |
Requisitos de Hardware
| Configuração | VRAM | Tempo por imagem | |--------------|------|------------------| | RTX 4090 | 24GB | ~3s (512x512) | | RTX 3060 | 12GB | ~10s (512x512) | | CPU (i7) | RAM 16GB+ | ~3-5min (512x512) |
Expansões Possíveis
- ControlNet: controlar pose, bordas e profundidade da imagem
- Inpainting: editar partes específicas de uma imagem
- LoRA: usar modelos fine-tunados para estilos específicos
- Upscaling: aumentar resolução com Real-ESRGAN
- Batch: gerar múltiplas variações de um mesmo prompt
- Web UI: interface gráfica com Gradio ou Streamlit
Geração de imagens com IA é uma das aplicações mais impressionantes de deep learning — e com Stable Diffusion, tudo isso roda na sua própria máquina! 🎨