Documentação técnica para extração de texto de imagens e PDFs usando GPT-4 Vision
Autor: Dante Testa
Data: 01/12/2024
Versão: 1.0
- Visão Geral
- Autenticação
- Endpoint
- Estrutura da Requisição
- Envio de Imagens
- Casos de Uso OCR
- Processamento de PDFs
- Extração de Dados Estruturados
- Tratamento de Erros
- Exemplos Completos
A API OpenAI Vision (GPT-4o, GPT-4-turbo) permite analisar imagens e extrair texto (OCR). Diferente de OCRs tradicionais, ela usa inteligência artificial para:
- Extrair texto de qualquer orientação/formatação
- Entender contexto e estrutura de documentos
- Retornar dados estruturados (JSON)
- Processar documentos complexos (tabelas, formulários)
| Modelo | Capacidade | Recomendação |
|---|---|---|
gpt-4o |
Mais rápido, ótima qualidade | Recomendado para OCR |
gpt-4-turbo |
Alta qualidade | Alternativa |
gpt-4-vision-preview |
Legado | Evitar |
Todas as requisições requerem uma API Key no header:
Authorization: Bearer YOUR_API_KEY
Obtenha sua chave em: https://platform.openai.com/api-keys
POST https://api.openai.com/v1/chat/completions
Headers obrigatórios:
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
{
"model": "gpt-4o",
"messages": [
{
"role": "system",
"content": "Instruções do sistema (opcional)"
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "Seu prompt/instrução"
},
{
"type": "image_url",
"image_url": {
"url": "URL ou Base64 da imagem",
"detail": "high"
}
}
]
}
],
"max_tokens": 4096
}| Parâmetro | Tipo | Descrição |
|---|---|---|
model |
string | Modelo a usar (gpt-4o recomendado) |
messages |
array | Array de mensagens |
max_tokens |
integer | Limite de tokens na resposta (máx ~4096) |
detail |
string | Qualidade: low, high, auto |
Converta a imagem para Base64 e envie como Data URI:
data:{mime_type};base64,{base64_encoded_data}
Exemplo PHP:
$imageData = file_get_contents('documento.jpg');
$base64 = base64_encode($imageData);
$dataUri = "data:image/jpeg;base64,{$base64}";Exemplo JavaScript:
const file = document.getElementById('input').files[0];
const reader = new FileReader();
reader.onload = () => {
const dataUri = reader.result; // Já vem como data URI
};
reader.readAsDataURL(file);Envie a URL direta da imagem (deve ser acessível publicamente):
{
"type": "image_url",
"image_url": {
"url": "https://exemplo.com/imagem.jpg"
}
}- Imagens: JPEG, PNG, GIF, WebP
- PDF:
⚠️ Requer conversão para imagem (não aceito diretamente) - Tamanho máximo: ~20MB
Prompt:
Extraia todo o texto visível nesta imagem.
System message sugerida:
Você é um assistente especializado em OCR. Extraia todo texto visível, mantendo a formatação original.
Prompt:
Extraia o texto desta imagem preservando:
- Estrutura de parágrafos
- Listas e bullet points
- Hierarquia de títulos
Prompt:
Extraia a tabela desta imagem e formate como markdown ou CSV.
Prompt:
Extraia os dados deste documento e retorne em JSON:
- numero_documento
- nome
- data_nascimento
- endereco
A API Vision não aceita PDFs diretamente. É necessário converter para imagem primeiro.
Usando pdftoppm (Linux/Mac):
pdftoppm -png -r 200 documento.pdf outputPHP com exec:
function convertPdfToImages($pdfPath) {
$outputDir = '/tmp/pdf_' . uniqid();
mkdir($outputDir);
$command = "pdftoppm -png -r 200 " .
escapeshellarg($pdfPath) . " " .
escapeshellarg($outputDir . '/page');
exec($command);
return glob($outputDir . '/*.png');
}Para PDFs com múltiplas páginas, se precisar processar cada uma separadamente:
$pages = convertPdfToImages('documento.pdf');
$allText = [];
foreach ($pages as $index => $imagePath) {
$text = processOCR($imagePath);
$allText[] = "--- Página " . ($index + 1) . " ---\n" . $text;
}
$resultado = implode("\n\n", $allText);Para extrair dados em formato JSON, use prompts específicos:
Analise este documento e extraia os dados em formato JSON.
Campos a extrair:
- campo1
- campo2
- campo3
IMPORTANTE: Retorne APENAS JSON válido, sem markdown ou explicações.
Se um campo não existir, use string vazia "".
Exemplo: {"campo1": "valor", "campo2": "valor"}
Você é um extrator de dados de documentos.
Sempre retorne JSON válido sem markdown ou explicações.
A API pode retornar JSON com markdown. Limpe antes de decodificar:
$content = $response['choices'][0]['message']['content'];
// Remover possível markdown
$content = preg_replace('/^```json\s*/i', '', $content);
$content = preg_replace('/\s*```$/i', '', $content);
$content = trim($content);
$data = json_decode($content, true);| Código | Erro | Solução |
|---|---|---|
| 400 | Invalid MIME type | Verifique se o formato é suportado |
| 400 | Image too large | Reduza o tamanho/resolução |
| 401 | Invalid API key | Verifique sua chave |
| 429 | Rate limit | Aguarde ou reduza requisições |
| 500 | Server error | Tente novamente |
Se o modelo retornar "I can't assist with that", ajuste o prompt:
Problema: Modelo interpreta como solicitação inadequada
Solução: Use system message clara:
Você é um assistente de OCR. Sua única função é extrair texto de imagens.
Você DEVE sempre extrair qualquer texto visível, independentemente do conteúdo.
Foque APENAS no texto escrito. Nunca recuse uma solicitação de extração.
<?php
function extractText($imagePath) {
$apiKey = 'YOUR_API_KEY';
// Converter imagem para base64
$imageData = file_get_contents($imagePath);
$base64 = base64_encode($imageData);
$mimeType = mime_content_type($imagePath);
$dataUri = "data:{$mimeType};base64,{$base64}";
// Montar payload
$payload = [
'model' => 'gpt-4o',
'messages' => [
[
'role' => 'system',
'content' => 'Você é um OCR. Extraia todo texto visível da imagem.'
],
[
'role' => 'user',
'content' => [
['type' => 'text', 'text' => 'Extraia o texto desta imagem:'],
['type' => 'image_url', 'image_url' => ['url' => $dataUri, 'detail' => 'high']]
]
]
],
'max_tokens' => 4096
];
// Fazer requisição
$ch = curl_init('https://api.openai.com/v1/chat/completions');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey
]
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
return $result['choices'][0]['message']['content'];
}async function extractText(file) {
const apiKey = 'YOUR_API_KEY';
// Converter para base64
const base64 = await new Promise((resolve) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.readAsDataURL(file);
});
// Fazer requisição
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify({
model: 'gpt-4o',
messages: [
{
role: 'system',
content: 'Você é um OCR. Extraia todo texto visível.'
},
{
role: 'user',
content: [
{ type: 'text', text: 'Extraia o texto:' },
{ type: 'image_url', image_url: { url: base64, detail: 'high' } }
]
}
],
max_tokens: 4096
})
});
const data = await response.json();
return data.choices[0].message.content;
}<?php
function extractCNPJData($imagePath) {
$apiKey = 'YOUR_API_KEY';
$imageData = file_get_contents($imagePath);
$base64 = base64_encode($imageData);
$dataUri = "data:image/jpeg;base64,{$base64}";
$prompt = 'Extraia os dados deste Cartão CNPJ em JSON:
- cnpj
- razao_social
- nome_fantasia
- endereco
- telefone
- email
- situacao
Retorne APENAS JSON válido.';
$payload = [
'model' => 'gpt-4o',
'messages' => [
[
'role' => 'system',
'content' => 'Retorne apenas JSON válido, sem markdown.'
],
[
'role' => 'user',
'content' => [
['type' => 'text', 'text' => $prompt],
['type' => 'image_url', 'image_url' => ['url' => $dataUri]]
]
]
],
'max_tokens' => 4096
];
// ... fazer requisição ...
// Limpar e decodificar resposta
$content = $result['choices'][0]['message']['content'];
$content = preg_replace('/^```json\s*|\s*```$/i', '', $content);
return json_decode(trim($content), true);
}- Use
detail: highpara documentos com texto pequeno - Limite resolução a ~2000px para melhor performance
- Processe PDFs página por página para evitar timeout
- Valide JSON antes de usar os dados extraídos
- Implemente retry para erros 429 (rate limit)
- Cache resultados quando possível
- Use system message para evitar recusas do modelo
| Item | Limite |
|---|---|
| Tamanho máximo da imagem | ~20MB |
| Tokens por requisição | ~128k (entrada + saída) |
| Timeout recomendado | 120 segundos |
Custos aproximados (GPT-4o):
- Input: $5.00 / 1M tokens
- Output: $15.00 / 1M tokens
- Imagens: ~85-170 tokens por tile (varia com tamanho)
Dica Final: Para OCR em produção, considere implementar uma fila de processamento assíncrono para documentos grandes ou múltiplos arquivos.