Dans ce tutoriel, on vous guide pas à pas à :
- Comprendre le principe d’un QR Code
- Créer des QR Codes avec le module qrcode
- Lire des QR Codes depuis une image avec OpenCV et avec pyzbar
- Lire des QR Codes en temps réel via une webcam
1. À propos du QR Code
1.1 Définition
Un QR Code (Quick Response) est un code-barres 2D capable de stocker des données (texte, URL, identifiants, etc.) sous forme de modules (petits carrés noirs et blancs). Il est conçu pour être rapide à scanner et robuste face à certaines dégradations (grâce à la correction d’erreur).
1.2 Pourquoi Python pour les QR Codes ?
Python propose un écosystème riche : le module qrcode pour générer facilement des images, OpenCV pour la vision par ordinateur et l’analyse d’images, et pyzbar pour décoder efficacement des QR Codes (et d’autres codes-barres).
2. Pré-requis : installation et préparation
2.1 Installation des bibliothèques
Le code ci-dessous installe les modules nécessaires. On installe opencv-python (vision), qrcode (génération) et pyzbar (décodage). Le module Pillow est souvent utilisé en interne par qrcode pour manipuler les images.
Voici les commandes d'installation (à exécuter dans un terminal ou dans un notebook avec un "!" devant). Si vous exécutez ce code dans un fichier .py classique, utilisez plutôt le terminal.
|
1 2 3 4 |
pip install opencv-python pip install qrcode[pil] pip install pyzbar pip install pillow |
2.2 Organisation conseillée du projet
Une structure simple permet de retrouver rapidement les fichiers. Vous pouvez créer un dossier qr_tutorial, puis y mettre un sous-dossier images pour stocker les QR Codes générés et des images à tester.
|
1 2 3 |
qr_tutorial/ main.py images/... |
3. Créer un QR Code avec le module qrcode
3.1 Génération simple (texte ou URL)
Dans votre fichier main.py, ajoutez le code suivant qui crée un QR Code contenant une URL (ou du texte). On choisit un nom de fichier de sortie. Le QR code est obtenu sous forme d'image PNG. Cette méthode est idéale pour les cas simples.
|
1 2 3 4 5 6 7 8 9 10 11 12 |
import qrcode data = "https://example.com/mon-qr-code" output_path = "images/qr_simple.png" img = qrcode.make(data) img.save(output_path) print("QR Code généré :", output_path) # Output : # QR Code généré : images/qr_simple.png |

3.2 Génération avancée (taille, bordure, correction d’erreur)
Ici, on contrôle précisément les paramètres : la correction d’erreur (plus robuste mais plus “dense”), la taille des modules (box_size) et la bordure (border). C’est utile si vous devez imprimer le QR Code ou l’afficher dans une interface.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import qrcode from qrcode.constants import ERROR_CORRECT_M data = "Texte important : ID=ABC123; role=admin; exp=2026-12-31" output_path = "images/qr_avance.png" qr = qrcode.QRCode( version=2, # taille “logique” du QR (plus grand => plus de données possibles) error_correction=ERROR_CORRECT_M, # niveau de correction d'erreur : L, M, Q, H box_size=10, # taille d'un module (pixel) border=4 # bordure blanche (modules) ) qr.add_data(data) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") img.save(output_path) print("QR Code avancé généré :", output_path) # Output : # QR Code avancé généré : images/qr_avance.png |
4. Lire un QR Code depuis une image avec OpenCV
4.1 Décodage avec QRCodeDetector
OpenCV propose QRCodeDetector. Il détecte et décode un QR Code depuis une image. C’est une solution simple si vous voulez rester uniquement dans l’écosystème OpenCV.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import cv2 image_path = "images/qr_simple.png" img = cv2.imread(image_path) detector = cv2.QRCodeDetector() data, points, _ = detector.detectAndDecode(img) if points is None or data == "": print("Aucun QR Code détecté.") else: print("QR Code détecté !") print("Contenu :", data) # Output (exemple) : # QR Code détecté ! # Contenu : https://example.com/mon-qr-code |
4.2 Dessiner le contour du QR Code détecté
Lorsque points est disponible, OpenCV fournit les sommets du QR Code. On peut dessiner un contour pour visualiser la zone scannée, ce qui est très utile en debug ou en application temps réel.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import cv2 import numpy as np image_path = "images/qr_simple.png" img = cv2.imread(image_path) detector = cv2.QRCodeDetector() data, points, _ = detector.detectAndDecode(img) if points is None or data == "": print("Aucun QR Code détecté.") else: pts = points.astype(int).reshape(-1, 2) for i in range(len(pts)): p1 = tuple(pts[i]) p2 = tuple(pts[(i + 1) % len(pts)]) cv2.line(img, p1, p2, (0, 255, 0), 2) print("Contenu :", data) out = "images/qr_simple_avec_contour.png" cv2.imwrite(out, img) print("Image annotée sauvegardée :", out) # Output (exemple) : # Contenu : https://example.com/mon-qr-code # Image annotée sauvegardée : images/qr_simple_avec_contour.png |
5. Lire un QR Code avec pyzbar
5.1 Décodage robuste (QR + autres codes-barres)
pyzbar est pratique car il peut décoder non seulement des QR Codes, mais aussi d’autres types de codes-barres. Il retourne une liste d’objets détectés : on peut afficher le contenu, le type, et même la zone détectée.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import cv2 from pyzbar.pyzbar import decode image_path = "images/qr_avance.png" img = cv2.imread(image_path) decoded = decode(img) if not decoded: print("Aucun code détecté.") else: for obj in decoded: content = obj.data.decode("utf-8", errors="replace") print("Type :", obj.type) print("Contenu :", content) # Output (exemple) : # Type : QRCODE # Contenu : Texte important : ID=ABC123; role=admin; exp=2026-12-31 |
5.2 Dessiner la boîte autour du QR Code
Chaque objet renvoie un rectangle (rect) et parfois un polygone. On peut dessiner une boîte pour montrer ce qui est détecté, puis sauvegarder l’image annotée.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import cv2 from pyzbar.pyzbar import decode image_path = "images/qr_avance.png" img = cv2.imread(image_path) decoded = decode(img) if not decoded: print("Aucun code détecté.") else: for obj in decoded: x, y, w, h = obj.rect cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) content = obj.data.decode("utf-8", errors="replace") print("Contenu :", content) out = "images/qr_avance_avec_boite.png" cv2.imwrite(out, img) print("Image annotée sauvegardée :", out) # Output (exemple) : # Contenu : Texte important : ID=ABC123; role=admin; exp=2026-12-31 # Image annotée sauvegardée : images/qr_avance_avec_boite.png |
6. Lecture en temps réel avec une webcam (OpenCV)
6.1 Scanner en direct avec QRCodeDetector
Ce code ouvre la webcam, détecte et décode le QR Code à chaque frame. Dès qu’un QR Code est détecté, son contenu s’affiche dans la console, et un contour est dessiné sur l’image. Pour quitter, on appuie sur la touche q.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import cv2 import numpy as np cap = cv2.VideoCapture(0) detector = cv2.QRCodeDetector() if not cap.isOpened(): print("Impossible d'ouvrir la webcam.") else: print("Webcam ouverte. Appuyez sur 'q' pour quitter.") while True: ret, frame = cap.read() if not ret: print("Erreur de lecture de la webcam.") break data, points, _ = detector.detectAndDecode(frame) if points is not None and data: pts = points.astype(int).reshape(-1, 2) for i in range(len(pts)): p1 = tuple(pts[i]) p2 = tuple(pts[(i + 1) % len(pts)]) cv2.line(frame, p1, p2, (0, 255, 0), 2) cv2.putText(frame, "DETECTE", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2) print("QR :", data) cv2.imshow("Scanner QR (OpenCV)", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() # Output (exemple) : # Webcam ouverte. Appuyez sur 'q' pour quitter. # QR : https://example.com/mon-qr-code # QR : Texte important : ID=ABC123; role=admin; exp=2026-12-31 |
6.2 Variante temps réel avec pyzbar
Dans certains cas, pyzbar peut être plus "souple" (selon la qualité de l’image, l’éclairage, etc.). Le code suivant détecte tous les codes présents, affiche le contenu, et trace un rectangle autour.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import cv2 from pyzbar.pyzbar import decode cap = cv2.VideoCapture(0) if not cap.isOpened(): print("Impossible d'ouvrir la webcam.") else: print("Webcam ouverte. Appuyez sur 'q' pour quitter.") while True: ret, frame = cap.read() if not ret: print("Erreur de lecture de la webcam.") break decoded = decode(frame) for obj in decoded: x, y, w, h = obj.rect cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) content = obj.data.decode("utf-8", errors="replace") cv2.putText(frame, obj.type, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0,255,0), 2) print(obj.type, ":", content) cv2.imshow("Scanner QR (pyzbar)", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() # Output (exemple) : # Webcam ouverte. Appuyez sur 'q' pour quitter. # QRCODE : https://example.com/mon-qr-code |
7. Mini-projet : générer un QR Code puis vérifier sa lecture automatiquement
7.1 Objectif
Dans une vraie application, on veut souvent :
- générer un QR Code à partir d’une donnée (par exemple un identifiant)
- lire l’image produite
- vérifier que le contenu lu correspond exactement à la donnée d’origine
7.2 Script complet (génération + lecture + validation)
Le code ci-dessous crée un QR Code, puis tente de le relire avec OpenCV. Ensuite, il compare la valeur lue à la valeur attendue et affiche un message de succès ou d’échec. Ce genre de test est utile pour l’automatisation et la validation de vos QR Codes avant diffusion.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import cv2 import qrcode # 1) Donnée à encoder expected = "USER:98765|PLAN:PREMIUM|EXP:2026-12-31" # 2) Génération du QR Code out_path = "images/qr_test_validation.png" img = qrcode.make(expected) img.save(out_path) # 3) Lecture avec OpenCV read_img = cv2.imread(out_path) detector = cv2.QRCodeDetector() decoded, points, _ = detector.detectAndDecode(read_img) # 4) Validation print("Attendu :", expected) print("Lu :", decoded) if decoded == expected: print("OK : le contenu est valide.") else: print("ERREUR : le contenu ne correspond pas !") # Output (exemple) : # Attendu : USER:98765|PLAN:PREMIUM|EXP:2026-12-31 # Lu : USER:98765|PLAN:PREMIUM|EXP:2026-12-31 # OK : le contenu est valide. |
7.3 Conseils pratiques (qualité, sécurité, erreurs fréquentes)
- Éclairage : en webcam, un mauvais éclairage est la cause n°1 d’échec de lecture.
- Taille : un QR Code trop petit à l’écran ou trop loin de la caméra est difficile à détecter.
- Contraste : gardez un fond clair et un QR sombre (ou l’inverse) avec une bordure nette.
- Données sensibles : évitez de mettre des secrets en clair. Préférez un identifiant + une vérification côté serveur.
- Validation : vérifiez toujours le format (ex : présence de champs attendus) avant d’agir sur le contenu scanné.
Younes Derfoufi CRMEF OUJDA



