Dans l’article d’aujourd’hui, nous allons nous intéresser à la lecture des plaques d’immatriculation des voitures. Pour ce faire, nous allons nous appuyer sur l’article Automatic License Plate Recognition using Python and OpenCV de K.M. Sajjad. Cette méthode s’appuie sur l’utilisation de la bibliothèque de reconnaissance de caractère Tesseract que nous avons déjà utilisé.

Afin de pouvoir lire une plaque d’immatriculation, plusieurs opérations sont réalisées. Dans un premier temps, des prétraitements sont appliqués afin de faciliter les analyses ultérieures de l’image. Afin de localiser la plaque, l’image est seuillée afin de mettre en avant les zones blanches de l’image pouvant correspondre à une plaque d’immatriculation. Enfin, la reconnaissance de caractère est appliquée afin d’obtenir l’immatriculation de la voiture.

Maintenant que notre plan d’action est défini, nous pouvons passer à la partie Python avec OpenCV.

Prétraitements de l’image

Avant de pouvoir commencer, nous importons les bibliothèques nécessaires, à savoir OpenCV, Numpy et Tesseract :

import cv2
import numpy as np
import pytesseract

L’étape inévitable qui suit est de charger l’image que nous souhaitons analyser:

img = cv2.imread('image.jpg')

Nous pouvons maintenant passer aux prétraitements. Deux opérations seront à réaliser : convertir l’image RGB en niveau de gris, puis effectuer un seuillage afin de mettre en avant les zones claires, correspondant potentiellement aux plaques d’immatriculation.

img_gris = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
seuil, img_seuil = cv2.threshold(img_gris, 80, 255, cv2.THRESH_BINARY)

Nous pouvons maintenant passer à l’étape suivante, à savoir, extraire les plaques d’immatriculation de l’image.

Extraction des plaques d’immatriculation

Comme l’étape précédente nous à permis de mettre en avant les zones claires, nous allons commencer par utiliser une extraction de contours afin d’extraire de l’image les coordonnées des zones blanches :

contours, _ = cv2.findContours(img_seuil, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

Du fait qu’il est fort probable que de nombreuses zones claires soient présentes dans l’image, il est nécessaire de devoir écarter celles ne correspondant pas aux plaques d’immatriculation. Pour ce faire, nous pouvons effectuer un seuillage dimensionnel :

kernel = np.ones((5, 5), np.uint8)
for cnt in contours:
	(x, y, w, h) = cv2.boundingRect(cnt)
	if (w >= 3 * h) & (w < 6 * h) & (w * h > 5000) & (w * h < 50000):
		img_crop = img_seuil[y:y + h, x:x + w]
		img_resize = cv2.resize(img_crop, (0, 0), fx=5, fy=5)
		img_corrige = cv2.morphologyEx(img_resize, cv2.MORPH_OPEN, kernel)

Pour chaque contour (l. 13), nous calculons alors le rectangle encadrant (l.14), afin de pouvoir effectuer le seuillage dimensionnel à la ligne 15.

Pour les dimensions, nous cherchons un rectangle, dont la largeur est entre 3 et 5 fois plus grande que la hauteur. En effet, les plaques d’immatriculation européenne ont, en générale, une taille de 520mm par 110mm soit un ratio d’environ 4,7 entre la largeur et la hauteur.

Nous ajoutons à cela un seuil sur l’aire de la plaque afin de ne conserver uniquement les zones blanches d’une taille proche de celles d’une plaque d’immatriculation. Ces valeurs dépendent de la taille de l’image et il est important de les ajuster en fonction des conditions d’acquisitions.

Lorsque l’on trouve une zone pouvant correspondre à une plaque, nous extrayons cette zone de l’image seuillée (l.16), puis augmentons la taille de l’image extraite (l. 17) . Cette opération est réalisée afin de faciliter la détection de caractère par tesseract.

Enfin, avant de passer à la lecture de la plaque, nous appliquons une fermeture (l.18), grâce au kernel défini à la ligne 12, afin d’améliorer l’image finale.

Exemples de zones extraites pour la lecture de plaques d'immatriculation
Exemples de zones extraites

Lecture de l’immatriculation

Nous pouvons donc maintenant passer à l’étape qui nous intéresse le plus : la lecture de l’immatriculation !

		txt = pytesseract.image_to_string(img_corrige,config='--psm 7')
		if (txt != ''):
			cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 5)
			cv2.putText(img, txt, (x, y - 15),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 3)
		else:
			cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 5)
cv2.imshow('image', img)
cv2.waitKey(0)

Pour ce faire, nous appelons la fonction image_to_string() de la bibliothèque tesseract, que nous avions déjà utilisé dans cet article. Du fait que les caractères dans les plaques d’immatriculation soient alignés, nous spécifions en configuration l’argument « –psm 7 » qui permet de considérer que l’image ne contient qu’une seule ligne de texte. Pour plus de détails sur les options disponibles, je vous invite à consulter le manuel de tesseract.

Dans le cas où un texte est trouvé (l. 21), nous affichons un rectangle de couleur vert autour de la plaque (l. 22) et nous ajoutons le texte retourné sur l’image (l. 23). Dans le cas contraire, nous affichons un rectangle rouge (l. 25).

Enfin, nous pouvons afficher l’image résultante ligne 26-27.

Nous arrivons, pour chaque image, à retrouver les plaques d’immatriculation. De plus, le nombre de zones autres que des plaques et relativement faible. Cependant, comme nous pouvons le voir, le résultat n’est pas parfait. Afin d’améliorer les résultats, il serait possible de mettre en place un certain nombre de corrections.

Sur de nombreuses images, un caractère est ajouté avant ceux de la plaque. La détection de la partie bleue de la plaque permettrait de ne pas la prendre en compte lors de la lecture de la plaque et ainsi éviter de prendre en compte un caractère supplémentaire.

Si nous nous intéressons à des plaques d’immatriculation d’un seul pays, alors nous pouvons utiliser les normes en vigueurs. Par exemple, en France, les plaques ont une numérotation de la forme AA 000 AA.


18 commentaires

Boka · 29 août 2019 à 12 h 33 min

SVP pouvez-vous mettre le fichier python à télécharger. On en a besoin. Merci pour tout.

    Florent · 30 août 2019 à 14 h 13 min

    Bonjour,
    Le code entier se trouve dans l’article.

Boka · 30 août 2019 à 13 h 20 min

SVP comment éliminer la partie bleu e lors de la détection des caractères ?

Ange · 6 novembre 2019 à 9 h 33 min

svp comment afficher la plaque d’immatriculation en haut n’est pas dans le casre la

Nan · 13 décembre 2019 à 11 h 09 min

Bonjour!!! je ne trouve pas l’artice qui contient le code!!aidez moi svp

    Florent · 13 décembre 2019 à 11 h 20 min

    J’ai peur de ne pas comprendre votre question. Le code se trouve dans cet article !

Alicia · 17 janvier 2020 à 8 h 41 min

Bonjour,

Le code ne fonctionne pas sur des plaques françaises, normal? Dois-je rajouter quelques chose ou je peux utiliser votre code tel quel?

    Florent · 20 mars 2020 à 8 h 32 min

    Bonjour,
    Il n’y a pas de raison que cela ne fonctionne pas avec les plaques françaises : les plaques sont sur un format européen.
    Le problème doit provenir de la localisation de la plaque. Il est nécessaire d’adapter le seuillage aux conditions d’acquisition des images.

Wilkin Andre · 23 février 2020 à 19 h 53 min

j ai lancer le code sur mon portable qui est une machine tres tres legere et il m’affiche l’image que j’ai renseigner ds le code ( une de tes photo de voiture dont j’ai effacer le resultat en vert ) mais ca ne donne rien dois-je attendre plus longtemps (a cause de ma becanne) ou faut il faire qqchose d’autre ??
merci

    Florent · 20 mars 2020 à 8 h 25 min

    Bonjour, le problème vient surement du fait que les images sur le blog sont compressé afin d’amélioré la stabilité sur le site. Tu peux télécharger les photos originales en cliquant sur le lien sous les photos.

Guillaume de Rybel · 7 mars 2020 à 15 h 33 min

Merci beaucoup pour ton code !
J’ai essayé de l’optimisé au maximum de mon côté. J’ai deux choses qui pourront aider dans la précision (du moins pour les plaques françaises):
-if(len(txt)>3) & (len(txt)<12) à la place de if(txt!=""), on cherche une plaque avec qui a entre 3 et 12 caractères, pour éviter les zones 'parasites'.
-Faire une sorte de 'blacklist' pour tesseract : txt = txt.replace("/", ""), ici pour un slash, on crée un vide. Cela peut être utile, notamment si l'on veut utiliser le nom de la plaque comme nom de fichier (car certains caractères sont interdits).
Cependant, je ne connais pas bien numpy et je ne comprend pas l'interêt de l'utiliser, si tu pourrais m'expliquer plus en détail, je suis preneur 🙂

Cordialement,

Guillaume

    Florent · 20 mars 2020 à 8 h 50 min

    Bonjour,
    Merci pour tes précisions !

    Numpy est une bibliothèque scientifique dont le principal avantage est d’être très performante pour la manipulation de matrices multidimensionnelles. Son utilisation a, en effet, peu d’intérêt dans le code de cet article du fait que l’on utilise uniquement une matrice 5×5. Cependant elle révèle ses avantages au niveau de la manipulation et au traitement des images, voire à des groupes d’images. D’ailleurs, tu pourras remarquer que les images utilisées par OpenCV sont de type ‘numpy.ndarray’.

daniel komba · 12 avril 2020 à 5 h 35 min

bonjour chez le programme localise la plaque mais ne le lit pas

daniel komba · 13 avril 2020 à 23 h 30 min

salut j’ai essayé de complilé ce programme chez moi , je pas obtenu les resultats que je voulais puisque le programme localise la plaque mais il ne le lit pas je dois faire comment?

Loïc Kammerer · 24 avril 2020 à 15 h 28 min

Bonjour,

est-ce possible d’effectuer la même chose sous java? Si oui comment pourrait-on procéder pour tracer le rectangle aux bonnes dimensions de la plaque ?

Loïc

Clément · 15 juin 2020 à 14 h 51 min

Salut,
merci beaucoup pour ces articles toujours très intéressant!
Cependant j’ai un soucis avec cette application ci… à la ligne 15, je rentre jamais dans la boucle if, la condition est jamais satisfaite alors que je prend une des images que t’as pris et pour laquelle ça fonctionne.
T’as une idée de où ca pourrait venir ?

Emericdev · 29 juin 2020 à 11 h 37 min

Bonjour,
J’aimerais transformer cette ligne : img = cv2.imread(‘image.jpg’) pour que ça soit une vidéo en direct (webcam). Et un flux vidéo (fichier .avi ou .mp4). Est ce que vous savez comment faire ?

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.