Automatizar extração de texto de imagens com GCP Vision e Python
Transforme uma página digitalizada ou captura de tela em texto com um pequeno programa de linha de comando em Python. Este exemplo envia um JPEG ou PNG local ao Google Cloud Vision e imprime o texto reconhecido ou um resumo em JSON para outro programa consumir. Ele não precisa de um bucket do Cloud Storage.
Requisitos
- Python 3.14.7 ou uma versão de manutenção mais recente do Python 3.14, instalada a partir dos downloads do Python.
- A Google Cloud CLI e um projeto do Google Cloud com o faturamento e a Cloud Vision API habilitados.
- Um JPEG ou PNG local que você tenha permissão para enviar ao Google Cloud.
Os comandos de shell abaixo usam Bash no macOS. Este tutorial foi testado com Python 3.14.7 e
google-cloud-vision 3.16.0. Abra um terminal em um diretório exclusivo para o exemplo; mantenha
ali o programa e sua imagem. Verifique se os pré-requisitos funcionam antes de criar o ambiente virtual:
python3.14 --version && gcloud --version
Configurar o projeto na nuvem
No Google Cloud Console, selecione um projeto, confirme que o faturamento está habilitado e habilite a Cloud Vision API. Anote o ID do projeto. Se outra pessoa administra o projeto, peça que ela conclua essas etapas e autorize sua conta; consulte o guia de configuração do Vision do Google.
Configuração de desenvolvimento
Para desenvolvimento local, use Application Default Credentials (ADC). Substitua
PROJECT_ID abaixo pelo ID do seu projeto e faça login com uma conta autorizada a
usar esse projeto:
gcloud auth application-default login &&
gcloud auth application-default set-quota-project PROJECT_ID
As credenciais ADC são separadas do login normal da CLI. O comando de projeto de cota exige
serviceusage.services.use, fornecido pelo papel Service Usage Consumer. Uma configuração existente
de GOOGLE_APPLICATION_CREDENTIALS tem precedência sobre o arquivo ADC local; verifique se ela aponta
para as credenciais desejadas ou remova essa substituição neste terminal antes de usar o login local.
O guia de autenticação do Google explica os requisitos de login e de
projeto de cota. Não coloque credenciais no programa.
Autenticação em produção
Para uma futura implantação, prefira uma conta de serviço vinculada no Google Cloud ou Workload Identity Federation em outros ambientes. Ambas funcionam com ADC sem baixar uma chave de conta de serviço. Este tutorial usa credenciais de usuário locais e não configura uma implantação em produção.
Instalar o cliente Python
Crie um novo ambiente virtual e instale o cliente com a versão fixada. Chamar o interpretador desse ambiente diretamente evita a ativação pelo shell e mantém a instalação dentro deste diretório:
test ! -e .venv && test ! -L .venv &&
python3.14 -m venv .venv &&
./.venv/bin/python -m pip install 'google-cloud-vision==3.16.0'
A primeira verificação impede a reutilização de um .venv existente. Se a
instalação falhar após a criação do ambiente, mantenha seus arquivos e tente novamente apenas o
comando de instalação:
./.venv/bin/python -m pip install 'google-cloud-vision==3.16.0'
Se a própria criação do ambiente virtual falhou, escolha um novo diretório para o exemplo antes de
repetir a configuração. Use o interpretador .venv nos comandos seguintes,
mesmo que outro ambiente esteja ativo no seu terminal.
Salvar o programa de OCR
Salve o bloco completo como extract_text.py. Ele usa document_text_detection para
texto denso de páginas e lê full_text_annotation.text, conforme descrito no
tutorial de detecção de texto em documentos do Google.
O transporte REST continua usando o cliente Python oficial e ADC.
import argparse
import json
from pathlib import Path
import sys
import time
from google.api_core.exceptions import ServiceUnavailable
from google.cloud import vision
class OcrError(RuntimeError):
"""A safe diagnostic generated by this program."""
def process_ocr_text(raw_text: str) -> dict:
lines = raw_text.splitlines()
return {
'full_text': raw_text,
'lines': lines,
'line_count': len(lines),
'word_count': len(raw_text.split()),
'cleaned_text': ' '.join(raw_text.split()),
}
def safe_ocr_call(client, image):
for attempt in range(3):
try:
response = client.document_text_detection(
image=image, retry=None, timeout=30.0
)
except ServiceUnavailable:
if attempt == 2:
raise
time.sleep(2 ** attempt)
continue
if response.error.code:
raise OcrError(f'Vision OCR failed (code {response.error.code}).')
return response
def extract_text(image_path: str) -> str:
path = Path(image_path)
if path.suffix.lower() not in ('.jpg', '.jpeg', '.png'):
raise OcrError('Use one JPEG or PNG image, not a PDF or TIFF.')
content = path.read_bytes()
if not content.startswith((b'\x89PNG\r\n\x1a\n', b'\xff\xd8\xff')):
raise OcrError('Input does not have a JPEG or PNG signature.')
with vision.ImageAnnotatorClient(transport='rest') as client:
response = safe_ocr_call(client, vision.Image(content=content))
return response.full_text_annotation.text
def main() -> int:
parser = argparse.ArgumentParser(description='Extract text from one JPEG or PNG.')
parser.add_argument('image_path')
parser.add_argument('--json', action='store_true', help='Print a JSON summary.')
args = parser.parse_args()
try:
text = extract_text(args.image_path)
except OcrError as error:
print(error, file=sys.stderr)
return 1
except Exception as error:
print(f'OCR failed ({type(error).__name__}).', file=sys.stderr)
return 1
if args.json:
print(json.dumps(process_ocr_text(text), ensure_ascii=False))
else:
sys.stdout.write(text)
if not text:
print('No text detected.', file=sys.stderr)
return 0
if __name__ == '__main__':
sys.exit(main())
A verificação da assinatura detecta arquivos vazios e erros evidentes de formato antes de uma requisição. Ela não decodifica nem valida completamente uma imagem; danos além do cabeçalho podem ser rejeitados ou recuperados pelo Vision. Inspecione a imagem original e compare o texto reconhecido com ela antes de usar o resultado.
Executar com sua imagem
Salve uma digitalização ou captura de tela nítida como invoice.png no mesmo diretório
do programa e execute:
./.venv/bin/python extract_text.py invoice.png
O texto reconhecido é enviado à saída padrão com suas quebras de linha originais. Uma requisição
bem-sucedida sem texto reconhecido termina com status zero, deixa a saída padrão vazia e imprime
No text detected. na saída de erro padrão. Esse é um resultado do reconhecimento, não uma
prova de que a imagem não contém texto escrito. Erros encerram o processo com status um e sem texto
extraído; argumentos de linha de comando incorretos encerram o processo com status dois.
Para obter o exemplo integrado de normalização, execute o mesmo programa com
--json:
./.venv/bin/python extract_text.py --json invoice.png
full_text mantém a resposta de OCR. lines,
line_count e word_count descrevem esse texto;
cleaned_text reduz sequências de espaços em branco para facilitar a busca. Esses
campos não identificam totais de faturas, tabelas nem parágrafos do documento. Um resultado em branco
produz strings vazias, um array lines vazio e contagens iguais a zero.
Diagnosticar uma falha na extração
O programa desabilita as novas tentativas automáticas do cliente e faz no máximo três chamadas ao
método de OCR, repetindo apenas ServiceUnavailable, com esperas de um e dois segundos. Cada
chamada tem um tempo limite de requisição de 30 segundos; esse não é um prazo para o comando inteiro,
incluindo a autenticação e as esperas entre tentativas. Falhas de permissão, esgotamento de cota e
erros por imagem incorporados à resposta não geram novas tentativas.
FileNotFoundError: verifique o nome do arquivo de imagem e o diretório atual do terminal.DefaultCredentialsError: conclua o login ADC ou corrija uma substituição indesejada de credenciais.Forbidden,PermissionDeniedou código incorporado 7: verifique o acesso ao projeto, a habilitação da API e o projeto de cota ADC. Repetir a mesma requisição não pode conceder permissão.TooManyRequests,ResourceExhaustedou código incorporado 8: inspecione as cotas do projeto antes de tentar novamente manualmente.- Um código incorporado 3 ou
InvalidArgument: verifique se a entrada é um JPEG ou PNG legível e íntegro.
Mensagens de erro de terceiros não são impressas porque podem conter detalhes da requisição. Os códigos numéricos incorporados e os nomes das exceções indicam a próxima verificação sem expor esses detalhes.
Manter o fluxo de trabalho de imagens dentro de seus limites
Este programa lê uma imagem completa para a memória e a envia a um serviço na nuvem. Use primeiro uma imagem pequena de teste, verifique os formatos compatíveis e limites de tamanho e consulte os preços do Vision antes de executar uma carga de trabalho maior. O processamento em lote pode reduzir a sobrecarga das requisições, mas não elimina as cobranças por recurso aplicado a cada imagem.
Para PDFs ou TIFFs com várias páginas, use as APIs de anotação de arquivos em vez de renomear o arquivo ou passá-lo a esta CLI de imagens. A detecção automática de idioma e o OCR ainda podem interpretar o texto incorretamente; avalie suas próprias digitalizações, sistemas de escrita e layouts. Um exemplo sintético simples não comprova a precisão em recibos, textos manuscritos ou documentos de produção.
