Beta · Estamos validando o produto. Pode ter instabilidades. Saiba mais

Voltar para o blog
·9 min·Israel Oriente

Como ler placa de carro em Python em 2026

Guia prático para integrar reconhecimento de placa de veículo em Python. Comparativo de bibliotecas, código pronto e quanto custa rodar em produção no Brasil.

pythonocralprtutorial

Reconhecer a placa de um carro a partir de uma foto é uma daquelas tarefas que soam simples até você tentar fazer. Tem oclusão, tem ângulo torto, tem foto à noite, tem placa Mercosul nova convivendo com placa antiga, tem reflexo de farol. E quando você finalmente fica satisfeito com a precisão num set de testes, descobre que o modelo come 4GB de RAM e demora 8 segundos por imagem.

Este post é o guia que eu queria ter encontrado quando comecei a trabalhar com leitura de placa em Python no Brasil. Vou cobrir as três abordagens viáveis em 2026, com código real, comparação de precisão, e o custo de rodar cada uma em produção.

TL;DR

  • OpenCV + Tesseract: zero custo, ~70% de precisão, requer muito tuning manual. Bom para protótipo, ruim para produção.
  • EasyOCR / PaddleOCR: ~85% de precisão out-of-the-box, mas pesa GBs e exige GPU pra ser rápido.
  • API gerenciada (leituradeplaca, Plate Recognizer, etc): 95%+ de precisão, sem infra, custa entre R$ 0,003 e R$ 0,80 por leitura. Para quem quer entregar produto, é o caminho.

Se você quer ir direto para o código com a API e voltar para casa em 5 minutos, pula para a seção 4.

O problema na prática

Cada placa veicular brasileira tem um destes dois formatos:

  • Padrão antigo: ABC1234 — 3 letras + 4 dígitos
  • Mercosul (a partir de 2018): ABC1D34 — 3 letras + 1 dígito + 1 letra + 2 dígitos

O OCR precisa distinguir os dois padrões e normalizar a saída. E precisa lidar com:

  • Foto à noite com farol invadindo o quadro
  • Placas inclinadas (carros estacionados em vagas oblíquas)
  • Sujeira, pichação parcial, adesivos
  • Câmeras com lente granangular distorcendo letras
  • Placa pequena no quadro (carro afastado)

A precisão que você consegue depende muito mais da qualidade do seu input do que do modelo. Manda uma foto de 4MP com a placa de frente e bem iluminada — qualquer modelo decente acerta. Manda uma foto de 480p com luminária amarela e ângulo de 45° — só os melhores acertam.

Abordagem 1: OpenCV + Tesseract

O caminho clássico. Zero custo de inferência, mas você paga em código.

import cv2
import pytesseract
import re

def read_plate_opencv(image_path: str) -> str | None:
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # Realça bordas para encontrar regiões retangulares (placas tendem a ser).
    edges = cv2.Canny(gray, 100, 200)
    contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    for contour in sorted(contours, key=cv2.contourArea, reverse=True)[:10]:
        x, y, w, h = cv2.boundingRect(contour)
        aspect_ratio = w / h
        # Placas brasileiras têm proporção ~3.2 (40cm × 13cm aprox)
        if 2.5 < aspect_ratio < 5 and w > 80 and h > 25:
            roi = gray[y:y+h, x:x+w]
            # Threshold local para destacar letras pretas no fundo claro
            roi = cv2.threshold(roi, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
            text = pytesseract.image_to_string(
                roi,
                config='--psm 7 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
            ).strip()
            text = re.sub(r'[^A-Z0-9]', '', text)
            if re.match(r'^[A-Z]{3}\d[A-Z\d]\d{2}$', text):
                return text
    return None

Funciona? Sim, em ~70% das fotos boas. Falha catastroficamente em fotos mais complexas. Você vai gastar dias ajustando thresholds, valores de Canny, filtros morfológicos.

Custo: zero por leitura. Mas custo de desenvolvimento alto.

Recomendado para: prototipagem, projeto de TCC, validação de conceito. Não para produto que cliente paga.

Abordagem 2: Modelos pré-treinados (EasyOCR / PaddleOCR)

Step up da abordagem 1: usa modelos de deep learning treinados em milhões de imagens.

EasyOCR

import easyocr
import re

reader = easyocr.Reader(['pt'], gpu=True)

def read_plate_easyocr(image_path: str) -> str | None:
    results = reader.readtext(image_path, allowlist='ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
    for (_, text, conf) in results:
        text = re.sub(r'[^A-Z0-9]', '', text.upper())
        if re.match(r'^[A-Z]{3}\d[A-Z\d]\d{2}$', text) and conf > 0.5:
            return text
    return None

Precisão: ~85% out-of-the-box em fotos razoáveis. Sobe para ~92% se você fizer fine-tuning com seu próprio dataset.

Custo de produção:

  • CPU: ~3-5 segundos por imagem. Inviável para volume.
  • GPU: ~200-400ms por imagem. Servidor com GPU custa R$ 800-2.000/mês no Brasil (instâncias menores em AWS/GCP), ou você compra hardware próprio (~R$ 8.000 uma vez).

Memória: o modelo + imagem em memória pesa ~2-4GB de RAM. Você precisa de máquina dedicada ou container generoso.

Recomendado para: quem tem volume alto (>100k leituras/mês) e quer não depender de API externa. Não recomendado para começar — você gasta semanas tunando deploy de GPU antes de ver o primeiro cliente.

PaddleOCR

Similar ao EasyOCR, mas frequentemente mais preciso para texto não-latino. Para placas brasileiras (que usam letras latinas), a diferença é marginal.

Abordagem 3: API gerenciada

A escolha pragmática quando você quer entregar produto agora. Você manda a foto, recebe a placa em JSON, paga só pelo que usar. Sem GPU, sem treino de modelo, sem manutenção.

Exemplo com a API leituradeplaca

import os
import requests

def read_plate_api(image_path: str) -> dict:
    with open(image_path, 'rb') as f:
        response = requests.post(
            'https://leituradeplaca.com.br/api/v1/read-plate',
            headers={
                'X-API-Key': os.environ['LEITURADEPLACA_KEY'],
                'Content-Type': 'image/jpeg',
            },
            data=f.read(),
            timeout=10,
        )
    response.raise_for_status()
    return response.json()

# Uso
result = read_plate_api('carro.jpg')
print(result)
# {
#   "plate": "ABC1D34",
#   "confidence": 0.94,
#   "error": null,
#   "latency_ms": 2410
# }

Precisão: 95%+ em fotos típicas. Funciona com Mercosul e padrão antigo.

Custo: a partir de R$ 0,003 por leitura no plano Diamond, ou R$ 0,05 no pacote Trial (R$ 4,99 por 100 leituras). Tabela completa de preços.

Latência: 1.000 a 4.200 ms por imagem.

Sem servidor de GPU para manter, sem modelo para treinar, sem dataset para coletar. Você integra em 5 minutos e segue para o próximo problema do seu produto.

Comparativo direto

AbordagemPrecisãoLatênciaCusto/1.000 leiturasSetup
OpenCV + Tesseract~70%100-300msR$ 0 (CPU local)Dias de tuning
EasyOCR + GPU~85%200-400ms~R$ 27 (GPU prorata)Semanas
leituradeplaca API95%+1-4sR$ 3-505 minutos
Plate Recognizer95%+500ms-2s~R$ 5 (USD-based)30 min (docs em inglês)

Como decidir

Use a abordagem 1 se você está aprendendo OCR ou fazendo TCC. Você vai aprender muito sobre processamento de imagem, mas não vai entregar produto.

Use a abordagem 2 se você tem mais de 500k leituras/mês, equipe ML, e o custo do API gerenciado se torna proibitivo. Aí faz sentido investir em infra própria.

Use a abordagem 3 (API) em qualquer outro cenário. Você vai economizar semanas de trabalho, ter precisão maior do que conseguiria sozinho, e pagar barato enquanto o volume é pequeno. Quando crescer e fizer sentido econômico, você decide internalizar.

Próximos passos

Se você optou pela API, crie uma conta gratuita e gere uma chave. O pacote Trial de R$ 4,99 te dá 100 leituras pra testar com seus dados reais antes de assinar.

Se você prefere ir de OpenCV ou EasyOCR, recomendo começar pelo dataset UFPR-ALPR — fotos brasileiras anotadas, ótimo para validar acurácia.

Dúvida sobre integração? Documentação da API ou manda mensagem em contato@leituradeplaca.com.br.

Pronto para integrar?

Crie uma conta e ganhe acesso à API em menos de 60 segundos.