Gemini API Image Understanding: entrada de imagem e imagem para texto em Python

Envie uma foto para a API do Gemini a partir do Python e receba texto de volta. Este artigo mostra bytes inline, a Files API e prompts com várias imagens, depois transforma a mesma chamada em legendas, OCR de recibos e caixas delimitadoras, com cálculo de tokens, limites de tamanho e correções para erros comuns.

Gemini API Image Understanding: entrada de imagem e imagem para texto em Python
Cristian Da Conceicao
Fundador do Picasso IA

Você tem uma foto e precisa de palavras. Uma imagem de produto que precisa de texto alternativo, um recibo que precisa do total, uma prateleira que precisa de contagem. A API do Gemini aceita a imagem como parte do prompt e devolve texto, então todo o trabalho cabe em uma única chamada em Python de cerca de dez linhas. Este artigo segue a ordem em que os problemas realmente aparecem: configuração, três formas de enviar uma imagem, prompts que retornam texto utilizável, custos em tokens e os erros que desperdiçam requisições.

Uma mudança importa para o código abaixo. A documentação atual do Google mostra a entrada de imagem pela Interactions API (client.interactions.create) e marca o método mais antigo, generateContent, como legado, embora confirme que ele continua totalmente suportado. As duas versões aparecem aqui, para que você possa colar a que corresponde ao seu projeto.

O que a entrada de imagem faz de fato

Mulher segurando um celular sobre uma foto impressa de mercado ao lado de um notebook

Os modelos Gemini são multimodais, o que significa que uma única requisição pode conter partes de texto e partes de imagem lado a lado. Você envia uma foto mais uma instrução, e o modelo responde em texto. Não há endpoint de visão separado, nenhuma etapa de pré-processamento e nenhuma biblioteca de OCR para instalar antes. A imagem é apenas mais uma parte do prompt.

Imagem para texto em uma requisição

O mesmo padrão de chamada resolve trabalhos bem diferentes, dependendo da instrução que você anexa:

  • Legendagem: uma frase para uma postagem em redes sociais ou a descrição de uma página.
  • Texto alternativo: descrições curtas e literais para acessibilidade.
  • Perguntas visuais: "Quantas cadeiras há na mesa?" ou "O rótulo está virado para frente?"
  • OCR: texto extraído de recibos, placas, formulários e anotações manuscritas.
  • Detecção: caixas delimitadoras com rótulos, retornadas como JSON.
  • Comparação: diferenças entre duas ou mais imagens.

💡 Trate a instrução como o produto. O modelo é o mesmo em todos os casos. O prompt decide se você recebe um poema sobre uma foto ou um total limpo em JSON.

Modelos que aceitam imagens

A página de modelos do Google lista estes IDs atuais, todos com entrada de imagem:

ID do modeloStatusDescrição do Google
gemini-3.8-flashEstávelModelo Flash mais inteligente
gemini-3.7-flashEstávelProgramação complexa e fluxos de trabalho agênticos
gemini-3.6-flashEstávelTrabalho multimodal geral
gemini-3.5-flash (Gemini 3.5 Flash)EstávelCargas de trabalho de alta vazão
gemini-3.1-pro-preview (Gemini 3.1 Pro)PréviaResolução de problemas complexos
gemini-3-flash-preview (Gemini 3 Flash)PréviaTarefas multimodais

As linhas de modelos mudam rápido, então confira a página de modelos antes de fixar um ID em produção. Para trabalho com imagens, um modelo Flash é o padrão sensato. Passe para um modelo Pro somente quando as respostas sobre digitalizações densas ou cenas complicadas vierem erradas.

Configure seu ambiente Python

Notebook de desenvolvedor sobre uma mesa de nogueira com um terminal aberto ao entardecer

Dois minutos de configuração agora economizam uma tarde de erros de importação confusos depois.

Instale o SDK

O pacote oficial é google-genai. Os exemplos abaixo também usam Pydantic para saída estruturada e Pillow para desenhar as caixas.

pip install -U google-genai pydantic pillow

Não confunda com o pacote google-generativeai, mais antigo. O novo é importado como from google import genai, e todos os trechos aqui partem dele.

Crie o cliente

Gere uma credencial no Google AI Studio, armazene-a na variável de ambiente indicada na página de configuração do Google e mantenha-a fora do controle de versão. O cliente a lê automaticamente:

from google import genai

client = genai.Client()

Sem argumentos, sem segredos fixos no script. Todo exemplo a seguir reutiliza este client.

Envie uma imagem de três formas

Escolha o método pelo tamanho do arquivo e pelo reuso, não pelo hábito.

Bytes inline para arquivos pequenos

Entrada de cartão de memória de câmera com cópias de uma cidade portuária atrás

Os dados inline são o caminho mais curto. Você lê o arquivo, codifica e envia junto com o prompt. A versão atual da Interactions API fica assim:

import base64
from pathlib import Path

image_bytes = Path("street-market.jpg").read_bytes()

interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {"type": "text", "text": "Caption this image in one sentence."},
        {
            "type": "image",
            "data": base64.b64encode(image_bytes).decode("utf-8"),
            "mime_type": "image/jpeg",
        },
    ],
)

print(interaction.output_text)

A versão generateContent legada continua válida e um pouco mais curta, porque o SDK cuida da codificação:

from google.genai import types

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=[
        types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg"),
        "Caption this image in one sentence.",
    ],
)

print(response.text)

Os dados inline limitam o total da requisição (texto do prompt, instruções do sistema e bytes da imagem somados) a 20 MB. Uma foto de celular cabe com folga. Um lote de digitalizações em resolução total não cabe.

Files API para imagens maiores

Fotógrafo ao lado de uma grande cópia de lago de montanha segurando um HD externo

Quando a requisição ultrapassaria 20 MB, ou quando você quer fazer várias perguntas sobre a mesma imagem, envie o arquivo uma vez e referencie-o pela URI:

uploaded = client.files.upload(file="mountain-lake-print.jpg")

interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {"type": "text", "text": "Describe the scene and list any visible text."},
        {
            "type": "image",
            "uri": uploaded.uri,
            "mime_type": uploaded.mime_type,
        },
    ],
)

print(interaction.output_text)

Os arquivos enviados ficam armazenados temporariamente, então trate a Files API como um mecanismo de entrega, não como arquivo morto. Guarde seus originais.

Várias imagens em um prompt

Duas cópias quase idênticas de uma sala de estar com uma diferença destacada

Adicione mais partes de imagem à mesma lista input. A documentação do Google permite até 3.600 arquivos de imagem em uma requisição.

before = client.files.upload(file="living-room-before.jpg")
after = client.files.upload(file="living-room-after.jpg")

interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {
            "type": "text",
            "text": "The first image is BEFORE and the second is AFTER. "
                    "What is different between them?",
        },
        {"type": "image", "uri": before.uri, "mime_type": before.mime_type},
        {"type": "image", "uri": after.uri, "mime_type": after.mime_type},
    ],
)

print(interaction.output_text)

Diga no texto qual imagem é qual. O modelo vê uma lista ordenada, e um simples "compare estas" o deixa adivinhando os papéis.

Prompts que transformam fotos em texto

A chamada nunca muda. Só a instrução muda.

ObjetivoPadrão do promptFormato da saída
Legenda"Legende esta imagem em uma frase."Texto simples
Texto alternativo"Escreva um texto alternativo com menos de 125 caracteres. Descreva apenas o que está visível."Texto simples
Pergunta visual"Quantas caixas vermelhas há na prateleira da esquerda?"Resposta curta
Extração"Extraia estabelecimento, data e total."JSON via schema
Detecção"Detecte todos os itens de destaque na imagem."JSON via schema

Legendas e texto alternativo

Editor web escrevendo texto alternativo em um caderno ao lado de um monitor

O maior ganho de qualidade vem das restrições. "Descreva esta imagem" retorna um parágrafo. "Escreva um texto alternativo com menos de 125 caracteres, sem frase de abertura como 'imagem de'" retorna algo que você pode publicar.

prompt = (
    "Write alt text for this photo in under 125 characters. "
    "Describe only what is visible. Do not start with 'image of'."
)

Rode isso sobre uma pasta de fotos com um laço simples e você terá um primeiro rascunho de cada atributo alt que falta em um site. Uma pessoa ainda precisa ler os rascunhos, porque um modelo pode julgar mal o que importa em uma cena.

OCR e recibos

Recibos amassados e uma lista manuscrita sobre o balcão de um café

Recibos são um bom teste porque misturam texto impresso, números e dobras. Peça saída estruturada em vez de prosa. Defina o formato com Pydantic e passe seu JSON schema por meio de response_format:

from pydantic import BaseModel

class LineItem(BaseModel):
    name: str
    price: float

class Receipt(BaseModel):
    merchant: str
    date: str
    items: list[LineItem]
    total: float

receipt = client.files.upload(file="receipt.jpg")

interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {
            "type": "text",
            "text": "Extract the merchant, date, line items, and total.",
        },
        {"type": "image", "uri": receipt.uri, "mime_type": receipt.mime_type},
    ],
    response_format={
        "type": "text",
        "mime_type": "application/json",
        "schema": Receipt.model_json_schema(),
    },
)

data = Receipt.model_validate_json(interaction.output_text)
print(data.merchant, data.total)

Se o modelo retornar algo que não se encaixa no schema, model_validate_json gera um erro ali mesmo, em vez de deixar dados ruins escorregarem para o seu banco de dados.

Detecção de objetos com caixas

Corredor de mercado com caixotes de laranjas, tomates e pimentões

O Gemini pode retornar caixas delimitadoras como [ymin, xmin, ymax, xmax], normalizadas em uma escala de 0 a 1000. Peça-as com um schema, depois converta para pixels e desenhe:

from PIL import Image, ImageDraw
from pydantic import BaseModel, Field

class Box(BaseModel):
    box_2d: list[int] = Field(
        description="[ymin, xmin, ymax, xmax] normalized to 0-1000."
    )
    label: str

class Boxes(BaseModel):
    boxes: list[Box]

aisle = client.files.upload(file="grocery-aisle.jpg")

interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {"type": "text", "text": "Detect all of the prominent items in the image."},
        {"type": "image", "uri": aisle.uri, "mime_type": aisle.mime_type},
    ],
    response_format={
        "type": "text",
        "mime_type": "application/json",
        "schema": Boxes.model_json_schema(),
    },
)

result = Boxes.model_validate_json(interaction.output_text)

image = Image.open("grocery-aisle.jpg")
width, height = image.size
draw = ImageDraw.Draw(image)

for item in result.boxes:
    ymin, xmin, ymax, xmax = item.box_2d
    left, top = xmin / 1000 * width, ymin / 1000 * height
    right, bottom = xmax / 1000 * width, ymax / 1000 * height
    draw.rectangle((left, top, right, bottom), outline="red", width=4)
    draw.text((left + 6, top + 6), item.label, fill="red")

image.save("grocery-aisle-boxes.jpg")

A segmentação segue o mesmo padrão. O schema adiciona um campo mask com os pontos do polígono, também normalizados de 0 a 1000. O Google recomenda definir o nível de raciocínio como minimal para segmentação, já que o raciocínio estendido adiciona latência sem melhorar os polígonos.

Limites, tokens e custos

Folha de contato com pequenos quadros sobre uma mesa de luz com uma lupa

As imagens são cobradas em tokens, e a contagem depende do tamanho. Conhecer a regra permite prever a cobrança antes do lote rodar.

Como as imagens contam como tokens

Situação da imagemCusto em tokens
Ambas as dimensões com 384 px ou menos258 tokens
Imagem maiorDividida em blocos de 768 x 768 px, 258 tokens por bloco
Exemplo: uma imagem que se divide em quatro blocos4 x 258 = 1.032 tokens

A documentação também descreve uma configuração media_resolution que limita o número máximo de tokens alocados a cada imagem de entrada. Reduza-a em legendagem em massa, quando detalhes finos não importam. Aumente-a quando letras pequenas ou objetos distantes forem relevantes. Confira a referência atual para saber como a sua versão do SDK escreve a opção.

O preço varia por modelo, então consulte a página de preços do Google para ver os números. A alavanca que você controla é a contagem de tokens, e enviar uma cópia menor do arquivo é a forma mais barata de reduzi-la.

Limites de formato e tamanho

LimiteValor
Formatos suportadosPNG, JPEG, WEBP, HEIC, HEIF
Imagens por requisiçãoAté 3.600 arquivos
Tamanho da requisição inline20 MB no total (texto, instruções e bytes)
Escala das caixas delimitadoras0 a 1000, ordem [ymin, xmin, ymax, xmax]

💡 Se um trabalho envia muitas imagens com um prompt longo, some o total inline antes de bater no limite de 20 MB. Mudar para a Files API no meio do projeto é fácil, mas fazer isso cedo evita uma falha intermitente às 2 da manhã.

Três erros que desperdiçam chamadas

A maioria das requisições com falha vem da mesma lista curta.

Tipo MIME errado

O mime_type precisa corresponder ao arquivo real. Rotular um PNG como image/jpeg ou enviar um formato não suportado gera erros ou resultados ruins. Deixe o Python decidir em vez de digitar strings à mão:

import mimetypes

def mime_for(path: str) -> str:
    mime, _ = mimetypes.guess_type(path)
    if mime is None:
        raise ValueError(f"Unknown image type: {path}")
    return mime

Alguns sistemas não reconhecem o tipo HEIC, então acrescente um pequeno mapeamento manual se você aceita originais de iPhone.

Caixas no lugar errado

Se os retângulos desenhados caem em lugares estranhos, verifique duas coisas. Primeiro, a ordem é [ymin, xmin, ymax, xmax], com o valor vertical primeiro. Muita gente lê como x e depois y. Segundo, os números estão em uma escala de 0 a 1000, não em pixels. Divida por 1000 e depois multiplique pela largura ou altura reais.

Texto livre onde deveria haver JSON

Escrever "retorne JSON" no prompt funciona até o modelo envolver a resposta em um bloco de código ou acrescentar uma frase simpática. Passe um schema por meio de response_format e interprete com model_validate_json. O contrato passa a viver no código, onde uma resposta ruim falha de forma explícita e uma boa chega tipada.

Experimente o Gemini 3.5 Flash sem código

Antes de escrever Python, teste o prompt no navegador. O Gemini 3.5 Flash roda no PicassoIA e aceita imagens diretamente, então você pode ajustar uma instrução em segundos e colá-la no seu script depois.

  1. Abra a página do Gemini 3.5 Flash no PicassoIA.
  2. Anexe suas fotos no campo Images. O modelo aceita até 10 imagens por execução, cada uma com até 7 MB.
  3. Digite a instrução no campo Prompt, com a redação exata que você pretende enviar pelo Python.
  4. Opcionalmente, preencha System Instruction para fixar o papel, como "Você escreve textos alternativos com menos de 125 caracteres."
  5. Escolha um Thinking Level entre none, low ou high. Deixe em none para legendas e aumente para raciocínio denso.
  6. Defina Temperature baixa para extração e OCR, e mais alta para legendas criativas.
  7. Execute, compare a resposta com o que você queria e ajuste a redação antes de copiar para o código.
CampoO que fazValor inicial
PromptA instrução enviada com as imagensSua redação exata de produção
ImagesAté 10 arquivos, 7 MB cadaUma imagem durante os testes
System InstructionDefine o papel do modeloUma frase curta
Thinking Levelnone, low ou highnone
TemperatureAleatoriedade de 0 a 20,2 para OCR, 1 para legendas
Max Output TokensLimita o tamanho da respostaO padrão serve

Os limites no PicassoIA são diferentes dos limites nativos da API acima, então trate a página como um laboratório de prompts e a API como o caminho de produção. Para uma segunda opinião sobre uma imagem difícil, rode o mesmo prompt pelo Gemini 3.1 Pro, pelo Qwen3.7-Plus, que interpreta imagens tão bem quanto texto, ou pelo Granite Vision 4.1 4B, feito para gráficos e tabelas.

Crie suas próprias imagens de teste

Você não precisa de uma pasta com fotos reais para começar. Gere uma mesa bagunçada, uma prateleira de mercado, uma rua chuvosa ou um recibo amassado com o PicassoIA Image ou o Seedream 4.5, depois envie cada resultado para o Gemini 3.5 Flash e veja o que ele consegue ler.

Faça três experimentos esta semana. Peça texto alternativo para cinco fotos geradas. Peça uma caixa delimitadora em volta de um objeto em uma cena movimentada. Peça um total em JSON a partir de uma imagem de recibo. Cada um leva minutos, e juntos mostram onde o modelo é preciso e onde o seu prompt precisa de ajustes.

Abra o PicassoIA, crie sua primeira imagem de teste e rode o seu próprio prompt. Veja todos os modelos disponíveis em picassoia.com/en/all-models e combine um gerador de imagens com um modelo de visão para montar o seu próprio fluxo de trabalho de imagem para texto.

Compartilhe este artigo

Escolha seu idioma