Lab · Plateproof · visão computacional

Sete minutos de um cruzamento, lidos por uma máquina

Gravei sete minutos de uma câmera de trânsito ao vivo e processei tudo num notebook, sem placa de vídeo. Os veículos foram detectados, seguidos e contados, o semáforo foi lido pela luz acesa e as placas foram lidas e depois pixeladas. Os números desta página saem desse processamento, e os mais importantes eu conferi um por um.

Fresno · Califórnia · EUA 7 minutos 12.750 quadros só CPU
Meio minuto do programa rodando, gravado da tela. Eu escolho o vídeo e o arquivo de números, e o resto é ele: caixa em cada veículo, rastro dos últimos dois segundos, as linhas de contagem, os contadores subindo e o semáforo contando há quantos segundos está verde. As placas já estão pixeladas no vídeo.

Imagem: transmissão ao vivo do canal Friant Roulette no YouTube (ver a transmissão). Relógio, logotipo e o semáforo desenhado no canto são do canal. As placas e a data do relógio foram pixeladas por mim.

01 · o que passou

316 veículos em 7 minutos

316veículos cruzaram a linha de contagem
47placas lidas e confirmadas, em 266 passagens em que a placa apontou para a câmera
3ciclos completos de semáforo (verde, amarelo e vermelho)
177 mspor quadro, mediana, num notebook sem GPU
Um quadro do vídeo com 18 veículos marcados por caixas, o tipo e o número de cada um, o rastro dos últimos segundos e as linhas de contagem tracejadas
Um quadro qualquer, com o que a máquina viu desenhado por cima: 18 veículos marcados ao mesmo tempo, o tipo e o número de cada um, o rastro dos últimos dois segundos e as linhas tracejadas onde a contagem acontece. Cinco já tinham a placa lida — é o que diz o "plate read".
TipoContadosRastreados na tela
Carros e SUVs262511
Utilitários (picape, van, caminhão)5384
Ônibus00
Motos11
Bicicletas04
Pedestres26

Só conta quem cruzou uma linha: 168 seguiram em frente se afastando da câmera, 98 vieram no sentido contrário e 50 cruzaram pela transversal. O rastreador acompanhou 606 objetos, mas boa parte é o mesmo carro parado na fila ou um pedaço de rastro que se perdeu atrás de outro veículo, e isso fica fora da conta. O que o modelo chama de truck junta picape, van e caminhão; a conferência da seção 05 mostra quanto tem de cada.

02 · o semáforo manda

O fluxo anda no ritmo da luz verde

A luz foi lida pela cor das lentes do próprio semáforo, sem ligação nenhuma com o controlador. Em 7 minutos couberam 3 ciclos completos: verde de 53,2 a 62,4 s, amarelo de 5 s e vermelho de 44,3 a 59,5 s. Nos três verdes completos seguiram em frente 25, 43 e 43 veículos. No vermelho a linha ainda registrou 26: 14 estavam na faixa da direita, que na Califórnia pode converter no vermelho depois de parar, e os outros 12 são a fila andando alguns metros, porque a linha de contagem fica antes da faixa de retenção.

O mesmo semáforo em dois momentos, ampliado: com a lente vermelha acesa e com a verde acesa
Não tem integração com controlador nenhum: uma caixa cobre a carcaça do semáforo e o programa mede o brilho de cada terço dela. A lente acesa estoura para perto de 255; as apagadas ficam entre 110 e 160. É essa diferença, e só ela, que vira "verde há 8 segundos".
Veículos que seguiram em frente, a cada 10 segundos · faixas cinza = sinal vermelho
Vermelho às 09:06:56, por 17 s Vermelho às 09:08:10, por 55 s Vermelho às 09:10:07, por 60 s Vermelho às 09:12:14, por 44 s 0481216 09:06:56 · 4 veículos 09:07:06 · 1 veículo 09:07:16 · 4 veículos 09:07:26 · 10 veículos 09:07:36 · 5 veículos 09:07:46 · 3 veículos 09:07:56 · 2 veículos 09:08:16 · 2 veículos 09:08:26 · 3 veículos 09:08:36 · 1 veículo 09:08:56 · 1 veículo 09:09:06 · 8 veículos 09:09:16 · 16 veículos 09:09:26 · 11 veículos 09:09:36 · 3 veículos 09:09:46 · 5 veículos 09:09:56 · 1 veículo 09:10:26 · 2 veículos 09:10:36 · 3 veículos 09:11:06 · 5 veículos 09:11:16 · 1 veículo 09:11:26 · 1 veículo 09:11:36 · 10 veículos 09:11:46 · 12 veículos 09:11:56 · 12 veículos 09:12:06 · 8 veículos 09:12:16 · 3 veículos 09:12:26 · 3 veículos 09:12:36 · 1 veículo 09:12:56 · 2 veículos 09:13:06 · 1 veículo 09:13:16 · 4 veículos 09:13:26 · 3 veículos 09:13:36 · 7 veículos 09:13:46 · 6 veículos 09:13:56 · 4 veículos 09:0709:0809:0909:1009:1109:1209:1309:14
ver as fases do semáforo em tabela
InícioLuzDuraçãoVeículos na fase
09:06:56vermelho17 s4
09:07:12verde53 s25
09:08:05amarelo5 s0
09:08:10vermelho55 s7
09:09:05verde57 s43
09:10:02amarelo5 s1
09:10:07vermelho60 s6
09:11:06verde62 s43
09:12:09amarelo5 s3
09:12:14vermelho44 s9
09:12:58verde62 s27

03 · placa pequena não se lê

Quantos pixels uma placa precisa para ser lida

Das 266 passagens pela Friant, em 170 o detector achou a placa em pelo menos um quadro. Nas outras 96 nunca achou, quase sempre carro vindo de longe no sentido contrário. Uma leitura só vale quando o mesmo veículo teve três leituras ou mais e 75% dos caracteres concordaram entre elas, e 47 passaram nesse filtro. O gráfico explica por que foram poucas: esta câmera foi posta para mostrar o cruzamento, e a placa quase nunca passa de 80 pixels de largura. Abaixo de 40 px nenhuma foi lida. A Axis pede 130 px.

Veículos com placa lida e confirmada, pela maior largura que a placa atingiu no quadro de 1920 px · n = veículos na faixa · barra clara = menos de 10 veículos, amostra pequena
0%25%50%75%100% 0% até 40 px n = 29 40 a 60: 8 de 54 (15%) 15% 40 a 60 n = 54 60 a 80: 33 de 72 (46%) 46% 60 a 80 n = 72 80 a 100: 3 de 11 (27%) 27% 80 a 100 n = 11 100 ou mais: 3 de 4 (75%) 75% 100 ou mais n = 4

04 · onde vai o tempo

177 ms por quadro, medidos etapa por etapa

O processamento inteiro rodou num notebook com Intel Core i7-13700H, sem placa de vídeo: 38,5 minutos para 7 minutos de vídeo, 5,5 quadros por segundo. As duas detecções ficam com quase todo o tempo, 75 ms para veículos e 88 ms para placas na mediana. Rastrear, ler a placa e pixelar custam pouco perto disso.

Tempo por quadro em cada etapa · barra = mediana · traço = 95% dos quadros abaixo dele · Intel Core i7-13700H
Decodificar quadro Decodificar quadro: mediana 4,3 ms, p95 6,5 ms 4,3 / 6,5 ms Detectar veículos Detectar veículos: mediana 75,0 ms, p95 96,3 ms 75,0 / 96,3 ms Rastrear (ByteTrack) Rastrear (ByteTrack): mediana 2,2 ms, p95 4,9 ms 2,2 / 4,9 ms Detectar placas Detectar placas: mediana 87,5 ms, p95 116,7 ms 87,5 / 116,7 ms Ler placas (OCR) Ler placas (OCR): mediana 0,1 ms, p95 7,9 ms 0,1 / 7,9 ms Pixelar e gravar Pixelar e gravar: mediana 5,2 ms, p95 7,8 ms 5,2 / 7,8 ms
EscolhaO que foi medidoPor que ficou
Detector de placa YOLOv9-s-608Nos mesmos 5 quadros: o t-384 levou 18 ms e achou 1 placa por quadro; o t-640, 57 ms e 1,6; o s-608, 64 ms e 3,2.Mais que o triplo de placas achadas por 46 ms a mais.
Leitor de placa cct-xs-v2Na placa de teste, o xs leu os 7 caracteres certos; o cct-s-v2, maior, trocou um 9 por H.O menor acertou a placa de teste e é mais rápido.
Detector de veículos YOLOX-s75 ms por quadro na mediana do vídeo inteiro.Licença Apache 2.0, livre para uso comercial, e roda direto no ONNX Runtime, sem PyTorch.
ONNX Runtime sem espera ativaTeste com 300 quadros: 1,3 quadro/s antes, 4,8 depois (desligando a espera ativa e limitando o codificador de vídeo a 2 threads).Três sessões ONNX giravam threads em vazio disputando os mesmos núcleos.

05 · como eu conferi

Número de máquina, conferido à mão

32 de 47placas exatas

Olhei o recorte de cada uma das 47 placas aceitas e comparei caractere por caractere. 11 tinham um caractere trocado, quase sempre 8 lido como B no começo. 4 nem eu consegui ler, e contei como erro. Uma regra do formato da placa (número, três letras, três números) corrigiria 8 das 11, a mesma ideia que serve para o padrão Mercosul.

8 de 53utilitários eram caminhões

Vi cada veículo que o modelo chamou de caminhão: 24 picapes, 13 vans, 8 caminhões, 3 reboques e 5 SUVs, esses sim erro. O modelo aprendeu no conjunto COCO, onde picape e van costumam cair na classe de caminhão.

4 a 6 de 168contagens a mais

Montei a sequência dos 168 veículos que seguiram em frente e procurei o mesmo veículo contado duas vezes. Três reboques entraram separados de quem os puxava, e há de um a três casos prováveis na faixa da direita, onde um poste esconde o carro e o rastreio troca o número.

O que eu não medi: quantos veículos passaram sem ser contados. Isso exige contar os 7 minutos à mão, e fica para a próxima rodada. As horas da página são as do relógio da câmera. No começo da gravação ele marcava uns 14 segundos a menos que o relógio do meu computador, diferença que soma o atraso da transmissão do YouTube e um possível desvio do relógio da câmera.

06 · limites desta câmera

O que uma câmera feita para ler placa exige

Para rodar ao vivo, quase nada muda no código. Aqui o vídeo veio de uma gravação; numa instalação real ele chega da câmera por RTSP, o protocolo que a maioria das câmeras IP já fala. O mesmo FFmpeg abre o fluxo, o mesmo processamento roda quadro a quadro, e em vez de gravar um arquivo o resultado vai por WebSocket para um painel como o de cima, ao vivo.

  1. Câmera IPRTSP / ONVIF
  2. FFmpegabre o fluxo
  3. Detecção, rastreio, placao pipeline desta página
  4. Eventoscontagem, placa, semáforo
  5. Painel ao vivoWebSocket

O que muda de verdade é a câmera. Esta foi instalada para mostrar o cruzamento, não para ler placa, e o gráfico da seção 03 mostra o preço disso. Os fabricantes publicam o que uma câmera de leitura de placa precisa:

RequisitoValorFonte
Largura da placa na imagem130 px ou mais (placa de uma linha); na Hikvision, caracteres com 20 a 30 px de altura e a linha de caracteres com 100 a 200 px de largura numa câmera de 2 MPAxis · Hikvision
Tempo de exposição1/150 a 1/200 s até 30 km/h; 1/250 a 1/500 s de 30 a 60 km/h; 1/500 a 1/1000 s acima dissoHikvision
Ângulo entre câmera e placaaté 30° em qualquer direçãoAxis · Hikvision
Distância e altura em portaria2 a 7 m de distância, 1 a 3,5 m de alturaAxis
Leitura noturnaIR 850 nm; 740 nm para placa refletivaMilesight

Três tipos de câmera, pela ficha técnica

Exemplos de cada tipo com a ficha técnica do fabricante. O que muda de um para outro é lente, sensibilidade à luz e se a leitura de placa já vem embarcada.

Câmera IP comum

Intelbras VIP 1230 B G5 2 MP · lente fixa 3,6 mm · IR 30 m · RTSP/ONVIF ficha técnica
Hikvision DS-2CD1123G0E-I 2 MP · lente fixa 2,8 mm · IR 30 m · RTSP/ONVIF ficha técnica

Câmera com lente ajustável

Intelbras VIP 3230 B SL G3 2 MP · Starlight F1.6 · IR 30 m · RTSP/ONVIF ficha técnica
Hikvision DS-2CD1623G2-LIZSU/SL 2 MP · varifocal motorizada 2,8–12 mm · RTSP/ONVIF ficha técnica

Câmera dedicada a placa

Intelbras VIP 5460 LPR IA 4 MP · varifocal 2,7–12 mm · WDR 140 dB · leitura embarcada até 60 km/h ficha técnica
Hikvision iDS-TCM403-BI 4 MP · varifocal 8–32 mm · WDR 140 dB · leitura embarcada 5–200 km/h ficha técnica

Onde o processamento roda

MáquinaDado de desempenho
O notebook desta página (Intel Core i7-13700H)Medido aqui: 5,5 quadros por segundo com as seis etapas ligadas. Tempo real a 30 quadros por segundo não cabe nesta máquina; ao vivo, o caminho é analisar um quadro a cada cinco ou seis, ou usar um acelerador.
Mini PC com Intel N100Sem número publicado de YOLO. Teria que medir, como medi o notebook acima.
Raspberry Pi 5 + AI HAT+ (Hailo-8, 26 TOPS)O model zoo da Hailo lista 491 q/s no YOLOv8s, medido em PCIe x4. No Pi 5, que liga o HAT em x1, um teste da comunidade mediu cerca de 105 q/s. Hailo comunidade
NVIDIA Jetson Orin Nano Super67 TOPS. Não encontrei número oficial da NVIDIA de YOLO para este kit.

07 · privacidade

A placa foi lida e não aparece

O texto das placas não sai desta página: o painel mostra só que a placa foi lida, quantas vezes e com que confiança. No vídeo, toda placa detectada é pixelada. Além disso, todo veículo que o detector achou e cuja caixa tem 100 px de altura ou mais tem a parte de baixo pixelada, inclusive alguns quadros antes e depois do rastro. Isso cobre a maior parte das placas que o detector de placa perdeu. Veículo pequeno demais, lá no fundo, não recebe a faixa: a placa dele também não passa de uns 20 px e não sai legível, mas isso é um limite, não uma garantia. Sobra um caso: veículo e placa perdidos no mesmo quadro, e é para ele que serve a conferência a olho abaixo. A data do relógio do canal também foi coberta.

Rosto eu não pixelo, então o mínimo é olhar. O detector rastreou 51 pessoas e bicicletas nestes sete minutos. Conferi as doze maiores, recorte por recorte: oito são a cabeça do semáforo de pedestre lida como gente, de novo e de novo. As outras quatro mostram um retrovisor de caminhão, uma silhueta em contraluz e alguém de costas. Nenhum rosto identificável — a maior caixa de pessoa do vídeo inteiro tem 310 px de altura, o que põe um rosto em uns 30 px. Isso é uma conferência, não uma garantia.

O que este método não cobre: rosto não é tratado. A placa que o detector nunca achou não é pega pelo ataque automático, porque ele usa o mesmo detector. E ataque que combina vários quadros para reconstruir o mosaico eu não testei. Nada disso aqui é "impossível de recuperar" — é o que eu tentei, com a melhor ferramenta que eu tinha, e o que eu não consegui provar está escrito.

Um quadro inteiro do vídeo publicado: a parte de baixo de cada veículo próximo está coberta por mosaico
Um quadro do vídeo publicado, inteiro, sem recorte. A faixa de baixo de cada veículo grande o bastante está coberta — não só onde o detector achou placa, mas onde ela estaria de qualquer jeito.

Conferi de dois jeitos. Rodei o mesmo leitor de placa em cima do vídeo publicado, ampliado para 1920 px, nos 12.750 quadros, todos. Ele não achou nenhuma leitura em forma de placa.

Zero não prova nada sozinho: lê igual quando o vídeo está limpo e quando a ferramenta quebrou. Então rodei o mesmo comando no vídeo original, sem pixelar, como controle. Em 400 quadros ele achou 224 leituras em forma de placa, 142 delas a dois caracteres ou menos de uma placa real, com distância mínima zero — acerto em cheio. A ferramenta enxerga. No vídeo publicado, nos 12.750 quadros, ela não enxerga nada. Como esse teste tem o mesmo ponto cego do detector, também olhei 25 quadros inteiros sorteados, incluindo o do pôster, procurando qualquer placa legível: não achei nenhuma. O texto completo das placas existe só no computador onde rodei a análise, para a conferência manual.

08 · o código

O mesmo processamento, rodando na sua máquina

Tudo o que está nesta página é código aberto, licença MIT, e roda em processador comum. O repositório não traz vídeo, nem peso de modelo, nem resultado pronto: você traz a sua imagem. Junto vem um visor de um arquivo só, que abre no navegador e lê o vídeo e os números do seu próprio disco — nada sai da sua máquina, a página não faz uma requisição de rede sequer.

A tela do visor: o vídeo com as caixas de detecção à esquerda, as leituras do instante à direita e a tabela de configurações embaixo
A tela inteira depois de instalar: o vídeo com a visão da máquina por cima, as leituras do instante à direita e, embaixo, as configurações e a tabela de linhas de contagem que vieram do arquivo de cena.

Ver o código no GitHub MIT · Python + ONNX Runtime · sem GPU · 17 testes que rodam sem vídeo e sem modelo

Rodar no seu vídeo, passo a passo

Precisa de Python 3.12 ou mais novo e do FFmpeg no PATH, que só o passo 5 usa. Do clone até o primeiro número na tela, cinco passos.

  1. Instalar
    git clone https://github.com/eucleberpaiva/plateproof.git
    cd plateproof
    python -m venv .venv
    .venv\Scripts\activate          # Linux e macOS: source .venv/bin/activate
    python -m pip install --require-hashes -r requirements.txt
    python -m plateproof.models
    python -m unittest
    O --require-hashes faz o pip recusar qualquer pacote cujo hash não seja o travado no arquivo. O plateproof.models faz o mesmo com os três modelos: baixa da fonte original e confere o SHA-256 de cada um. Se a fonte trocar o arquivo, o download falha em vez de rodar um modelo diferente.
  2. Calibrar a cena
    cp scenes/example-intersection.toml scenes/minha-cena.toml
    python -m plateproof.sample meu-video.mp4 out --n 3
    Abra os quadros que caíram em out/sheets/ num editor de imagem que mostre a posição do cursor e anote as coordenadas: onde ficam as linhas de contagem, a caixa de cada semáforo e as áreas que não são placa (logotipo, relógio). Cada campo está explicado dentro do arquivo. Essa calibragem é a única parte que dá trabalho, e é ela que faz a contagem valer alguma coisa.
  3. Processar
    python -m plateproof.analyze meu-video.mp4 scenes/minha-cena.toml out --max 300
    python -m plateproof.summarize scenes/minha-cena.toml out
    O --max 300 processa só os primeiros 300 quadros: confira a calibragem antes de entregar o vídeo inteiro. Só quer a contagem? Rode o analyze com --no-text: a placa continua sendo detectada para ser pixelada depois, mas nenhum texto e nenhum recorte é gravado.
  4. Ver
    viewer/index.html
    Abra esse arquivo no navegador e escolha o seu vídeo e o out/tracks.json. É o visor do vídeo aí em cima.
  5. Antes de mostrar o vídeo para alguém
    python -m plateproof.privacy meu-video.mp4 scenes/minha-cena.toml out
    python -m plateproof.verify out/public.mp4 scenes/minha-cena.toml out
    python -m plateproof.sample out/public.mp4 out --n 24
    O primeiro gera o vídeo com as placas pixeladas. O segundo ataca esse vídeo com o mesmo leitor de placa, mais sensível do que na análise, e sai com erro sempre que marca alguma coisa — de propósito: o veredito é seu, olhando recorte por recorte. O terceiro sorteia quadros inteiros para você conferir a olho. É a mesma conferência da seção 07 desta página.

Uma placa de veículo identifica uma pessoa. Antes de apontar isso para uma câmera: imagem que você tem direito de usar, publicação só do que passou pelo passo 5, e apagar os arquivos sensíveis quando a conferência acabar. O repositório marca, arquivo por arquivo, o que pode e o que não pode sair da sua máquina.

09 · créditos

Quem fez as peças que eu montei