Skip to content

Stratégie d'optimisation de la reconnaissance ​

Statut : stratégie de travail capturée le 2026-05-14 ; diagnostic accuracy scellé mis à jour le 2026-05-20.

Cette page documente la discussion sur l'optimisation de la reconnaissance scanner pour les cartes, les slabs et les produits scellés. Ce n'est pas un gel d'architecture définitif. C'est la direction actuelle pour rendre les résultats plus rapides, plus précis et plus explicables pendant que l'app Android reste une surface de test.

Objectif ​

Le scanner cible doit paraître instantané, mais la vraie promesse produit est l'accuracy : un utilisateur doit pouvoir scanner une carte brute, une carte gradée ou un produit scellé et comprendre pourquoi SKN a choisi ce résultat.

La cible long terme est :

  • très forte accuracy top-1 sur captures propres ;
  • ambiguïté explicite quand des produits sont visuellement trop proches ;
  • diagnostics top-K en mode debug ;
  • support des cartes brutes, slabs, labels gradés, boosters, displays, ETB, tins, blisters, collections et decks ;
  • résultat explicable combinant similarité visuelle, OCR, metadata produit, langue et contexte pricing.

Modèle mental actuel ​

Le stack de retrieval visuel actuel doit être compris comme deux responsabilités séparées.

DINOv2 est l'encodeur visuel. Il transforme une image en embedding : un vecteur de nombres qui représente le contenu visuel. Il ne répond pas directement "c'est le produit scellé Edition Base Ptera". Il produit une représentation où des images visuellement proches doivent se retrouver proches.

FAISS et pgvector sont des moteurs de recherche de plus proches voisins. Ils cherchent dans des embeddings déjà calculés pour les assets de référence et retournent les candidats les plus proches.

Le flow lab scellé actuel est donc :

text
images scellées de référence
-> embeddings DINOv2
-> index vectoriel

capture téléphone
-> embedding DINOv2
-> recherche nearest-neighbour
-> top-K candidats scellés
-> garde-fou d'ambiguïté / résultat

C'est de la similarité visuelle, pas de l'OCR. C'est rapide et utile, mais cela ne lit pas de manière fiable les noms produit, codes de set, langues, labels de grading ou codes-barres.

Réindexer versus réentraîner ​

Le système actuel utilise DINOv2 frozen. La plupart des améliorations doivent venir d'un meilleur index et d'une meilleure évaluation avant tout fine-tuning du modèle.

Réindexer signifie :

text
nouvelle image de référence
-> embedding DINOv2
-> insertion dans FAISS / pgvector

C'est relativement rapide, simple à opérer, et cela doit être fait quand le corpus de référence change.

Réentraîner ou fine-tuner signifie modifier les poids du modèle. C'est un investissement plus tardif qui demande un dataset labellisé, des hard negatives, du budget GPU et des métriques d'évaluation stables. Pour les produits scellés, ce ne doit pas être le premier fix.

Ordre recommandé :

  1. Construire un benchmark labellisé de photos téléphone.
  2. Améliorer la couverture et les metadata des références.
  3. Ajouter des filtres type produit et langue.
  4. Améliorer crop et gestion de perspective.
  5. Ajouter OCR et reranking hybride.
  6. Ajouter un reranker entraîné ou un fine-tuning metric-learning seulement quand le benchmark montre précisément où le retrieval échoue.

Pourquoi le scellé est plus dur que les cartes ​

Les produits scellés ne sont pas des objets au format carte. Booster, ETB, display, blister, tin et collection box ont des ratios différents, des surfaces réfléchissantes, logos, noms produit, textes régionaux et artworks répétés.

Le comportement actuel ambiguous-neighbor est volontaire. Si le meilleur candidat est trop proche du runner-up, le backend doit refuser de prétendre qu'il sait. C'est un contrôle des faux positifs, pas la solution finale d'accuracy.

Les prochains gains d'accuracy pour le scellé doivent venir de :

  • détection et crop spécifiques au scellé ;
  • filtres type produit depuis l'UI ;
  • OCR sur les candidats top-K ;
  • reranker hybride qui pondère similarité visuelle, preuve texte, langue, metadata de set et type produit ;
  • images benchmark capturées depuis de vrais téléphones, avec reflets, angle, screenshots, photos d'écran, plastique et crops partiels.

Diagnostic accuracy scellé actuel — 2026-05-16 ​

Le premier passage sur dix photos scellées françaises SKN-owned a montré clairement le vrai blocage :

  • avant l'existence de références françaises, le benchmark strict était à 0/10 exact ou recoveries top-K ;
  • la recherche visuelle non filtrée retournait quand même des voisins utiles : 8 images sur 10 retournaient ambiguous-neighbor, et 2 images sur 10 retournaient un top-1 non français ;
  • la recherche filtrée avec lang=fr retournait no-match-after-filter sur les 10 images ;
  • le catalogue scellé indexé contenait des produits en, de, ja et ko, mais aucun produit scellé fr.

Le fix bootstrap du 2026-05-16 a ajouté une source séparée skn-owned avec les dix photos françaises possédées comme références approuvées, puis réingéré l'index scellé. Le benchmark indique maintenant :

  • 10/10 exact matches sans filtre ;
  • 10/10 exact matches avec --use-label-filters ;
  • les lignes skn-owned sont des références bootstrap approuvées avec IDs stables.

Ce résultat valide le path ingest/query/debug scellé français. Ce n'est pas encore un score d'accuracy marché production, parce que les photos benchmark sont aussi les images de référence bootstrap.

Le diagnostic complémentaire du 2026-05-20 a corrigé un faux modèle mental venu des tests terrain : le scanner scellé ne comparait pas seulement contre les dix photos skn-owned. L'index actif contient le corpus large ptcg-assets plus ces références possédées. Le vrai problème pratique était que l'app ne montrait pas clairement la source des candidats, et que le reranker backend n'avait accès qu'au premier set de candidats trop étroit.

Le backend maintenant :

  • récupère un pool interne de candidats scellés plus large avant le reranking OCR/texte ;
  • renvoie toujours un top-K debug compact à l'app mobile ;
  • expose source et productType sur chaque candidat pour grouper les échecs par ptcg-assets versus skn-owned et par famille scellée ;
  • mappe les termes OCR Wizards vers les vrais IDs de set ptcg-assets : base1, base2, base3 et base5.

Le suivi du 2026-05-23 a mis skn-owned en pause pour les scans scellés normaux. Ces lignes sont utiles pour valider le câblage des références possédées et pour des expériences benchmark, mais elles peuvent dominer les vrais scans parce qu'elles représentent un petit set bootstrap déséquilibré au lieu d'un catalogue marché équilibré. /scan-sealed-lab utilise maintenant source=ptcg-assets par défaut ; utiliser source=skn-owned ou source=all uniquement quand le test a volontairement besoin de ces lignes.

Cela ne rend pas le matching scellé générique équivalent à une démo booster-only. Cela rend le debug et le reranking honnêtes. Le path booster visible de Tormknd est contraint aux boosters ; le mode mobile Sealed de SKN est aujourd'hui plus large et doit comparer boosters, ETB, displays, blisters, tins, collection boxes et decks tant qu'un filtre de sous-type ou un routing par détecteur n'est pas ajouté.

Les deux modes d'échec observés les plus importants :

  • Confusion langue / SKU. Une photo française de booster Tortank Edition Base peut remonter le booster allemand Base Set Blastoise en top-1, car l'artwork est proche et il n'existe pas de référence française indexée.
  • Confusion type produit. Une photo de blister Wizards peut remonter des boosters ou des blisters non pertinents parce que le flow actuel embed l'image complète et ne détecte ni n'impose encore le type produit.

Cela confirme que le prochain gain scellé ne doit pas être un simple réglage de seuil. La priorité est maintenant :

  1. collecter des photos téléphone françaises inédites et les garder hors du set de référence ;
  2. garder les références SKN-owned en opt-in tant que l'évaluation terrain ne prouve pas qu'elles aident les photos inédites ;
  3. ajouter davantage de références scellées françaises possédées ou licenciées ;
  4. ajouter détection / filtrage par type produit ;
  5. ajouter OCR et reranking hybride sur le top-K visuel ;
  6. continuer à utiliser le benchmark scellé avant de changer les poids modèle.

Enseignements de DogBreed_Classifier ​

Le repo local DogBreed_Classifier n'est pas directement réutilisable pour la reconnaissance de scellés. C'est un classifieur fermé TensorFlow/Keras entraîné pour des races de chiens, et les fichiers .h5 locaux sont des pointeurs Git LFS plutôt que les poids téléchargés.

Il reste utile comme pattern de référence :

  • dossiers d'images groupés par classe ;
  • split train/validation ;
  • transfer learning ;
  • augmentation ;
  • suivi de l'accuracy top-1 ;
  • petite app d'inférence qui retourne label et confiance.

Pour SKN, l'adaptation utile n'est pas "utiliser le modèle chien". L'adaptation utile est de créer un benchmark produits scellés, puis éventuellement un classifier/reranker scellé quand il y aura assez d'exemples labellisés.

Rôle de YOLO ​

YOLO est utile pour la détection, pas pour l'identité finale du produit.

Le pipeline pratique devrait être :

text
image téléphone brute
-> YOLO détecte carte / slab / scellé / label gradé / zone barcode
-> crop ou segmentation de la région utile
-> DINOv2 + recherche vectorielle récupèrent les candidats visuels
-> OCR lit les zones texte ciblées
-> reranker hybride choisit ou refuse un résultat

YOLOv10 est attirant pour la détection basse latence parce que son design supprime le NMS en inférence et vise l'efficacité temps réel. YOLO11 est le premier candidat le plus pragmatique pour ce projet, car l'écosystème Ultralytics supporte détection, segmentation, classification, boîtes orientées, training, validation et export dans un seul workflow.

Les premières classes YOLO doivent rester larges :

  • card
  • slab
  • sealed
  • graded_label
  • barcode

Le modèle ne doit apprendre des classes scellées plus fines qu'après validation de cette détection large : booster_pack, booster_box, elite_trainer_box, tin, blister, collection_box.

Note légale : Ultralytics YOLO11 est distribué sous AGPL-3.0 ou licence Enterprise commerciale. Tout usage production dans une app commerciale fermée doit passer par une revue licence avant livraison.

Dataset photos réelles pour la détection scellé ​

ptcg-assets peut bootstrap la typologie scellée parce que ses dossiers encodent déjà des familles produits utiles : packshots, Elite Trainer Boxes, displays, collections, blisters, tins, mini-tins, booster bundles et decks. C'est donc une bonne source pour générer un premier dataset YOLO interne avec des classes larges et des boxes simples.

Mais cela ne suffit pas seul. Les images ptcg-assets sont surtout des images catalogue propres. Le scanner Android recevra des vraies captures téléphone avec fonds de table, mains, reflets, plastique brillant, perspective, crops partiels, photos d'écran, faible lumière et produits pas parfaitement centrés. Un détecteur entraîné seulement sur des assets catalogue peut apprendre "image catalogue" au lieu de "vrai objet scellé".

YOLO doit classifier la typologie, pas l'identité produit exacte :

text
sealed_booster_pack
sealed_blister
sealed_booster_display
sealed_elite_trainer_box
sealed_collection_box
sealed_tin
sealed_booster_bundle
card
slab
slab_label

Il ne faut pas entraîner des classes YOLO comme Base Set Blastoise Booster FR. L'identité produit exacte appartient à DINOv2, aux filtres metadata, à l'OCR et au reranking après le crop.

Cibles dataset recommandées :

  • POC utile : 30 à 50 vraies photos téléphone par classe prioritaire, soit environ 200 à 350 photos au total pour booster_pack, blister, elite_trainer_box, booster_display, collection_box, slab et card.
  • Bêta stable : 100 à 200 vraies photos téléphone par classe, soit environ 700 à 1 400 photos au total sur les mêmes classes.
  • Niveau produit : 300+ vraies photos par classe, 2 000+ photos à terme, avec hard negatives et cas d'échec répétés.

La première cible pratique :

text
50 ETB
50 booster packs
50 blisters
50 displays
50 collection boxes
30 slabs
30 cards

Cela donne environ 310 vraies photos. Le split doit rester honnête :

  • train set : utilisé pour entraîner / fine-tuner YOLO ;
  • validation set : utilisé pendant les réglages ;
  • test set : jamais utilisé pour entraîner ou régler, seulement pour reporter l'accuracy.

Pour un premier set de 310 photos, un split pragmatique est environ 250 train / 60 test, ou 220 train / 30 validation / 60 test si une validation est nécessaire. Les photos de test doivent rester inédites et inclure des captures difficiles, pas seulement des photos propres.

Protocole d'évaluation terrain scellé ​

Avant d'entraîner YOLO ou de changer les seuils de similarité, SKN a besoin d'une boucle d'évaluation honnête pour le retrieval scellé.

Le backend sépare maintenant deux rôles de fixtures :

  • tests/fixtures/sealed-samples : références bootstrap SKN-owned qui peuvent être ingérées comme produits scellés skn-owned.
  • tests/fixtures/sealed-eval : photos téléphone SKN-owned ou avec permission explicite, utilisées uniquement pour l'évaluation. Ces lignes doivent utiliser evaluationOnly: true et sont bloquées côté ingest de référence SKN-owned.

Cette distinction est importante. Si la même image sert de référence et d'échantillon benchmark, un score de 100 % prouve seulement le câblage. Si l'échantillon est inédit pour l'index, les échecs deviennent de vraies données produit.

Lancer l'évaluation avec :

bash
cd tcg-collector-backend/src/api
npm run benchmark:sealed:eval -- --json /tmp/sealed-field-eval.json

Utiliser le rapport pour choisir la prochaine action d'ingénierie :

  • produit attendu dans le top-K mais pas top-1 : ajouter OCR et reranking hybride ;
  • type produit correct absent du top-K : ajouter des références ou améliorer le crop ;
  • mauvais type produit dominant : ajouter détection de typologie ou forcer un filtre UI ;
  • candidats tous bruités visuellement : collecter plus de captures terrain et prioriser le crop par détecteur ;
  • confusion langue/SKU récurrente : ajouter preuve de langue et références régionales.

Le rapport expose ces champs lisibles par machine pour grouper les échecs sur beaucoup de photos :

  • diagnosis=expected-in-topk, nextAction=add-ocr-reranking ;
  • diagnosis=wrong-product-type, nextAction=add-type-filter-or-detector-crop ;
  • diagnosis=wrong-language, nextAction=add-language-evidence-or-reference ;
  • diagnosis=expected-absent, nextAction=add-reference-or-improve-crop ;
  • diagnosis=unlabeled-review, nextAction=label-sample.

Utiliser les agrégats summary.diagnoses et summary.nextActions pour décider si le prochain sprint doit cibler OCR/reranking, typologie/crop, couverture langue/références, ou encore références/crop.

OCR et reranking ​

L'OCR ne doit pas être la première étape bloquante. L'OCR pleine image est bruité sur les packagings brillants, le plastique, les photos en angle et les petites typographies foil.

L'OCR doit être ciblé après retrieval candidat :

text
top-K visuel
-> OCR sur zones titre produit / set code / langue / label gradé / barcode
-> comparaison des preuves OCR aux metadata candidates
-> rerank ou statut ambiguous

Pour les slabs, l'OCR doit cibler :

  • société de grading ;
  • valeur de grade ;
  • nom de carte sur le label ;
  • numéro de certification ;
  • set ou année quand visible.

Pour le scellé, l'OCR doit cibler :

  • nom produit ;
  • nom de set ;
  • langue ;
  • type produit ;
  • barcode ou code produit quand visible.

Pour les cartes brutes, l'OCR reste ciblé sur :

  • collector number ;
  • set code ou set symbol ;
  • rareté ;
  • langue si nécessaire.

Architecture cible ​

text
capture / image importée
-> détection objet : carte / slab / scellé / label / barcode
-> crop, deskew et quality scoring
-> embedding visuel DINOv2
-> retrieval vectoriel avec filtres metadata
-> OCR ciblé sur les zones utiles
-> reranking hybride
-> politique confiance et ambiguïté
-> résultat final ou résultat ambigu explicite

Le mode debug doit préserver chaque candidat et chaque score. Le scanner normal doit afficher un résultat rapide et propre, tandis que Scan Debug doit exposer tout le chemin de raisonnement.

Les cas Scan Debug peuvent aussi être uploadés dans l'archive lab backend. Cela transforme les scans téléphone individuels en file d'entrée façon machine-learning : image d'entrée, crop optionnel, JSON backend, candidats top-K, scores, timings et raison d'échec. Ces cas ne sont pas des données d'entraînement tant qu'un reviewer n'a pas ajouté le produit attendu, le verdict correct/incorrect, le statut de droits et le label d'échec.

État du cadrage mobile ​

Au 2026-05-20, le scanner React Native expose des presets de cadre manuels avant capture :

  • carte : cadre carte standard et cadre plus serré avec zoom ;
  • slab : cadre slab complet et cadre centré label ;
  • scellé : booster vertical, box rectangulaire, produit carré et display large.

Chaque preset porte à la fois la géométrie du guide et le zoom caméra demandé. Cela améliore les tests terrain immédiatement parce que l'utilisateur n'a plus besoin de forcer tous les scellés dans le même overlay vertical.

Ce n'est pas encore de la détection automatique d'objet. Le vrai cadrage auto appartient toujours au path avec détecteur :

text
caméra live / image importée
-> détecter l'objet carte / slab / scellé
-> choisir la géométrie de crop correspondante
-> crop ou warp
-> envoyer l'image normalisée au retrieval

Tant que ce path n'est pas livré, le preset manuel est un hint contrôlé par l'utilisateur. Le preset Pack est volontairement câblé comme un path laboratoire spécifique booster : l'app envoie preprocess=sealed&typeHint=booster_pack, donc le backend peut reproduire le flow booster de tcg-app2 en croppant le pack d'abord, tout en gardant un hint plus souple que le filtre A/B backend dur type=booster_pack. Box, Square et Wide restent des presets scellés plus larges pour comparaison tant que leur routing détecteur/type n'est pas prouvé.

Benchmarker avant de changer le modèle ​

Le projet a besoin d'un benchmark petit mais réel avant d'ajouter du ML plus lourd.

Benchmark scellé minimum utile :

  • 5 à 10 vraies photos téléphone par produit cible pour les premiers smoke tests ;
  • 30 à 50 photos par famille de produits confusants pour un vrai travail d'accuracy ;
  • exemples négatifs de produits scellés visuellement proches ;
  • captures avec reflets, angle, faible lumière, erreurs de crop, photos d'écran et reflets de packaging ;
  • product id attendu, type, langue et notes.

Métriques :

  • accuracy top-1 ;
  • recall top-3 et top-5 ;
  • taux d'ambiguïté ;
  • taux de faux positifs ;
  • latence par étape ;
  • hit rate OCR sur zones ciblées ;
  • réussite de correction quand l'utilisateur choisit dans le top-K.

Roadmap recommandée ​

Maintenant ​

  • Garder les cinq endpoints carte pour les tests app.
  • Garder l'endpoint scellé comme path lab.
  • Ajouter l'import d'image pour accélérer les tests répétés.
  • Préserver les diagnostics top-K dans Scan Debug.
  • Archiver les cas Scan Debug pour labellisation humaine et promotion ultérieure en benchmark.
  • Utiliser le preset Pack comme path spécifique booster, et le comparer aux presets scellés plus larges.
  • Collecter des samples téléphone réels pour les échecs scellés.

Prochaine étape ​

  • Ajouter la détection YOLO large pour carte / slab / scellé.
  • Appliquer un crop spécifique scellé avant le retrieval DINOv2.
  • Ajouter des hints de type produit sûrs pour les presets box, carré et large après preuve benchmark.
  • Ajouter OCR sur les candidats top-K scellés.
  • Ajouter un reranker hybride et garder ambiguous-neighbor comme refus sûr.

Plus tard ​

  • Entraîner un reranker ou classifier scellé avec le benchmark.
  • Envisager le fine-tuning metric-learning seulement quand le benchmark prouve le mode d'échec.
  • Ajouter OCR de label slab et parsing des sociétés de grading.
  • Ajouter des sources d'assets production-safe et contrôles licence avant tout serving public.

Références externes ​

Pages liées ​