Serviço de identificação por visão computacional; apps mobile e web em dupla, 2026
Card Finder — a via óbvia não passou no teste
App em React Native e uma versão web que identificam cartas de Pokémon numa foto e devolvem o valor de mercado, ou uma lista de deck pronta para importar. A identificação roda num serviço próprio de visão computacional. O caminho óbvio falhou com fotos reais, e o método e o limiar de aceite que ficaram saíram do teste.
- Stack
- React Native,Expo,TypeScript,Vite,Python,FastAPI,OpenAPI
- Pilares
- Produto
- Técnica
O problema
Quem coleciona carta de Pokémon e quer saber quanto tem na mão faz isso carta a carta: digita o nome, escolhe a edição, confere o número, olha o preço. Com trinta cartas em cima da mesa, ninguém faz.
A ideia era tirar uma foto e receber os valores de volta. Depois apareceu um segundo uso: fotografar um deck montado e receber a lista pronta para importar no jogo digital.
O que descobri
Duas coisas, e as duas mudaram o caminho.
Comecei pelo óbvio: comparar imagem por hash perceptual. Ele gera uma assinatura numérica da foto e procura a mais parecida no catálogo, e é barato. Só que compara pixel, e no uso real o pixel é outro: a carta na mesa está impressa em português, o catálogo guarda o render em inglês, e o celular põe brilho no plástico. Testei outros métodos de recuperação lado a lado com ele, nas mesmas fotos, e em parte delas o hash deixava a carta certa longe do topo.
O que passou no teste foi trocar a assinatura por embedding, um vetor que descreve o conteúdo da imagem em vez dos pixels. Aí a tradução, o brilho e o ângulo pesam menos.
A segunda descoberta é do outro lado do mesmo problema: modelo de visão erra com confiança. Ele devolve uma carta que não existe naquela edição, ou acerta o nome e erra o número, e o grau de confiança que ele mesmo reporta continua alto. Num produto que fala de dinheiro, carta inventada é o usuário achando que tem um valor que não tem.
O que construí
Um serviço de identificação próprio, em Python, que roda local, e dois aplicativos em cima dele: um mobile em React Native com Expo e um web em Vite.
- A foto entra inteira e sai em cartas: o serviço acha cada carta na imagem, recorta e endireita antes de comparar.
- Acima de um limiar de similaridade o resultado é aceito direto. Abaixo dele o serviço não chuta: marca a carta como incerta e confere o nome e o número impressos antes de decidir.
- Quando o serviço próprio não responde, o app cai para um modelo externo. Só nesse caso: falha de infraestrutura tem um tipo de erro próprio, e o erro de domínio continua subindo em vez de ser engolido por um fallback genérico.
- Toda carta reconhecida é conferida numa base pública antes de aparecer na tela, e o preço vem dessa base.
- Os tipos do serviço são gerados a partir do OpenAPI dele, então mudança de contrato quebra no TypeScript, não em produção.
- A interface é uma conversa em vez de um formulário. Manda a foto, recebe as cartas.
Resultado
O teste com fotos reais mostrou onde o aceite automático estava errado: cartas erradas passavam do limiar de confiança. Subi o limiar até nenhuma passar, e esses casos voltaram para o caminho da verificação.
A imagem não resolve tudo. Quando a mesma arte aparece em edições diferentes, quem decide é o número impresso na carta.
Os dois fluxos do produto estão implementados: valor de mercado por carta, e lista de deck no formato que o Pokémon TCG Live importa.
Próximo case
Este site, construído com IA