Skip to content

Lab scanner scellé ​

Statut : path backend lab mergé le 2026-05-14. Mis à jour le 2026-05-20 avec la parité booster façon Tormknd, embeddings scellés DINOv2-base dédiés, preprocessing YOLO/OpenCV, routing booster_pack optionnel, filtres metadata OCR, retrieval interne élargi et diagnostics de source candidat. Mis à jour le 2026-05-23 pour mettre en pause les références scellées SKN-owned sur les scans normaux.

Le lab scanner scellé est le premier path backend dédié aux produits Pokémon scellés : boosters, displays, booster bundles, Elite Trainer Boxes, blisters, tins, mini-tins, collections et decks.

Il ne réutilise volontairement ni le schéma des cartes brutes, ni le crop de scan carte. Un produit scellé n'est pas un objet au format carte, et le forcer dans le warp perspective d'une carte ferait perdre une partie importante de la géométrie du packaging.

Le path scellé par défaut garde encore la recherche pleine image afin de comparer le lab avec la baseline initiale. Le mode preprocess=sealed est maintenant YOLO-first : le sidecar embeddings tente un modèle de segmentation scellé entraîné quand SEALED_YOLO_MODEL_PATH pointe vers un fichier valide, puis retombe sur l'ancien crop de premier plan OpenCV aligné sur les axes. Les deux chemins tournent avant DINOv2 et sont utiles pour les captures téléphone où la table, la main, l'étagère ou l'écran prennent trop de place.

La stack déployée doit être vérifiée via le payload health du sidecar : si aucun fichier YOLO entraîné n'est monté dans /models/yolo/booster_seg.pt, les scans scellés génériques peuvent encore déclencher un embedding pleine image brut défensif et retourner preprocessingFallback.reason = sealed-preprocessing-without-yolo. Quand YOLO est disponible, les scans scellés génériques comparent encore le crop avec un embedding pleine image brut et ne basculent que si le brut gagne clairement ou résout une ambiguïté ; ce fallback retourne preprocessingFallback.reason = raw-score-beats-yolo-crop. Pour les tests A/B backend booster-only, les callers peuvent encore envoyer type=booster_pack&preprocess=sealed ; ce path fait volontairement confiance au résultat de crop YOLO/OpenCV pour s'aligner sur le scanner booster tcg-app2 de Tormknd.

L'architecture cible est maintenant explicite : le scellé utilise un flow en deux cerveaux. Le premier cerveau isole le packaging physique avec YOLO quand les poids sont disponibles, ou avec OpenCV en fallback. Le second cerveau identifie le packaging isolé en l'encodant avec DINOv2 puis en cherchant dans le catalogue scellé. Les scans mobiles normaux interrogent maintenant ptcg-assets par défaut ; les références SKN-owned sont gardées pour les requêtes debug ou benchmark explicites. L'OCR n'est pas le premier étage ; c'est un reranker conditionnel et un filtre metadata sur le top-K visuel quand les expériences debug/accuracy le demandent.

La différence importante avec l'ancienne implémentation SKN est la séparation du modèle et de la géométrie booster. Les scans carte restent sur facebook/dinov2-small avec des vecteurs 384 dimensions. Les scans scellés ont maintenant leur propre sidecar sealed-embeddings en facebook/dinov2-base / ViT-B/14 avec des vecteurs 768 dimensions stockés dans sealed_product_embeddings_vitb_lab. Les embeddings scellés/raw utilisent la même géométrie d'entrée DINO que tcg-app2 (Resize(526) puis CenterCrop(518)), afin de conserver le ratio des wrappers booster avant matching. Cela reprend l'idée centrale du scanner booster tcg-app2 de Tormknd, tout en gardant notre stockage dans Postgres/pgvector au lieu de Qdrant.

Les premiers tests téléphone après le déploiement du 2026-05-18 montrent une amélioration qualitative nette de la précision avec preprocess=sealed. La raison est simple : DINOv2 compare maintenant surtout le produit scellé, au lieu de comparer le produit scellé plus le bureau, la main, l'écran, l'étagère ou d'autres pixels de fond. Le crop conserve le ratio du packaging, donc il améliore le rapport signal/bruit sans appliquer le warp perspective des cartes, qui abîmerait les boxes, blisters, tins et boosters. Cette observation est encourageante, mais elle reste un signal de test terrain tant qu'elle n'est pas mesurée sur le benchmark séparé sealed-eval.

Ce qui existe maintenant ​

Le repo backend expose :

  • POST /scan-sealed-lab sur l'API Fastify ;
  • sealed_products, sealed_product_images et sealed_product_embeddings_lab dans Postgres ;
  • sealed_product_embeddings_vitb_lab pour l'index scellé dédié en 768 dimensions ;
  • ingestSealedProductsLab.js pour ingérer les fichiers locaux de ptcg-assets ;
  • des embeddings scellés DINOv2-base pleine image via le sidecar scellé dédié avec POST /embed?mode=raw ;
  • un pré-traitement scellé YOLO-first optionnel avec POST /scan-sealed-lab?preprocess=sealed, qui appelle le sidecar avec POST /embed?mode=sealed ;
  • une comparaison brute défensive pour les scans scellés génériques : les crops OpenCV sont toujours comparés au brut, et les crops YOLO sont gardés sauf si le brut gagne clairement ou résout une ambiguïté ;
  • un matching crop-first pour les boosters quand la requête inclut type=booster_pack, comme dans tcg-app2 ;
  • des diagnostics de preprocessing avec ?debug=1, incluant méthode, bounding box, dimensions du crop et data URI JPEG du crop ;
  • un reranking OCR optionnel avec ?ocr=1, qui utilise le crop quand il existe et expose sealedOcr, rerank et les scores visuel/texte/combiné de chaque candidat ;
  • des filtres metadata OCR forts avant le ranking visuel quand c'est sûr, par exemple un texte Edition Base réduit à set_id = base1 et du texte français réduit à language = fr ;
  • des filtres de requête par type produit et langue, par exemple ?type=booster_pack&lang=en ;
  • un filtrage de source : les requêtes normales utilisent source=ptcg-assets par défaut ; le debug peut demander explicitement source=skn-owned ou source=all ;
  • des réponses metadata-only tant que la source reste internal-only.

L'endpoint retourne le meilleur match, la similarité, le runner-up, le top-K de diagnostic, le type produit, l'id de set, la langue, le chemin source et le statut de droits.

Le diagnostic du 2026-05-20 a confirmé que /scan-sealed-lab n'est pas limité aux dix photos bootstrap SKN-owned. L'index lab actif peut contenir le corpus large ptcg-assets plus les références skn-owned. Ce qui induisait en erreur était surtout la surface debug : les candidats n'exposaient pas clairement s'ils venaient de ptcg-assets ou de skn-owned, et le reranking ne pouvait travailler que sur le petit top-K SQL remonté par le premier tri vectoriel.

Le suivi du 2026-05-23 a mis en pause les références SKN-owned pour les scans scellés normaux, car ces images bootstrap possédées pouvaient dominer les résultats réels. Les requêtes runtime utilisent maintenant source=ptcg-assets par défaut, même si d'anciennes lignes skn-owned existent encore dans Postgres. source=skn-owned et source=all restent disponibles pour le debug, les tests A/B contrôlés et les benchmarks qui mesurent volontairement les références possédées.

L'endpoint récupère maintenant un pool interne de candidats plus large avant le reranking OCR, puis renvoie un topK debug compact à l'app. Cela permet à l'OCR de sauver des candidats visuellement proches qui n'étaient pas dans les dix premiers voisins, sans rendre le carousel debug mobile énorme. Les objets candidats exposent source et productType en plus de type, donc Scan Debug peut distinguer un vrai voisin ptcg-assets d'une référence bootstrap possédée.

Il retourne volontairement productDetails.image = null pour les lignes venant de ptcg-assets. Ce repo n'a pas de licence déclarée, donc SKN ne doit pas exposer ces images publiquement ni les copier dans un CDN ou un bundle app public.

L'endpoint refuse aussi les voisins quasi ex aequo. Quand le meilleur candidat a moins de 0.015 point de score combiné d'avance sur le runner-up, il retourne match: null avec reason: ambiguous-neighbor tout en gardant les diagnostics runnerUp et topK. Cela évite de présenter comme certains des variants scellés visuellement très proches. L'OCR peut maintenant résoudre une partie de ces quasi égalités quand le texte produit soutient clairement un candidat visuel.

Le filtrage OCR des noms de set mappe aussi les noms Wizards vers les IDs catalogue utilisés par ptcg-assets : Base Set / Edition Base -> base1, Jungle -> base2, Fossil / Fossile -> base3, et Team Rocket -> base5. C'est important parce qu'un filtre littéral fossil ou jungle supprimerait les bonnes lignes ptcg-assets avant le ranking visuel.

Pourquoi commencer par la recherche visuelle brute ​

Pour les produits scellés, le premier passage le plus rapide et précis est la recherche visuelle :

  1. encoder toute l'image uploadée du packaging avec DINOv2 ;
  2. chercher les plus proches voisins dans sealed_product_embeddings_vitb_lab avec pgvector HNSW ;
  3. utiliser des filtres optionnels comme le type produit ou la langue quand l'UI les connaît déjà.

L'OCR est un reranker et un filtre metadata de second niveau, pas une étape bloquante en premier. Le texte packaging est souvent déformé par le plastique, les reflets, la localisation, les photos prises en angle et les petites typographies foil. L'OCR reste utile, surtout après que la recherche visuelle a réduit la liste des candidats ou quand un mot-clé fort peut réduire l'espace de recherche sans danger.

Le garde-fou d'ambiguïté actuel contrôle les faux positifs, ce n'est pas encore le moteur d'accuracy final. Il transforme les cas proches en ambiguïtés explicites ; le path actuel en résout déjà une partie avec l'OCR sur crop, et les prochaines étapes fortes sont les poids YOLO entraînés, les filtres type produit/langue, et des benchmarks terrain plus larges.

Le mode Sealed actuel de l'app ajoute debug=1&ocr=1 et garde l'upload brut par défaut. C'est volontaire : une UI Sealed générique doit encore matcher les ETB, displays, blisters, tins, collection boxes et boosters, et un crop booster-only peut se bloquer sur un booster visible à l'intérieur d'un produit plus large. L'app ajoute seulement preprocess=sealed&typeHint=booster_pack quand l'utilisateur choisit une frame de type booster. Les tests A/B backend peuvent toujours ajouter type=booster_pack&preprocess=sealed quand ils veulent volontairement tester le path booster-only avec un filtre dur de type produit.

C'est la différence principale avec le path de démonstration booster de Tormknd : son flow est spécifique booster, alors que le mode mobile Sealed SKN est aujourd'hui un path générique produits scellés. Le matching générique est plus large, donc plus difficile. Si l'objectif de test est uniquement un booster pack, le backend supporte la même contrainte booster-only via type=booster_pack&preprocess=sealed, tandis que la frame mobile booster envoie le hint plus souple typeHint=booster_pack&preprocess=sealed ; si l'objectif produit est tous les types de scellés, il faut soit des contrôles de sous-type, soit un routing par détecteur.

Le backend matérialise aussi le set de candidats scellés filtrés avant de trier par distance vectorielle. C'est volontairement plus exact qu'une requête filtrée uniquement via ANN : le catalogue scellé est petit, et les scans HNSW filtrés peuvent sinon retourner un top-K vide même quand la famille demandée, par exemple booster_pack, contient des centaines d'embeddings.

Opérationnellement, YOLO n'est pas l'identifiant final du produit. Il détecte et croppe ou masque l'objet scellé. DINOv2 embed ensuite ce crop, puis pgvector cherche les références scellées les plus proches. Si le modèle YOLO est absent, impossible à charger, ou sous le seuil, le sidecar continue le scan avec le fallback OpenCV au lieu d'échouer. Les scans A/B explicites type=booster_pack font confiance à ce résultat crop-first ; les scans scellés génériques comparent avec un embedding pleine image brut comme garde-fou, parce que le modèle YOLO bootstrap actuel est booster-only et peut cropper un booster visible à l'intérieur d'un produit scellé plus large.

L'ingest scellé compresse aussi les uploads de références trop lourds avant de les envoyer au sidecar embeddings. Les images sources et la provenance restent inchangées, mais les très gros PNG sont envoyés comme JPEG bornés pour éviter des trous 413 file-too-large dans la table de référence 768-d.

Bootstrap YOLO depuis tcg-app2 ​

tcg-app2 contient déjà un dataset YOLO de segmentation mono-classe pour les boosters. SKN peut l'utiliser comme bootstrap local sans modifier le repo de référence et sans committer les poids entraînés.

Depuis tcg-collector-backend :

bash
scripts/train-sealed-yolo.sh
docker compose --env-file .env -f docker/compose.yml restart sealed-embeddings embeddings

Le script attend ../tcg-app2/dataset, entraîne dans l'image Docker sealed-embeddings déjà buildée, puis installe l'artefact local gitignored ici :

text
tcg-collector-backend/models/yolo/booster_seg.pt

Après redémarrage, une requête debug scellée doit remonter preprocessing.method = yolo-segmentation sur une photo de booster. Cela ferme l'écart entre "le backend supporte YOLO" et "la stack en cours d'exécution utilise vraiment YOLO".

Statut mobile ​

L'app mobile est câblée sur ce path pour le mode de test manuel scellé.

Dans poc-tcg-collector, le sélecteur de type d'objet du Scanner contrôle maintenant le plan backend :

  • Card et Slab gardent les cinq endpoints carte de diagnostic : lab, compat, tormknd, combined et frame ;
  • Sealed masque le filtre TCG carte et appelle uniquement POST /scan-sealed-lab.

Depuis poc-tcg-collector#194, la frame scellée par défaut est Auto, pas Pack. C'est volontaire. Un scan scellé générique ne doit pas envoyer typeHint=booster_pack par défaut, parce que cela biaise les ETB, displays, bundles, tins, blisters et collection boxes importés vers des voisins booster-pack avant même l'évaluation visuelle.

Les images scellées importées restent aussi neutres : l'app trace si l'input vient de la caméra ou de la librairie d'images, et les imports librairie n'héritent pas du hint de type produit de la frame active. Les tests caméra manuels peuvent toujours sélectionner la frame Pack pour envoyer le hint souple booster_pack. Cela conserve le path A/B booster sans polluer les tests scellés importés cross-type.

Le panneau de test du Scanner et l'écran Scan Debug séparé conservent les diagnostics scellés. Scan Debug étiquette ces lignes en Pokémon sealed, affiche les métadonnées type produit / langue / droits, et peut afficher input -> crop -> match/candidate. Le crop vient des diagnostics privés de preprocessing, ce qui permet de distinguer un problème de crop d'un problème de retrieval/rerank.

Les cartes candidates dans les surfaces debug affichent maintenant source et productType. Quand un résultat est mauvais, la revue d'échec devient concrète : mauvaise famille produit ptcg-assets, mauvaise langue/SKU, vraie ambiguïté visuelle, ou domination par les références bootstrap skn-owned dans un run debug où elles ont été activées explicitement.

Cela reste une surface lab. L'app ne détecte pas encore automatiquement le packaging scellé. Elle n'affiche pas les images source de ptcg-assets parce que ces lignes restent internal-only ; elle peut afficher les images debug privées des références bootstrap skn-owned via /debug/sealed-owned/....

Archive De Cas Scan Debug ​

Les builds lab internes peuvent maintenant sauvegarder les captures Scan Debug côté backend avec POST /scan-debug-cases. Ce n'est pas de la télémétrie publique et ce n'est pas un entraînement automatique de modèle. C'est une archive contrôlée de cas qui donne à l'équipe la matière première pour revoir les échecs, les labelliser, puis promouvoir les exemples utiles vers des datasets d'évaluation ou d'entraînement.

Chaque cas sauvegardé contient :

  • input.jpg : la photo originale ou l'image importée envoyée par l'app ;
  • metadata.json : type d'objet, mode de scan, id Scan Debug local, résultat backend, candidats top-K, scores, raison d'échec et timings quand ils existent ;
  • crop.jpg : crop privé de preprocessing optionnel, extrait des métadonnées debug quand le backend en a retourné un.

L'endpoint est protégé par le token d'écriture backend (API_WRITE_TOKEN) parce qu'il stocke des images fournies par l'utilisateur. L'upload mobile est opt-in via le fichier de config local gitignored dans l'app POC. Si cette config locale est absente, Scan Debug continue de fonctionner en local et aucun upload n'est tenté.

Ces cas archivés sont la boucle de feedback :

  1. scanner ou importer un vrai item ;
  2. laisser l'app sauvegarder le résultat backend et les diagnostics ;
  3. revoir le cas plus tard et marquer le produit attendu, le type d'échec et les notes utiles ;
  4. promouvoir les cas labellisés dans sealed-eval ou un autre benchmark seulement quand les images sont possédées ou explicitement autorisées ;
  5. utiliser le benchmark pour décider si le prochain fix est une meilleure détection de crop, OCR/rerank, filtrage metadata, plus de références ou un modèle entraîné.

Utiliser la commande backend après une session de test :

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

Pour la revue visuelle, ouvrir l'app backend interne Cardex et utiliser la section scan debug. Elle affiche l'input archivé et le crop à côté du match retourné, de la raison, du statut de revue et des IDs candidats top-K.

Limite interne sur les assets ​

ptcg-assets est utile pour prouver le scanner scellé parce qu'il contient un corpus large de packagings et une taxonomie de fichiers exploitable. Ce n'est pas une source production-safe à elle seule.

Le lab peut aussi indexer une petite source skn-owned : dix photos scellées françaises possédées par SKN et stockées dans tcg-collector-backend/src/api/tests/fixtures/sealed-samples. Ces lignes utilisent des IDs produit stables skn-owned:* et rights_status = 'approved'. Ce sont des références bootstrap, pas un catalogue production complet, et elles sont en pause par défaut pour les scans mobiles normaux.

Garde-fous backend actuels :

  • chaque ligne venant de ptcg-assets est marquée internal_only ;
  • chaque ligne venant de skn-owned est liée à une fixture possédée et marquée approved, mais les requêtes /scan-sealed-lab normales l'excluent par défaut ;
  • l'ingest stocke la provenance source au lieu d'URLs publiques ;
  • l'API garde productDetails.image à null et n'expose les images source que comme URLs candidates debug privées ;
  • les mounts Docker sont en lecture seule ;
  • les tables scellées sont séparées des tables cartes et des embeddings cartes.

La production demande au moins l'une de ces bases :

  • permission explicite du propriétaire des assets ;
  • licence compatible ;
  • source payante/provider avec des termes compatibles avec l'usage prévu ;
  • images uploadées par l'utilisateur, avec consentement et règles de rétention ;
  • allowlist curatée d'assets dont les droits sont documentés.

Runbook ​

Depuis tcg-collector-backend :

bash
docker compose --env-file .env -f docker/compose.yml up -d sealed-embeddings
docker compose --env-file .env -f docker/compose.yml run --rm \
  --entrypoint "node dist/ingestSealedProductsLab.js" ingest

Le défaut compose garde les références SKN-owned en pause pendant l'ingest :

bash
SEALED_INCLUDE_SKN_REFERENCES=false

Si une session debug a volontairement besoin des références bootstrap possédées, les activer explicitement et les requêter explicitement :

bash
# exemples de requêtes runtime
/scan-sealed-lab?source=skn-owned
/scan-sealed-lab?source=all

Run contraint utile :

bash
SEALED_ASSET_SETS=tcgpa2b \
SEALED_ASSET_TYPES=booster_pack \
SEALED_ASSET_LIMIT=1 \
docker compose --env-file .env -f docker/compose.yml run --rm \
  --entrypoint "node dist/ingestSealedProductsLab.js" ingest

Smoke de l'endpoint avec un JPEG :

bash
curl -s \
  -F "photo=@../ptcg-assets/tcgpa2b/packshots/booster.jpg;type=image/jpeg" \
  "http://localhost:8080/scan-sealed-lab?type=booster_pack" | jq .

Lancer le benchmark scellé sur les samples labellisés et les photos inbox optionnelles :

bash
cd src/api
npm run benchmark:sealed -- --include-inbox --json /tmp/sealed-benchmark.json

Comparer le path pleine image et le crop premier plan scellé :

bash
npm run benchmark:sealed -- --json /tmp/sealed-raw.json
npm run benchmark:sealed -- --preprocess sealed --json /tmp/sealed-crop.json

Le benchmark lit tests/fixtures/sealed-samples/manifest.json comme vérité terrain labellisée et peut aussi scanner tests/fixtures/sealed-samples/images/inbox/ comme diagnostics non labellisés. Les samples inbox sont utiles pour revoir les candidats, mais ils sont exclus de l'accuracy tant qu'ils ne sont pas promus dans le manifest.

  • exactAccuracy compte les samples labellisés dont le top-1 est l'ID produit attendu.
  • topKAccuracy compte aussi les samples labellisés dont le produit attendu apparaît dans topK après une réponse ambiguous-neighbor.
  • expectedProductId doit être préféré dès que la ligne catalogue existe ; acceptableProductIds peut contenir des variants légitimes pendant le nettoyage catalogue.

Résultat bootstrap actuel après ingestion de la source skn-owned le 2026-05-16 :

  • 10/10 exact matches sans filtre ;
  • 10/10 exact matches avec --use-label-filters ;
  • cela valide le path ingest/query/debug scellé français, mais ne doit pas être présenté comme une accuracy marché parce que les photos benchmark sont aussi les images de référence bootstrap.

Depuis le 2026-05-23, ce path bootstrap doit rester opt-in. Utiliser --source skn-owned pour valider le câblage des références possédées, ou --source all pour une comparaison explicite. Les scans mobiles normaux doivent rester sur la source par défaut ptcg-assets tant que le dataset d'évaluation terrain ne prouve pas que les références possédées améliorent la généralisation au lieu de dominer les résultats.

Dataset d'évaluation terrain ​

Les photos téléphone inédites ont maintenant un dossier d'évaluation séparé dans le backend :

text
tcg-collector-backend/src/api/tests/fixtures/sealed-eval/
  manifest.json
  images/inbox/
  images/labeled/

Ce dossier est volontairement séparé de sealed-samples. sealed-samples contient les images bootstrap SKN-owned qui peuvent être indexées comme références scellées skn-owned. sealed-eval contient des vraies photos terrain qui doivent rester hors ingest de référence, même quand elles sont labellisées. La suite de tests backend rejette les lignes evaluationOnly: true si quelqu'un tente de les ingérer comme références SKN-owned.

Utiliser images/inbox/ pour les photos possédées dont le label est encore inconnu. Utiliser images/labeled/ plus manifest.json pour les photos avec metadata attendue. Chaque ligne labellisée doit inclure :

  • evaluationOnly: true ;
  • un file JPEG relatif sous images/ ;
  • expectedProductName ;
  • expectedProductType ;
  • captureSource ;
  • rights avec la valeur owned_by_skn ou explicit_permission ;
  • expectedProductId quand la ligne catalogue existe, sinon l'évaluation metadata-only reste possible.

Lancer l'évaluation terrain depuis src/api/, avec le stack backend démarré :

bash
npm run benchmark:sealed:eval -- --json /tmp/sealed-field-eval.json

La commande inclut les photos inbox pour revue diagnostic. Un dataset encore vide peut être vérifié avec :

bash
npm run benchmark:sealed:eval -- --allow-empty

Chaque échec doit être classé avant de changer les seuils :

  • produit attendu dans le top-K : ajouter OCR ou reranking hybride ;
  • mauvais type produit dominant : ajouter filtre type produit ou crop par détecteur ;
  • produit attendu absent : ajouter des références licenciées ou améliorer le crop ;
  • photo téléphone bruitée en échec large : prioriser détection/crop scellé.

Le runner de benchmark écrit maintenant cette classification directement dans la console et le rapport JSON :

diagnosisnextActionSignification
expected-in-topkadd-ocr-rerankingLe bon produit est proche, mais le ranking final a besoin de preuve texte ou metadata.
wrong-product-typeadd-type-filter-or-detector-cropLe retrieval compare contre la mauvaise famille scellée, par exemple booster pack au lieu de blister.
wrong-languageadd-language-evidence-or-referenceL'artwork est proche, mais la preuve locale/SKU est mauvaise.
expected-absentadd-reference-or-improve-cropLe produit attendu n'est pas récupéré ; il faut ajouter des références ou améliorer le crop.
unlabeled-reviewlabel-sampleLe sample peut être revu manuellement, mais il ne compte pas encore dans l'accuracy.

Pour les runs plus larges, le résumé JSON inclut aussi summary.diagnoses et summary.nextActions, et la console imprime les agrégats diagnoses: / next actions:.

Prochaines étapes ​

  1. Remplir sealed-eval avec des photos téléphone possédées et inédites, puis le lancer séparément du benchmark bootstrap.
  2. Garder les références SKN-owned en opt-in tant que l'évaluation terrain ne montre pas qu'elles aident les photos téléphone inédites.
  3. Ajouter des contrôles de sous-type scellé ou un routing par détecteur pour les produits non-booster comme ETB / display / tin / blister.
  4. Ajouter une frame caméra adaptée aux packagings sans supposer un ratio carte.
  5. Ajouter des labels de revue et feedback de correction aux cas Scan Debug sauvegardés.
  6. Entraîner ou importer des poids YOLO scellés production-quality dans models/yolo/booster_seg.pt.
  7. Benchmarker si le scellé doit rester sur DINOv2-base + pgvector ou déplacer plus tard le vector store vers Qdrant.
  8. Définir une politique production-safe pour les assets et l'affichage image avant lancement public.

Pages liées ​