Edugiyuu/Card-Scanner

★ 0Forks 0TypeScriptGitHub ↗Compare

README

# Card Scanner Scanner web para reconhecer cartas de Magic: The Gathering pela camera e mostrar informacoes da carta em tempo real. Este projeto e separado do marketplace. O objetivo inicial e simples: abrir a camera, detectar uma carta MTG no video, tentar ler o nome impresso na carta, consultar uma API de cartas e exibir imagem oficial, preco e dados relevantes. ## Como rodar ```bash pnpm install pnpm dev ``` Abra http://127.0.0.1:3000. Comandos uteis: ```bash pnpm lint pnpm type-check pnpm build ``` Observacoes: - A camera funciona em `localhost`/`127.0.0.1` por ser contexto seguro aceito pelos navegadores. - O OpenCV e servido localmente em `/vendor/opencv.js` para evitar CDN externo e tambem evitar empacotar codigo Node no bundle do Next. - O scanner usa OCR automatico, mas a busca manual continua como fallback quando reflexo, sleeve ou baixa luz atrapalharem a leitura. ## Objetivo Quando o usuario mostrar uma carta para a camera, por exemplo `Aang's Iceberg`, o app deve: 1. Capturar o frame da camera. 2. Detectar a area da carta com OpenCV. 3. Corrigir perspectiva e melhorar contraste/nitidez. 4. Extrair o nome da carta. 5. Consultar a carta na API. 6. Exibir o resultado com imagem, preco e informacoes importantes. ## Escopo inicial O MVP cobre apenas Magic: The Gathering. Incluido no MVP: - Camera no navegador. - Deteccao visual da carta no frame. - Recorte automatico da carta. - OCR do titulo da carta. - Busca aproximada por nome. - Exibicao de imagem oficial da carta. - Exibicao de preco, raridade, set, tipo, texto Oracle e legalidades principais. - Historico local dos ultimos scans da sessao. Fora do MVP: - Compra e venda de cartas. - Login de usuario. - Inventario/colecao pessoal. - Scanner de Pokemon, Yu-Gi-Oh ou outros TCGs. - Reconhecimento perfeito de edicao/idioma/foil. - App mobile nativo. ## Stack proposta ### Frontend - Next.js com App Router. - React. - TypeScript. - TailwindCSS. - shadcn/ui para componentes. - Zustand para estado simples do scanner. - WebRTC/getUserMedia para acesso a camera. ### Computer vision - OpenCV.js no navegador para: - detectar bordas da carta; - encontrar contornos retangulares; - corrigir perspectiva; - normalizar brilho/contraste; - gerar imagem recortada para OCR. ### OCR - Tesseract.js no navegador ou em uma API route. - Inicialmente, ler apenas a regiao superior da carta, onde fica o nome. - O resultado do OCR deve passar por limpeza antes da busca: - remover caracteres estranhos; - normalizar apostrofos; - remover quebras de linha; - ignorar baixa confianca. ### API de cartas API recomendada: Scryfall. Motivos: - API publica e bem documentada para Magic. - Busca por nome exato ou aproximado. - Retorna imagens oficiais da carta. - Retorna preco em USD, EUR e tix quando disponivel. - Retorna dados de set, raridade, legalidades, texto Oracle, artista e links de compra. Endpoint principal para o MVP: ```http GET https://api.scryfall.com/cards/named?fuzzy=Aang%27s%20Iceberg ``` Headers obrigatorios: ```http User-Agent: CardScanner/0.1 Accept: application/json ``` Campos relevantes retornados pela Scryfall: - `name` - `image_uris.normal` - `image_uris.large` - `mana_cost` - `type_line` - `oracle_text` - `rarity` - `set` - `set_name` - `collector_number` - `artist` - `prices.usd` - `prices.usd_foil` - `prices.eur` - `legalities` - `purchase_uris` - `scryfall_uri` Exemplo validado com `Aang's Iceberg`: - Nome: `Aang's Iceberg` - Set: `Avatar: The Last Airbender` - Codigo do set: `tla` - Numero de colecionador: `5` - Raridade: `rare` - Tipo: `Enchantment` - Custo de mana: `{2}{W}` - Preco USD retornado na consulta: `0.41` - Preco USD foil retornado na consulta: `0.68` ## Arquitetura ```text Browser | | getUserMedia v Camera stream | | frame a cada N ms v OpenCV.js | | detecta carta + corrige perspectiva v Imagem recortada | | OCR no titulo v Nome candidato | | /api/cards/lookup?name=... v Next.js API route | | consulta Scryfall v Resultado normalizado | v UI do scanner ``` ## Modulos sugeridos ```text src/ app/ page.tsx api/ cards/ lookup/ route.ts components/ scanner/ CameraPreview.tsx ScanOverlay.tsx CardResultPanel.tsx ScanHistory.tsx features/ scanner/ scanner-store.ts use-camera.ts use-card-scanner.ts opencv-pipeline.ts ocr-pipeline.ts card-normalizer.ts lib/ scryfall.ts types/ card.ts ``` ## Fluxo de reconhecimento ### 1. Camera O app abre a camera com `navigator.mediaDevices.getUserMedia`. Configuracao inicial: - `facingMode: "environment"` em mobile. - Resolucao ideal: 1280x720 ou superior. - Botao para alternar camera quando houver mais de uma. ### 2. Deteccao da carta com OpenCV Pipeline inicial: 1. Converter frame para escala de cinza. 2. Aplicar blur leve para reduzir ruido. 3. Usar Canny para detectar bordas. 4. Encontrar contornos. 5. Filtrar contornos com formato proximo ao ratio de carta MTG. 6. Selecionar maior retangulo valido. 7. Aplicar transformacao de perspectiva. 8. Gerar recorte normalizado da carta. Ratio esperado de carta MTG: ```text 63mm x 88mm aspect ratio aproximado: 0.716 ``` ### 3. OCR do nome Depois da perspectiva corrigida: 1. Recortar a faixa superior da carta. 2. Aumentar contraste. 3. Converter para preto e branco adaptativo. 4. Rodar OCR. 5. Validar confianca minima. 6. Enviar nome candidato para a API. ### 4. Busca na API A API route do Next.js recebe o nome candidato e chama: ```http GET https://api.scryfall.com/cards/named?fuzzy={nome} ``` O backend deve normalizar a resposta para um contrato simples: ```ts export type ScannedCard = { id: string; name: string; imageUrl: string | null; largeImageUrl: string | null; manaCost: string | null; typeLine: string | null; oracleText: string | null; rarity: string | null; setCode: string | null; setName: string | null; collectorNumber: string | null; artist: string | null; prices: { usd: string | null; usdFoil: string | null; eur: string | null; tix: string | null; }; legalities: Record; scryfallUrl: string; purchaseUrls: { tcgplayer?: string; cardmarket?: string; cardhoarder?: string; }; }; ``` ## Tela principal A primeira tela deve ser o proprio scanner. Layout sugerido: - Area central com preview da camera. - Overlay com retangulo da carta detectada. - Indicador discreto de status: - `Procurando carta` - `Carta detectada` - `Lendo nome` - `Buscando dados` - `Encontrada` - `Nao reconhecida` - Painel lateral ou inferior com o resultado. - Botao para pausar scanner. - Botao para escanear novamente. - Historico dos ultimos resultados. ## Estados da aplicacao ```ts type ScannerStatus = | "idle" | "requesting-camera" | "scanning" | "card-detected" | "reading" | "searching" | "found" | "not-found" | "camera-error" | "api-error"; ``` ## Regras de UX - O usuario nao deve precisar tirar foto manualmente no fluxo principal. - O app deve evitar consultar a API em todo frame. - Aplicar debounce: buscar apenas quando o mesmo nome candidato aparecer de forma estavel. - Mostrar confianca do reconhecimento de forma simples. - Permitir correcao manual do nome quando OCR falhar. - Mostrar link para abrir a carta na Scryfall. ## Performance Recomendacoes iniciais: - Processar frames em intervalo controlado, por exemplo a cada 500ms. - Rodar OpenCV em Web Worker quando possivel. - Pausar OCR enquanto uma busca estiver em andamento. - Cachear resultados por nome normalizado. - Evitar enviar imagem da camera para backend no MVP, mantendo processamento local. ## Privacidade No MVP, o processamento visual deve acontecer no navegador. - Nao salvar frames da camera. - Nao enviar imagem da camera para servidores externos. - Enviar para o backend apenas o texto candidato extraido pelo OCR. - Permitir o uso sem conta. ## Plano de implementacao ### Fase 1 - Base do app - Criar projeto Next.js com TypeScript. - Configurar TailwindCSS e shadcn/ui. - Criar tela principal do scanner. - Implementar acesso a camera. ### Fase 2 - API de cartas - Criar cliente `lib/scryfall.ts`. - Criar rota `GET /api/cards/lookup?name=...`. - Normalizar resposta da Scryfall. - Adicionar tratamento de erro e cache simples. ### Fase 3 - OpenCV - Integrar OpenCV.js. - Detectar contorno retangular da carta. - Renderizar overlay no preview. - Gerar recorte corrigido da carta. ### Fase 4 - OCR - Integrar Tesseract.js. - Recortar area do nome. - Extrair nome candidato. - Aplicar limpeza e debounce. - Buscar dados na API. ### Fase 5 - Refinamento - Adicionar historico de scans. - Adicionar edicao manual do nome. - Melhorar feedback de confianca. - Ajustar mobile. - Criar testes unitarios para normalizacao e cliente da API. ## Riscos tecnicos - OCR pode falhar com reflexo, sleeve brilhante, baixa luz ou carta inclinada. - Cartas em outros idiomas podem retornar resultado incorreto. - A busca aproximada pode confundir cartas com nomes parecidos. - Precos da API podem estar ausentes ou desatualizados. - OpenCV.js aumenta o tamanho do bundle se carregado de forma direta. Mitigacoes: - Carregar OpenCV dinamicamente apenas na tela do scanner. - Usar confirmacao visual com imagem oficial antes de aceitar o resultado. - Permitir correcao manual. - Futuramente, combinar OCR com matching visual por imagem. ## Evolucao futura - Index local de imagens da Scryfall Bulk Data para matching visual. - Reconhecimento de set e collector number. - Suporte a cartas foil e variantes. - Suporte offline parcial. - Exportacao de scans para CSV. - Modo inventario/colecao, caso o projeto deixe de ser apenas scanner. ## Referencias - Scryfall API: https://scryfall.com/docs/api - Scryfall named card endpoint: https://scryfall.com/docs/api/cards/named - Scryfall search endpoint: https://scryfall.com/docs/api/cards/search - OpenCV.js: https://docs.opencv.org/ - Tesseract.js: https://tesseract.projectnaptha.com/ # Card-Scanner

Contributors

Edugiyuu

Issues