Appearance
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 :
| Mode | Input | Endpoint | Rôle |
|---|---|---|---|
lab | JPEG caméra brut | /scan-lab | Path principal pgvector/DINOv2 sur le catalogue backend |
compat | JPEG caméra brut | /scan-compat | Path de comparaison FAISS via tcg-vision |
tormknd | JPEG caméra brut | Tormknd /scan | Référence upstream |
combined | JPEG caméra brut | /scan | Ancien path multi-signal : pHash + OCR + embedding |
frame | Crop pré-warpé côté client | /scan-frame | Path #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
topKdebug 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 :
msreporté par le backend dans la réponse. - Premier résultat utile : premier endpoint qui renvoie
ok: trueavec unmatchnon 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étrique | Source | Pourquoi c'est important |
|---|---|---|
| Timestamp de capture | entrée Scan Debug | Regroupe les cinq lignes endpoint |
| Filtre TCG actif | entrée Scan Debug | Explique le comportement forcé ?tcg= |
| Mode endpoint | entrée Scan Debug | Rend la comparaison A/B possible |
| Temps client elapsed | clientTotalMs ou clientMs | Ce que l'utilisateur a réellement attendu |
| Temps serveur elapsed | champ ms de la réponse | Sépare coût backend et coût téléphone/réseau |
| Timings Frame prep | clientPrepMs, clientDetectMs, clientWarpMs | Isole le coût téléphone du Path #5 |
| État du résultat | match, no-match, raison d'échec | Sépare accuracy et disponibilité |
| Confidence/similarity | champs de réponse | Aide à régler thresholds et ranking |
| Chemin du cas archivé | archive backend Scan Debug | Permet de revoir plus tard l'input exact, le crop, le top-K et le JSON backend |
| Verdict utilisateur | future UI de correction | Nécessaire pour apprendre l'accuracy réelle |
Niveaux De Dataset
On commence petit, mais les niveaux doivent rester explicites.
| Niveau | Taille | Contenu | Usage |
|---|---|---|---|
| Smoke | 5-10 images | Cartes faciles connues, une capture téléphone réelle chacune | Valider un build avant de demander plus de tests téléphone |
| Lab | 50 images | Cartes faciles, cartes visuellement proches, glare, tilt, fond mauvais | Comparer qualité et latence des endpoints |
| Régression | 200+ images | Tous les mauvais matchs et timeouts historiques | Empêcher les échecs connus de revenir |
| Produit | 500+ images | Cartes, slabs, scellés, plusieurs langues, plusieurs devices | Gate 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
- Pull les derniers repos
poc-tcg-collectoret backend. - Vérifier que les endpoints exposés répondent avec une image connue avant d'ouvrir l'app.
- Builder/installer l'app Android sur la machine de développement.
- Vider l'historique Scan Debug.
- Scanner chaque item physique trois fois :
- capture normale centrée
- léger angle
- lumière plus faible ou reflet
- Pour chaque mauvais résultat, garder le groupe Scan Debug ouvert et vérifier que le cas a été archivé.
- 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.
- 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.jsonLa 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-framePour 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
frametimeout 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 :
| Endpoint | total curl |
|---|---|
/scan-frame | 0.62 s |
/scan-lab | 0.83 s |
/scan combined | 0.84 s |
Tormknd /scan | 1.26 s |
/scan-compat | 1.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é.