YELY_AI_Module / docs /PREPROCESSING.md
danielxdata's picture
Module IA YELY - CRNN fine-tune, API FastAPI, interface demo
b510add
|
Raw
History Blame Contribute Delete
3.03 kB

Prétraitement (app/preprocessing.py)

detect_screen_region(img)

Cherche automatiquement la zone rectangulaire de l'écran LCD dans la photo, avant tout traitement.

Méthode : niveaux de gris → flou gaussien → détection de contours (Canny) → fermeture morphologique pour relier les segments → on garde le plus grand rectangle candidat dont le ratio largeur/hauteur est plausible pour un écran (entre 1.0 et 8.0) et dont l'aire dépasse 2% de l'image.

Limite connue et importante : cette heuristique cherche "le plus grand rectangle contrasté", pas spécifiquement un écran LCD. Sur certaines photos, elle capture par erreur le bandeau de marque du carburant (ex. "Shell FuelSave Super") au lieu de l'écran numérique, parce que ce bandeau forme un rectangle net et contrasté lui aussi. Repéré concrètement pendant cette session sur 20260622_112333_023.jpg/024.jpg : la détection automatique renvoyait le bandeau jaune, pas l'écran noir avec les chiffres.

Si le pipeline ne trouve aucune donnée exploitable sur une photo qui en contient pourtant, c'est le premier endroit à vérifier — visualiser le crop retourné par cette fonction avant d'aller chercher plus loin.

Si aucun rectangle plausible n'est trouvé, la fonction retourne l'image complète inchangée (charge alors au découpage en lignes de s'en sortir).

split_lcd_lines(screen_crop, n_lines=3)

Découpe le crop d'écran en n_lines bandes horizontales, une par valeur affichée.

Méthode principale : projection horizontale des pixels de texte (binarisation Otsu + CLAHE, puis comptage de pixels "actifs" par ligne) pour repérer automatiquement où sont les bandes de texte et où sont les espaces vides entre elles.

Repli : si la projection ne trouve pas exactement n_lines bandes (image bruitée, reflet, contraste insuffisant), découpage en bandes de hauteur égale. Ce repli est peu précis — voir docs/LIMITATIONS.md, c'est la cause principale du plafond de précision actuel du modèle (86% du jeu d'entraînement est passé par ce repli plutôt que par la détection précise).

Pourquoi n_lines=3 par défaut et pas 2 : la majorité des écrans du jeu d'annotation affichent trois valeurs (prix total, volume, prix du litre). Un défaut à 2 aurait systématiquement tronqué la troisième ligne — piège découvert en inspectant src/fine_tuned_inference.py (l'ancienne version, dans le prototype racine, avait ce défaut à 2).

FIELD_NAMES = ["prix", "volume", "prix_litre"]

Associe chaque ligne découpée (dans l'ordre où elle apparaît, de haut en bas) à un nom de champ métier. Cet ordre correspond à la convention observée sur les pompes photographiées : "Prix" en haut = montant total payé (pas le prix unitaire, malgré le nom), "Volume" au milieu = litres, "Prix Unitaire"/"Prix du litre" en bas = prix par litre. Voir docs/POSTPROCESS_RULES.md pour pourquoi cette distinction a causé un bug réel (confusion montant/prix unitaire).