Skip to content

Protocole D'évaluation Du Scan ​

Cette page définit comment évaluer la vitesse et l'accuracy du scanner entre l'app mobile, les endpoints backend et les futurs flows scellés/slabs. Le but n'est pas "le modèle avait l'air bon une fois"; le but est un protocole répétable qui dit quel path est rapide, quel path est correct et quel fallback UX permet à l'utilisateur de réussir.

Périmètre ​

Paths de fan-out mobile actuels :

ModeInputEndpointRôle
labJPEG caméra brut/scan-labPath principal pgvector/DINOv2 sur le catalogue backend
compatJPEG caméra brut/scan-compatPath de comparaison FAISS via tcg-vision
tormkndJPEG caméra brutTormknd /scanRéférence upstream
combinedJPEG caméra brut/scanAncien path multi-signal : pHash + OCR + embedding
frameCrop pré-warpé côté client/scan-framePath #5 expérimental : crop OpenCV sur le téléphone avant embedding backend

Les futurs modes doivent rentrer dans ce protocole avant de devenir candidats produit : slabs, scellés, labels gradés et tout path hybride OCR-first.

Définitions ​

  • Accuracy top-1 : le premier match affiché est exactement l'item attendu.
  • Récupérabilité top-3 : l'item attendu apparaît dans les alternatives ou le topK debug quand il existe.
  • Accuracy de réussite utilisateur : l'utilisateur peut finir le flow correctement via le top match, les alternatives ou l'UI de correction. C'est la cible produit; elle peut approcher 100% même quand le top-1 brut ne peut pas.
  • Latence client : temps wall-clock observé par le téléphone autour du prep/upload/réseau.
  • Latence serveur : ms reporté par le backend dans la réponse.
  • Premier résultat utile : premier endpoint qui renvoie ok: true avec un match non null.
  • Path bloquant : endpoint qui retarde l'état scanner alors qu'un autre endpoint a déjà produit un résultat utile.

Métriques Par Capture ​

Chaque photo capturée doit enregistrer :

MétriqueSourcePourquoi c'est important
Timestamp de captureentrée Scan DebugRegroupe les cinq lignes endpoint
Filtre TCG actifentrée Scan DebugExplique le comportement forcé ?tcg=
Mode endpointentrée Scan DebugRend la comparaison A/B possible
Temps client elapsedclientTotalMs ou clientMsCe que l'utilisateur a réellement attendu
Temps serveur elapsedchamp ms de la réponseSépare coût backend et coût téléphone/réseau
Timings Frame prepclientPrepMs, clientDetectMs, clientWarpMsIsole le coût téléphone du Path #5
État du résultatmatch, no-match, raison d'échecSépare accuracy et disponibilité
Confidence/similaritychamps de réponseAide à régler thresholds et ranking
Chemin du cas archivéarchive backend Scan DebugPermet de revoir plus tard l'input exact, le crop, le top-K et le JSON backend
Verdict utilisateurfuture UI de correctionNécessaire pour apprendre l'accuracy réelle

Niveaux De Dataset ​

On commence petit, mais les niveaux doivent rester explicites.

NiveauTailleContenuUsage
Smoke5-10 imagesCartes faciles connues, une capture téléphone réelle chacuneValider un build avant de demander plus de tests téléphone
Lab50 imagesCartes faciles, cartes visuellement proches, glare, tilt, fond mauvaisComparer qualité et latence des endpoints
Régression200+ imagesTous les mauvais matchs et timeouts historiquesEmpêcher les échecs connus de revenir
Produit500+ imagesCartes, slabs, scellés, plusieurs langues, plusieurs devicesGate release pour l'UX scanner

Chaque ligne de dataset doit contenir :

  • image_id
  • id de l'item attendu
  • type d'item : card, slab, sealed
  • TCG
  • langue
  • set / famille produit
  • notes de variante : holo, reverse, promo, société de grading, grade, type de scellé
  • contexte de capture : device, lumière, fond, distance, angle
  • alternatives acceptables attendues, si besoin

Runbook De Test Téléphone ​

  1. Pull les derniers repos poc-tcg-collector et backend.
  2. Vérifier que les endpoints exposés répondent avec une image connue avant d'ouvrir l'app.
  3. Builder/installer l'app Android sur la machine de développement.
  4. Vider l'historique Scan Debug.
  5. Scanner chaque item physique trois fois :
    • capture normale centrée
    • léger angle
    • lumière plus faible ou reflet
  6. Pour chaque mauvais résultat, garder le groupe Scan Debug ouvert et vérifier que le cas a été archivé.
  7. Sauvegarder un screenshot seulement quand le bug concerne l'UI elle-même ; l'archive backend du cas est la source de vérité pour la revue de reconnaissance.
  8. Noter si l'utilisateur pouvait quand même finir correctement via alternatives ou correction.

Archive De Cas Scan Debug ​

L'app peut uploader des cas Scan Debug dans l'archive lab backend quand la config locale d'upload est activée. L'archive stocke l'image d'entrée, le JSON de résultat backend, les candidats top-K, les champs de latence et le crop privé quand le preprocessing debug en a retourné un.

Traiter cette archive comme une file d'entrée machine-learning, pas comme un dataset d'entraînement. Un cas devient utile seulement après qu'un humain a labellisé l'item attendu, marqué si le match affiché était correct, et classé le mode d'échec. Les cas labellisés peuvent ensuite être copiés dans le dossier benchmark approprié, comme sealed-eval, quand les droits sont clairs.

Après une session de test téléphone, lancer la commande de revue backend :

bash
cd tcg-collector-backend/src/api
npm run scan-debug:review -- \
  --markdown /tmp/scan-debug-review.md \
  --json /tmp/scan-debug-review.json

La commande vérifie chaque dossier de cas archivé, contrôle que input.jpg et metadata.json existent, détecte le crop.jpg optionnel, compte les réponses ambiguës et les labels manquants, puis écrit un rapport Markdown pour la revue humaine.

L'app backend interne Cardex a aussi une section protégée scan debug. Elle lit la même archive via GET /scan-debug-cases, puis récupère input.jpg et crop.jpg via des URLs d'artefacts authentifiées par bearer token. Utiliser cet écran pour une revue visuelle rapide après un batch de tests associé : comparer l'input uploadé, le crop, le match du scanner, la raison et les IDs top-K avant d'ajouter le verdict humain.

Commande Smoke Backend ​

À utiliser seulement comme smoke test de disponibilité backend. Cela ne remplace pas le test téléphone, car cette commande n'exerce pas la capture caméra, le réseau Android ni le prep Frame côté client.

bash
img=/home/kael/skn-tcg/scan-debug.jpeg
curl -sS -m 12 -w "lab http=%{http_code} total=%{time_total}s\n" \
  -F "photo=@$img;type=image/jpeg" http://127.0.0.1:8080/scan-lab
curl -sS -m 12 -w "frame http=%{http_code} total=%{time_total}s\n" \
  -F "photo=@$img;type=image/jpeg" http://127.0.0.1:8080/scan-frame

Pour Tormknd, le champ multipart est file, pas photo.

Règles De Décision ​

  • Garder les cinq endpoints tant qu'on compare le comportement scanner.
  • Ne pas promouvoir un path parce qu'il gagne sur un screenshot; le promouvoir quand il gagne sur le niveau de dataset ciblé.
  • Si un endpoint est lent mais unique à être correct, le garder comme candidat secondaire/correction.
  • Si un endpoint est rapide mais souvent faux, le garder visible seulement en mode lab tant que le ranking n'est pas fixé.
  • Si frame timeout souvent et que les quatre endpoints raw-photo identifient déjà correctement, rendre Frame opt-in ou le garder debug-only.
  • Mesurer séparément la réussite utilisateur et le top-1 brut. Le produit peut être excellent si l'UI rend la correction rapide et apprend de cette correction.

Baseline Actuelle ​

Le 2026-05-13, un smoke VPS sur scan-debug.jpeg a donné environ :

Endpointtotal curl
/scan-frame0.62 s
/scan-lab0.83 s
/scan combined0.84 s
Tormknd /scan1.26 s
/scan-compat1.42 s

Cela suggère que la lenteur visible du Path #5 doit d'abord être investiguée dans le prep OpenCV côté Android, pas dans /scan-frame lui-même. Les captures téléphone restent la source de vérité.