Entrar nos 40 vem acompanhado de novos hobbies. Para alguns é o pão de fermentação natural. Para outros, jardinagem. Para mim e minha esposa, foram os pássaros.
Tudo começou com um comedouro de janela que ela instalou na cozinha. Minha reação inicial foi ceticismo puro: os pássaros vão se machucar no vidro, vai sujar tudo, os vizinhos vão reclamar. Aí apareceram alguns Finches. Depois mais. Depois chegou um cardeal, com uma aparência meio maltratada, perdendo as penas e sem topete. Decidimos chamar ele de Carequinha. Depois pousou um chapim de crista (Titmouse), e aí já era, fui vendido. Adoro Titmouse. Aquele topete e no total destemor deles é sensacional.
De repente, estávamos viciados. E sim, o projeto leva o nome deles: Titmouse (chapim, em inglês) + Raspberry Pi = TitPi.
Com o tempo compramos um Birdfy: um comedouro inteligente com câmera embutida. É um hardware bacana. Mas se você quiser identificação de espécies, precisa pagar uma assinatura. E o aplicativo é uma dor de cabeça: lento, difícil de navegar, e os downloads levam uma eternidade. Parece familiar?
Então decidi construir algo melhor.
Apresentando: TitPi. Um Raspberry Pi Zero 2W com uma câmera Sony IMX500 com IA que monitora o comedouro 24 horas por dia, 7 dias por semana, executa a detecção de objetos diretamente no chip do sensor, identifica cada visitante por espécie usando um modelo TFLite local (com fallback para o GPT-4o-mini nos casos difíceis) e serve um dashboard ao vivo com estatísticas, gráficos e um mapa de atividade dos últimos 365 dias.
Zero taxas de nuvem. Zero assinaturas. E sim, ele sabe o que é um chapim de crista.
Repositório: github.com/renanfernandes/titpi
Índice
- Hardware
- Por Que o IMX500 Muda Tudo
- Visão Geral da Arquitetura
- Detecção Baseada em Picos
- Identificação de Espécies: Pipeline em Duas Etapas
- O Dashboard
- Pássaro do Dia
- Alertas e Notificações
- Limitações e Próximos Passos
Hardware
| Componente | Modelo | Custo Aproximado |
|---|---|---|
| Placa | Raspberry Pi Zero 2W | ~$15 |
| Câmera | Sony IMX500 AI Camera | ~$70 |
| MicroSD | 32 GB+ | ~$8 |
| Case | Impresso em 3D (arquivos no GitHub) | ~$2 em filamento |
| Total | ~$95 |
A parte mais cara é o IMX500. Mas é exatamente o ponto central. Sem ele, você estaria rodando inferência na CPU do Pi, o que é lento, quente e consome muita energia num Zero. O IMX500 executa a rede neural diretamente no sensor. O Pi mal acorda até que algo interessante apareça.
O case é um design de Hanz — Raspberry Pi Zero Case + Camera V3/V2 for Tripod no MakerWorld. É ultra-compacto, tem suporte de tripé embutido (ótimo para apontar com precisão para o comedouro), e a área do GPIO pode ser facilmente cortada se você precisar de acesso aos pinos. Os arquivos STL estão incluídos no repositório.
Veja como o setup completo ficou na prática: o comedouro fica do lado de fora da janela da cozinha, e o Pi + câmera fica do lado de dentro, apontando através do vidro para ele.


Não é a instalação mais glamourosa, mas funciona perfeitamente. O vidro não afeta a qualidade da imagem a essa distância, e manter a eletrônica dentro de casa significa sem exposição ao tempo e um cabo de alimentação direto na tomada.
Por Que o IMX500 Muda Tudo
A maioria dos setups de câmera DIY funciona assim: câmera captura frames → CPU executa inferência → CPU decide o que fazer. Num Pi Zero 2W, esse pipeline é lento. Você consegue talvez 2-3 FPS com um modelo leve, alto uso de CPU em idle e muito calor para um dispositivo que fica ligado o dia todo.
O Sony IMX500 inverte esse modelo. Ele tem um acelerador de IA dedicado embutido diretamente no sensor de imagem. A inferência acontece antes do frame deixar o chip. Quando o Pi recebe os metadados, o modelo já rodou.
O que o Pi recebe do IMX500 não são pixels — é saída estruturada: bounding boxes, IDs de classe e pontuações de confiança. O Pi essencialmente recebe um relatório processado: “tem um pássaro nestas coordenadas, 78% de confiança.” Isso roda a ~10 FPS com carga de CPU quase zero no Pi.
Para uma câmera de comedouro que precisa rodar 24/7 com consumo mínimo de energia, é exatamente o que você quer.
Visão Geral da Arquitetura
Sensor IMX500 → SSD MobileNet v2 no chip → metadados de detecção
│
watcher.py
(detecção de picos + captura)
│
bird_id.py
(TFLite local → GPT-4o-mini)
│
database.py
(SQLite)
│
┌───────────────────┼───────────────────┐
notifier.py web.py compute_botd.py
(alertas por email) (dashboard) (Pássaro do Dia)
Quatro arquivos Python fazem o trabalho de verdade. O resto é configuração, templates e systemd.
Detecção Baseada em Picos
A abordagem ingênua — “disparar sempre que a pontuação de detecção de pássaro superar um limite” — parece simples, mas falha rapidamente na prática. As mudanças de iluminação ao longo do dia alteram a confiança de referência para tudo. Uma nuvem passa baixa, a cena escurece, as pontuações caem. O sol aparece, as pontuações disparam. Você teria falsos positivos ao amanhecer e perderia visitantes reais ao meio-dia.
Tem outra complicação: a câmera fica montada muito perto do comedouro. Um pintassilgo preenchendo o frame a 15 cm de distância não se parece nada com os dados de treinamento. O modelo COCO — que só conhece “pássaro” como categoria — já reportou com confiança elefantes, gansos e ursos no meu comedouro. Isso mesmo. Um urso. Num comedouro de janela. Na cidade.
A abordagem baseada em picos ajuda aqui também: não estamos confiando no que o modelo acha que vê, apenas usando a pontuação como um sinal de que algo mudou. A identificação da espécie acontece separadamente, com uma foto de close bem tirada.
O TitPi usa uma linha de base adaptativa no lugar disso. Em uma janela deslizante de 60 frames, ele rastreia a pontuação mediana de detecção para o que o modelo está vendo em idle. Um evento real não é apenas uma pontuação alta — é uma pontuação que dispara acima da linha de base atual por uma margem configurável. Dois frames consecutivos com pico são necessários antes de qualquer coisa disparar.
linha de base (mediana dos últimos 60 frames): 0,42
spike_threshold: 0,20
pontuação de gatilho: 0,42 + 0,20 = 0,62
Se o modelo pontua 0,65 em dois frames seguidos, provavelmente é um pássaro de verdade. Se pontua 0,63 uma vez após uma mudança de iluminação, a linha de base se ajusta e ignora.
Essa acabou sendo uma das partes mais importantes do sistema inteiro. Sem ela, você estaria afogado em falsos positivos.
Identificação de Espécies: Pipeline em Duas Etapas
Saber que “tem um pássaro” é o primeiro passo. Saber qual pássaro é a parte divertida.
Etapa 1 — Classificador TFLite local (rápido, sem rede)
O TitPi usa o modelo MobileNet AIY Birds V1 do Google, que classifica ~964 espécies a partir de um recorte de 224×224. Roda localmente no Pi em cerca de 300ms. Se retornar um resultado com ≥30% de confiança, está feito.
Etapa 2 — Fallback GPT-4o-mini (preciso, requer rede)
Se o modelo local estiver incerto — foto contra a luz, ângulo incomum, plumagem juvenil — a melhor foto da visita é enviada ao GPT-4o-mini via GitHub Models API. Ele retorna um objeto JSON com nome comum, nome científico, categoria e confiança.
Para evitar sobrecarregar a API (e seus limites de taxa), há um intervalo mínimo de 30 segundos entre chamadas GPT em todas as detecções simultâneas.
Limpeza de falsos positivos
Se nem o modelo local nem o GPT conseguirem identificar nada na foto, a detecção é descartada inteiramente — fotos e vídeo deletados. Isso mantém o banco de dados limpo sem curadoria manual.
O Dashboard
web.py é um pequeno app Flask que serve um dashboard de página única. Tudo é carregado via endpoints /api/* — sem renderização no servidor.

No topo você tem as estatísticas rápidas: visitas hoje, total de visitas, quantas espécies foram vistas nos últimos 30 dias, e o Pássaro do Dia com uma foto que você pode clicar para ver em tamanho completo. O pássaro de hoje é um Bluebird — e tem uma história por trás disso: um casal de Bluebirds acabou de ter três filhotes, e eles têm trazido os filhotes ao comedouro todos os dias. Ver os pais ensinando os filhotes a comer é uma experiência única.
Abaixo disso: um gráfico de rosca por espécie (clique em qualquer fatia para filtrar o feed de detecções), um gráfico de barras por hora mostrando quando o comedouro está mais movimentado, e um gráfico de atividade diária. Esse último tem um padrão de pico bem previsível — que coincide quase perfeitamente com quando coloco sementes novas (Que surpresa).

Role para baixo e você tem o mapa de calor estilo GitHub e a tabela completa de detecções. Cada linha mostra a espécie, pontuação de confiança e miniatura. Você pode clicar na foto para abrir a imagem completa — e há um clipe de vídeo anexado a cada detecção também. Alguns são genuinamente divertidos. Um dos chapins descobriu que tinha amendoins na mistura, pegou um, voou para um galho próximo e passou dois minutos abrindo. A câmera registrou tudo.
Se o modelo identificar algo errado (acontece), você pode corrigir direto na tabela.
O que tem no dashboard:
- Contagem de hoje e total de detecções de relance
- Gráfico de rosca por espécie — clique numa fatia para filtrar o feed por espécie
- Gráfico de barras por hora — quando o comedouro está mais movimentado?
- Mapa de calor de 365 dias — o gráfico de contribuições do GitHub, mas para pássaros
- Lightbox de fotos — clique em qualquer detecção para ver a imagem completa
- Gerenciamento em massa — selecione múltiplas detecções para editar espécie ou deletar
O mapa de calor é meu recurso favorito. Depois de alguns meses você começa a ver padrões: quais semanas tiveram mais atividade, chegadas sazonais, o período quieto no final do verão.
Pássaro do Dia
Todo dia às 19h, um serviço systemd de execução única roda o compute_botd.py. Ele escolhe o melhor pássaro do dia usando um sistema de pontuação:
- Primeiro avistamento sempre vence — uma espécie nunca vista antes no banco de dados sempre bate um visitante recorrente, independentemente do número de visitas.
- Se não houver espécie nova, a espécie mais visitada vence.
- Detecções com estrela adicionam pontos bônus — marcar uma foto com estrela sinaliza qualidade, então cada estrela adiciona +3 à pontuação da espécie.
A foto vencedora é copiada para detections/bird_of_the_day/ e exibida em destaque no dashboard.
Alertas e Notificações
A cada detecção confirmada, o notifier.py envia um e-mail HTML com:
- Foto inline do visitante
- Nome comum, nome científico e confiança
- Se a identificação veio do modelo local ou do GPT
- Link para o dashboard (ou vídeo anexado, configurável)
O template de e-mail usa um renderizador personalizado simples — apenas substituição de {{ variável }} e condicionais {% if %}, sem precisar do Jinja2 no Pi.
Limitações e Próximos Passos
Isso é uma v1. Funciona bem o suficiente para eu usar diariamente há meses, mas tem limitações reais:
- IMX500 é o único caminho suportado para câmera com IA — o Camera Module 3 funciona via fallback de detecção de movimento, mas é muito menos preciso
- GPT-4o-mini custa dinheiro — valores pequenos, mas é a única parte com custo contínuo. Um modelo local melhor eliminaria isso completamente
- Sem política de retenção — detecções acumulam. Num cartão de 32 GB isso não é problema por um bom tempo, mas é algo a monitorar
- Nó único — sem backup remoto ainda
Coisas que quero adicionar:
- Notificações push (ntfy / Pushover) como alternativa ao e-mail
- Integração com Home Assistant — mostrar o último visitante num card do dashboard
- Modelo local melhor — o AIY Birds V1 é de 2019. Modelos mais novos melhorariam significativamente a precisão
- Política de retenção/limpeza para detecções antigas
Se você construir um, adoraria saber o que aparece no seu comedouro. Abra uma issue ou deixe um comentário abaixo.
Tem algo silenciosamente satisfatório num computador de $95 lá fora, observando pássaros, fazendo inferência de IA real na borda e conhecendo cada visitante pelo nome — sem assinatura, sem nuvem, sem dados indo a lugar nenhum que você não escolheu.
Construa o seu: github.com/renanfernandes/titpi
Bônus: Uma Captura Real do TitPi
E por último, a prova de que funciona! Este chapim de crista foi capturado pelo próprio TitPi essa semana. Sem encenação, sem foto de banco de imagens. Só nosso modelo aparecendo, pegando uma semente e curtindo a vida!

O homônimo, em carne e osso. É exatamente por isso que construí essa coisa.