Como criar um gerador de imagens com IA em Python (passo a passo)

Escreva um script em Python que envia um prompt de texto para um modelo de imagem, aguarda o processamento e salva a imagem. Monte-o em quatro etapas e depois adicione uma linha de comando, lotes com threads, uma rota no Flask e correções para os erros que você vai encontrar.

Como criar um gerador de imagens com IA em Python (passo a passo)
Cristian Da Conceicao
Fundador do Picasso IA

A maioria dos tutoriais sobre imagens com IA para em "cole um prompt em um site". Isso funciona para uma imagem só. Mas deixa de funcionar quando você precisa de cinquenta fotos de produtos, um lote noturno de miniaturas para o blog ou um pequeno app em que visitantes digitam uma frase e recebem uma fotografia de volta. Para isso você precisa de código, e a boa notícia é que um gerador de imagens funcional em Python cabe em cerca de 60 linhas.

Este tutorial monta o gerador em quatro etapas pequenas: enviar um prompt para um modelo hospedado, aguardar o término do processamento, baixar o arquivo e, por fim, envolver tudo em uma ferramenta de linha de comando que roda lotes. Cada etapa termina com uma verificação rápida, para que você saiba que funciona antes de avançar.

💡 Resposta rápida: um gerador de imagens com IA em Python é um script que envia um prompt de texto para um modelo via HTTP, consulta o status até a imagem ficar pronta e então salva o arquivo. O modelo roda na GPU de outra pessoa. Seu código precisa de requests, de um token secreto e de um loop.

Antes de escrever qualquer linha

Mãos de um desenvolvedor digitando código Python em um notebook sobre uma mesa de madeira

Você precisa de três coisas: Python 3.10 ou mais recente, um terminal e um token secreto para o serviço de imagens. O código abaixo conversa com a API do PicassoIA por HTTP simples, então não há driver de GPU para instalar nem arquivo de modelo para baixar.

Configure o projeto

Crie uma pasta, um ambiente virtual e instale um único pacote:

mkdir ai-image-generator && cd ai-image-generator
python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install requests

Em seguida, crie um token na página da API e guarde-o em uma variável de ambiente, e não no arquivo de código. Uma conta pode ter até dois tokens ao mesmo tempo.

export PICASSOIA_API_TOKEN="pia_sk_your_token_here"

No PowerShell do Windows, a mesma linha fica $env:PICASSOIA_API_TOKEN = "pia_sk_your_token_here".

⚠️ Nunca cole o token no seu script. Tudo o que vai para o git fica no histórico, mesmo depois de você apagar. Uma variável de ambiente mantém o segredo fora do repositório.

Escolha primeiro um modelo

O modelo define como suas imagens ficam e a velocidade com que chegam. O script deste tutorial chama picassoia/picassoia-image pela API. Os modelos da tabela abaixo estão todos disponíveis no navegador, no PicassoIA, o que os torna úteis para testar prompts antes de levá-los ao código.

ModeloMelhor uso
P ImageRascunhos fotorrealistas rápidos, em torno de um segundo por imagem
Flux 2 ProImagens detalhadas a partir de texto ou de fotos de referência
Flux DevCenas e retratos fotorrealistas
Stable Diffusion 3.5 LargeImagens HD nítidas com muito detalhe
Imagen 4 FastResultados rápidos em poucos segundos
Seedream 4.5Saída em alta resolução, até 4K
SDXL Lightning 4StepPré-visualizações muito rápidas

Como o texto vira imagem

Um modelo de difusão parte de ruído aleatório e o remove em muitas pequenas passagens, guiado pelo seu prompt em cada uma delas. Cada passagem é um cálculo pesado em uma rede neural grande. É por isso que a geração de imagens exige uma GPU potente, e por que a primeira decisão de design no seu projeto em Python é onde essa GPU vai ficar.

Fileiras de racks de servidores pretos em um corredor silencioso de data center

GPU local ou API hospedada. Rodar um modelo na sua própria máquina dá controle total, mas também significa um conjunto de drivers, dezenas de gigabytes de pesos e uma placa com bastante memória. Uma API hospedada troca parte desse controle por uma configuração que leva minutos.

Close-up de uma placa de vídeo de desktop com tubos de calor de cobre dentro de um gabinete aberto

FatorGPU localAPI hospedada
Tempo de configuraçãoHorasMinutos
HardwarePlaca de vídeo recente com 12 GB ou mais de memóriaQualquer notebook
Escolha de modeloO que você baixarO que o serviço oferecer
EscalabilidadeComprar outra placaAumentar sua concorrência
Dependências do PythonPesadasApenas requests

Por que os trabalhos são assíncronos. Gerar uma imagem leva de menos de um segundo a cerca de um minuto, dependendo do modelo. Manter uma conexão HTTP aberta por todo esse tempo é frágil, então a API funciona em três movimentos: criar uma previsão, consultar seu status e buscar o resultado quando o status indicar succeeded. Seu código reproduz esses três movimentos na próxima seção.

Passo a passo: o primeiro script

Coloque tudo em um único arquivo chamado generate.py. As quatro etapas abaixo o constroem de cima a baixo.

Etapa 1: configure a requisição

A API segue o padrão do Replicate: uma URL base, o nome do modelo no caminho e um token Bearer no cabeçalho.

import os
import time
from pathlib import Path

import requests

API_BASE = "https://api.picassoia.com/v1"
MODEL = "picassoia/picassoia-image"
TOKEN = os.environ["PICASSOIA_API_TOKEN"]
HEADERS = {
    "Authorization": f"Bearer {TOKEN}",
    "Content-Type": "application/json",
}

Se a variável estiver ausente, o Python para com um erro logo aqui, que é exatamente o que você quer. Uma falha clara no topo do arquivo é melhor do que um 401 confuso mais adiante.

Etapa 2: envie o prompt

def create_prediction(prompt: str) -> str:
    url = f"{API_BASE}/models/{MODEL}/predictions"
    payload = {"input": {"prompt": prompt}}
    response = requests.post(url, headers=HEADERS, json=payload, timeout=30)
    response.raise_for_status()
    return response.json()["id"]

A função devolve um ID de trabalho, não uma imagem. Os prompts podem ter até 4.000 caracteres, bem mais do que você vai precisar.

Etapa 3: consulte até terminar

def wait_for_result(job_id: str, poll_every: float = 2.0, limit: float = 300.0) -> str:
    url = f"{API_BASE}/predictions/{job_id}"
    deadline = time.time() + limit
    while time.time() < deadline:
        response = requests.get(url, headers=HEADERS, timeout=30)
        response.raise_for_status()
        data = response.json()
        status = data["status"]
        if status == "succeeded":
            output = data["output"]
            return output[0] if isinstance(output, list) else output
        if status in ("failed", "canceled"):
            raise RuntimeError(f"Job {job_id} ended as {status}: {data.get('error')}")
        time.sleep(poll_every)
    raise TimeoutError(f"Job {job_id} did not finish within {limit} seconds")

💡 Dica: os nomes dos campos seguem o formato do Replicate. Se alguma resposta parecer diferente, imprima response.json() uma vez e ajuste as duas linhas que contêm status e output. O loop também define seu próprio prazo, então um trabalho travado nunca congela o script.

Etapa 4: salve o arquivo

def download(image_url: str, folder: str = "output") -> Path:
    Path(folder).mkdir(exist_ok=True)
    name = image_url.split("/")[-1].split("?")[0] or f"image-{int(time.time())}.png"
    target = Path(folder) / name
    response = requests.get(image_url, timeout=60)
    response.raise_for_status()
    target.write_bytes(response.content)
    return target


if __name__ == "__main__":
    prompt = "A misty mountain lake at sunrise, 35mm photograph, soft natural light, fine film grain"
    job_id = create_prediction(prompt)
    image_url = wait_for_result(job_id)
    print("Saved", download(image_url))

Vista por cima do ombro de uma janela de terminal ao lado de uma foto de praia na hora dourada

Execute python generate.py. Depois de alguns segundos você deve ver Saved output/... e um novo arquivo na pasta output. Checkpoint: se você consegue abrir essa imagem, as etapas 1 a 4 funcionam, e tudo o que vem depois é apenas empacotamento.

Transforme o script em uma ferramenta

Adicione uma linha de comando

Substitua o final do arquivo por um ponto de entrada argparse para que você possa passar prompts pelo terminal:

import argparse


def main() -> None:
    parser = argparse.ArgumentParser(description="Generate an image from a text prompt")
    parser.add_argument("prompt", help="what the image should show")
    parser.add_argument("--out", default="output", help="folder for saved files")
    args = parser.parse_args()

    image_url = wait_for_result(create_prediction(args.prompt))
    print(download(image_url, args.out))


if __name__ == "__main__":
    main()

Agora python generate.py "a red bicycle leaning on a brick wall, 50mm photo" --out bikes faz todo o trabalho em uma linha.

Rode lotes dentro dos limites

Um loop que espera cada imagem na sequência é lento. As threads resolvem isso, porque o script passa quase todo o tempo esperando pela rede. A API permite 5 previsões simultâneas por conta, compartilhadas entre seus tokens e quaisquer apps conectados, então cinco workers é o teto.

from multiprocessing.pool import ThreadPool


def generate(prompt: str) -> Path:
    return download(wait_for_result(create_prediction(prompt)))


def run_batch(prompts: list[str]) -> list[Path]:
    with ThreadPool(5) as pool:
        return pool.map(generate, prompts)

Fotógrafo examinando uma folha de contato impressa com pequenos quadros de paisagens e retratos

Se você também usar o site enquanto um lote roda, reduza para três workers para que os dois não disputem as mesmas cinco vagas. Um prompt que falha gera um erro dentro de pool.map, então envolva generate em um bloco try que registra o prompt e devolve None quando você roda centenas de uma vez.

Mantenha um registro. Acrescente cada prompt e nome de arquivo a um arquivo log.jsonl, para que você consiga rastrear qualquer imagem até o texto que a gerou. Chame essa função auxiliar dentro de generate, logo depois de download:

import json


def log_result(prompt: str, path: Path) -> None:
    with open("log.jsonl", "a", encoding="utf-8") as log:
        log.write(json.dumps({"prompt": prompt, "file": str(path)}) + "\n")

Daqui a seis semanas, quando alguém perguntar qual prompt gerou a foto do nascer do sol, esse arquivo responde em segundos.

Exponha como uma rota web

Equipes raramente querem um terminal. Um pequeno app em Flask permite que qualquer pessoa envie um prompt por uma página. Repare que a rota devolve o ID do trabalho imediatamente e uma segunda rota informa o progresso, então nenhuma requisição web fica travada por um minuto.

from flask import Flask, jsonify, request

app = Flask(__name__)


@app.post("/generate")
def start():
    prompt = request.get_json()["prompt"]
    return jsonify(id=create_prediction(prompt))


@app.get("/status/<job_id>")
def status(job_id):
    url = f"{API_BASE}/predictions/{job_id}"
    data = requests.get(url, headers=HEADERS, timeout=30).json()
    return jsonify(status=data["status"], output=data.get("output"))

Três colegas reunidos em volta de um monitor que mostra uma grade de miniaturas fotográficas

Seu front-end chama /generate e depois consulta /status/<id> a cada dois segundos até que status seja succeeded. O token fica no servidor, nunca no código do navegador.

Escreva prompts que se comportam bem

Vista de cima de uma mesa com notebook, esboços em cadernos e fotografias impressas

Monte prompts a partir de partes

Prompts vagos geram imagens vagas. Um prompt com um sujeito, um lugar, uma fonte de luz e uma lente resulta em algo repetível. Coloque essa estrutura em uma função para que cada imagem de um lote siga o mesmo padrão:

def build_prompt(subject: str, setting: str, light: str, lens: str = "50mm f/1.8") -> str:
    return (
        f"{subject}, {setting}, {light}, shot on a {lens} lens, "
        "natural skin and surface texture, fine film grain, photorealistic"
    )


print(build_prompt("a ceramic mug of black coffee", "on an oak desk", "soft window light from the left"))

Três hábitos tornam os resultados mais previsíveis:

  • Uma cena por prompt. Dois sujeitos disputando a atenção produzem imagens confusas.
  • Nomeie a luz. "Luz volumétrica da manhã vinda da esquerda" supera "iluminação bonita".
  • Nomeie a lente. Termos como 85mm e f/1.8 empurram o modelo para uma profundidade de campo rasa.

Faça um brainstorm com um modelo de linguagem

Escrever 50 prompts à mão fica cansativo lá pelo prompt doze. Um modelo de linguagem pode rascunhá-los para você. O Claude Sonnet 5 lida bem com listas estruturadas, e o Gemini 3.5 Flash devolve rascunhos rápidos quando você só precisa de volume. Peça 20 prompts que sigam a estrutura de sujeito, cenário, luz e lente, um por linha, e salve a resposta como prompts.txt. Depois, passe o arquivo para o seu executor de lotes:

prompts = [line.strip() for line in Path("prompts.txt").read_text().splitlines() if line.strip()]
run_batch(prompts)

Como usar o P Image no PicassoIA

Antes de gastar tempo com código, teste sua redação no navegador. O P Image responde em cerca de um segundo, então você pode testar dez variações no tempo que um modelo mais lento leva para renderizar um único resultado.

  1. Abra a página do modelo e encontre a caixa de prompt.
  2. Cole um prompt montado com o sujeito, o cenário, a luz e a estrutura de lente da seção anterior.
  3. Escolha a proporção 16:9 para imagens de artigos, ou 1:1 para miniaturas.
  4. Gere três variações e mude apenas um detalhe entre elas. Isso mostra qual palavra fez o trabalho.
  5. Copie a redação vencedora para prompts.txt ou para a sua chamada de build_prompt.

💡 Se houver um campo de seed disponível, fixe a seed enquanto compara as redações. Com a seed travada, qualquer mudança no resultado vem do seu prompt e de mais nada.

Quando o P Image der o enquadramento certo, mas não o acabamento certo, rode o mesmo prompt pelo Flux 2 Pro ou pelo Seedream 4.5 e compare os resultados lado a lado. Cada modelo tem seus próprios hábitos, e dez minutos de teste economizam horas de reescrita depois.

Corrija os erros que você vai encontrar

Erros de autenticação

Um 401 ou 403 quase sempre significa que o token nunca chegou à requisição. Verifique se PICASSOIA_API_TOKEN está definida no mesmo terminal que executa o Python, já que uma variável exportada em uma janela não existe em outra. Verifique também se há aspas sobrando ou um espaço no fim do valor.

Limites e trabalhos travados

SintomaCausa provávelCorreção
Resposta 429Mais de 5 trabalhos rodando ao mesmo tempoReduza ThreadPool para 3 ou 4 e tente de novo após uma pausa curta
Resposta 400Prompt com mais de 4.000 caracteres ou nome de campo erradoEncurte o prompt e imprima o corpo do erro
Trabalho nunca terminaFila pesada ou trabalho travadoMantenha o prazo de limit e tente uma vez mais
Status failedO modelo rejeitou o promptSimplifique e remova símbolos incomuns

Para as novas tentativas, espere um pouco mais após cada falha (2, 4 e depois 8 segundos) e desista após três tentativas. Bombardear a API com novas tentativas instantâneas só mantém você acima do limite.

Resultados suaves ou borrados

Mulher examinando uma grande fotografia de paisagem impressa em uma prancheta de desenho

Se o enquadramento está certo, mas o detalhe está suave, a causa geralmente é a resolução, não o prompt. Escolha um modelo que entregue alta resolução, como o Seedream 4.5, ou passe a imagem final por um modelo de Super Resolution no PicassoIA para aumentá-la de 2x a 4x. Verifique também se o prompt nomeia uma câmera e uma lente, já que "fotografia" sozinho deixa aberto demais.

Faça sua primeira imagem hoje

Homem de suéter cinza-carvão segurando um tablet com uma foto de trilha na floresta iluminada pelo sol em um café

Agora você tem um script que transforma uma frase em uma fotografia, um executor de lotes que respeita o limite de cinco trabalhos e um modelo de prompt que você pode reutilizar em todos os projetos. O próximo passo mais rápido é pequeno: abra o P Image no navegador, teste três prompts, cole a melhor redação em prompts.txt e rode o lote.

Quando quiser escalar, a página da API do PicassoIA lista os endpoints, e a lista completa de modelos mostra os modelos de texto para imagem, vídeo e fala que você pode testar em seguida. O mesmo loop de criar, consultar e baixar funciona também para trabalhos de vídeo, então o script que você escreveu hoje é a base de um gerador de clipes amanhã. Escolha um prompt, rode o script e veja o que aparece na sua pasta de saída.

Compartilhe este artigo

Escolha seu idioma