TNI+VO · Exercice de Programmation

EP06_08 — ⚫ Segmentation et Décodage Réel de QRCode avec OpenCV

6.14.8 EP06_08 ⚫ Segmentation et Décodage Réel de QRCode avec OpenCV

Dans les exercices précédents, les grandeurs intermédiaires du pipeline de traitement d’images — telles que les aires, les périmètres, les variances et les déplacements — étaient fournies directement ou calculées à partir de matrices numériques, sans nécessiter de bibliothèques spécialisées de Vision par Ordinateur. Dans cet exercice de clôture du chapitre, cette restriction est levée de manière intentionnelle : la bibliothèque OpenCV (cv2) sera utilisée pour localiser et décoder un QRCode réel présent dans une scène.

La proposition reproduit un flux simplifié de systèmes employés en inspection visuelle, en automatisation industrielle et en lecture automatique de documents. Pour maintenir l’entrée de données accessible au contexte éducatif, le chargement de l’image sera intégré à la bibliothèque didactique morph, via la fonction mm.readImg.

La scène est fournie au format PGM ASCII (P2) et contient un unique QRCode valide, ainsi que divers objets distracteurs, tels que des rectangles, des zones de bruit texturé et des blocs isolés. La segmentation basée uniquement sur des propriétés géométriques — comme l’aire et la forme approximativement carrée — est nécessaire pour réduire l’espace de recherche, mais ne suffit pas à identifier le code correct. La confirmation finale sera réalisée exclusivement par la tentative de décodage avec cv2.QRCodeDetector, procédure compatible avec les applications réelles de reconnaissance automatique.

6.14.8.1 📋 Directives d’Implémentation

  1. Lecture des dimensions et des paramètres

    Lire, dans cet ordre, via l’entrée standard :

    • une ligne contenant le nombre de lignes \(L\) ;
    • une ligne contenant le nombre de colonnes \(C\) ;
    • une ligne contenant les quatre paramètres de l’algorithme séparés par des espaces :
      • le seuil de binarisation \(T\) (entier) ;
      • l’aire minimale \(A_{\text{min}}\) (entier) ;
      • la tolérance d’aspect \(\text{tol}\) (réel) ;
      • la marge \(M\) (entier, en pixels).
  2. Chargement de l’image

    Utiliser la fonction didactique f = mm.readImg(L, C) pour lire les \(L \times C\) valeurs de l’image en niveaux de gris, obtenant ainsi un array NumPy de type uint8.

  3. Binarisation

    Appliquer une binarisation inversée en utilisant le seuil \(T\). Tout pixel de l’image originale avec une intensité strictement supérieure à \(T\) doit être converti à 255, tandis que les autres doivent prendre la valeur 0.

  4. Détection des contours

    Extraire les composants connectés externes en utilisant cv2.findContours(...) avec les paramètres :

    • cv2.RETR_EXTERNAL ;
    • cv2.CHAIN_APPROX_SIMPLE.
  5. Filtrage géométrique

    Pour chaque contour trouvé :

    • calculer le rectangle englobant (x, y, w, h) à l’aide de cv2.boundingRect ;

    • ne conserver que les candidats satisfaisant simultanément :

      Aire minimale

      \[ w \times h > A_{\text{min}} \]

      Rapport d’aspect

      \[ \left|\frac{w}{h}-1\right| \le \text{tol} \]

  6. Tri des candidats

    Trier les candidats par l’aire du rectangle englobant

    \[ w \times h \]

    en ordre décroissant.

    En cas d’égalité, préserver l’ordre originalement retourné par cv2.findContours.

  7. Vérification par décodage

    Pour chaque candidat, en suivant l’ordre établi :

    • étendre le rectangle de \(M\) pixels dans les quatre directions ;
    • limiter les indices pour rester dans l’image ;
    • extraire le recadrage directement depuis l’image originale f ;
    • appliquer cv2.QRCodeDetector().detectAndDecode(...) sur ce recadrage.
  8. Critère d’arrêt

    Interrompre immédiatement le traitement lorsque le premier candidat produit une chaîne décodée non vide.

  9. Cas non trouvé

    Si aucun candidat n’est décodé avec succès, imprimer exactement : QRCODE_NAO_ENCONTRADO

  10. Sortie (cas trouvé)

    Imprimer deux lignes.

    Première ligne : linha coluna altura largura en utilisant le rectangle englobant original, avant l’expansion par la marge \(M\).

    Deuxième ligne : texto_decodificado

6.14.8.2 📌 Contraintes Computationnelles

  • Utiliser les fonctions d’OpenCV pour réaliser la binarisation, la détection des contours, le calcul du rectangle englobant et le décodage du QRCode.
  • Le filtrage géométrique doit obligatoirement avoir lieu avant l’étape de décodage.
  • Utiliser exclusivement le seuil fixe \(T\) fourni en entrée. Il n’est pas permis d’utiliser des méthodes automatiques de seuillage, comme Otsu ou le seuillage adaptatif.
  • Garantir que les recadrages envoyés au décodeur restent dans les limites de l’image.

6.14.8.3 🧠 Fondement Théorique

Étape Rôle dans le pipeline Conséquence si omise
Filtrage géométrique Réduit l’espace de recherche en sélectionnant uniquement les régions compatibles avec la géométrie attendue d’un QRCode. Le décodeur traiterait tous les contours, y compris les bruits et les objets distracteurs.
Décodage Confirme sémantiquement si le candidat contient un QRCode valide. Des objets géométriquement similaires pourraient être classifiés incorrectement comme QRCode.
Marge \(M\) Préserve la zone de silence autour du code, facilitant sa détection. L’absence de cette marge peut empêcher l’alignement et la lecture correcte du code.

Cet exercice intègre les concepts étudiés tout au long du chapitre dans un pipeline unique de Vision par Ordinateur. La segmentation réduit l’ensemble des régions candidates grâce à des caractéristiques géométriques, tandis que l’étape de décodage valide le contenu de la région en utilisant un algorithme spécialisé de reconnaissance.

6.14.8.4 📦 Spécification d’Entrée et de Sortie (VPL)

Structure d’Entrée

L
C
T A_min tol M
[matrice de l'image]

Structure de Sortie (Succès)

linha coluna altura largura
texto_decodificado

Structure de Sortie (Échec)

QRCODE_NAO_ENCONTRADO

6.14.8.5 📌 Fichiers de Référence (.pgm)

À des fins de validation, de débogage local et d’analyse de matrices réelles de pixels, les fichiers d’image générés au format ASCII P2 sont disponibles dans le répertoire du projet. Vous pouvez les utiliser pour tester la conformité de votre code en les décodant avec votre téléphone (sauvegardez localement les *.pgm pour les visualiser) :

  • 📥 Cas 1 : Schéma Normal – Contient un unique code parfaitement centré avec des distracteurs géométriques simples en périphérie.
  • 📥 Cas 2 : Scénario Complexe – Présente une densité de bruit texturé plus élevée et de multiples candidats distracteurs qui testent les limites du filtrage par aspect.
  • 📥 Cas 3 : Message Étendu – Contient un QRCode structuré à partir d’une chaîne de caractères plus longue, générant une densité de modules internes plus élevée.
  • 📥 Cas 4 : Géométrie Compacte – Évalue le comportement du pipeline dans des conditions optimisées de contraste et de positionnement limite.
  • 📥 Cas 5 : Scénario d’Exclusion – Image composée purement d’éléments distracteurs de grande aire, conçue pour valider le comportement de défaillance contrôlée du programme.
📋 Simulateur EP06_08 : Segmentation et Décodage de QRCode Filtre géométrique→Critère d'arrêt sémantique

Ajustez interactivement les paramètres d'entrée de l'algorithme (A_min et tol) pour vérifier quels composants sont filtrés géométriquement et comment le critère d'arrêt par analyse sémantique interrompt le balayage de la file.

250
0.22
Visualisation de la Scène (Matrice f)
Composants Connectés dans la File
Figure 6.28: Simulateur EP06_08 : Segmentation géométrique + Vérification par décodage de QRCode
%%writefile EP06_08.py
# Code Python
Overwriting EP06_08.py
TestSuite("EP06_08.py").run()
✔️ EP06_08.cases existe déjà dans casos/
📋 5 cas chargé(s) depuis casos/EP06_08.cases

🔍 Test de Python : EP06_08.py
⚠️ EP06_08.py : fichier vide (moins de 3 lignes). Tests ignorés.