Analyse d'une carte d'identité

Partager cet article

Introduction

Dans cet article nous allons voir comment nous allons pouvoir récupérer des informations (photo, et autres informations) à partir d’une carte d’identité scannée. L’idée est de mettre en pratique les articles précédents sur la reconnaissance faciale et la reconnaissance de texte (avec tesseract).

Voici donc la carte d’identité que nous allons analyser :

Inutile de préciser que cette carte d’identité est fictive 🙂 néanmoins nous allons retrouver les mêmes difficultés que sur une vraie. Nous utiliserons comme language Python et les librairies OpenCV et Tesseract (pour l’OCR). Les premières lignes ne doivent pas générer d’erreur sans quoi vous devrez importer les librairies (n’oubliez pas numpy, Image, etc.) via pip par exemple.

try:
    from PIL import Image
except ImportError:
    import Image
import pytesseract
from pytesseract import Output
import cv2
import numpy as np
from matplotlib import pyplot as plt

Découpage de la photo

Comme nous l’avons vu dans l’article sur la reconnaissance faciale, nous allons tout d’abord reconnaître et découper la photo d’identité en utilisant la reconnaissance faciale d’OpenCV.

Note : Utilisez le modèle haarcascade_frontalface_default.xml pour ce type de détection.

imagePath = r'ci.jpg'
dirCascadeFiles = r'../opencv/haarcascades_cuda/'
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cascadefile = dirCascadeFiles + "haarcascade_frontalface_default.xml"
classCascade = cv2.CascadeClassifier(cascadefile)
faces = classCascade.detectMultiScale(
    gray,
    scaleFactor=1.1,
    minNeighbors=5,
    minSize=(30, 30),
    flags = cv2.CASCADE_SCALE_IMAGE
)
print("Il y a {0} visage(s).".format(len(faces)))
# Coordonnées des rectangles des visages détectés (x, y, w, h)
for (x, y, w, h) in faces:
    cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)

plt.imshow(image)

Aucune difficultés à signaler, OpenCV détecte très bien le visage et nous pouvons donc l’extraire simplement en faisant une opération de slicing avec numpy :

f = faces[0]
plt.imshow(image[f[1]:f[1]+f[3], f[0]:f[0]+f[2]])

Récupération des autres informations

L’objectif est maintenant de récupérer les informations textuelles de la carte d’identité. Essayons tesseract directement sur l’image source :

print(pytesseract.image_to_string(image))
REPUBLIQUE FRANCAISE
‘CARTE NATIONALE DIDENTITE Ne 7700773MIO777__Nationaité Francaise
MS Nom! JACKSON

Prtnomiy: MICHAEL, JOSEPH

Sexe: H Nef le: 29.08, 1958

IDFRAJACKSON<<<<<<<<

Nous récupérons tant bien que mal les différentes informations. Néanmoins on trouve beaucoup d'erreurs d'interpretation (Prtnomiy à la place de Prénom(s), etc.) qui risquent de rendre difficile une récupération intelligente des différents éléments. Cela est peut être dû au fond complexe de la carte d'identité (filigrammes et autres) qui rendent la tâche difficile à tesseract. Essayons re retoucher l'image (en jouant sur les seuils, niveaux de gris, etc.):

# Niveaux de gris
def grayscale(image):
    return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Réduction de bruits
def remove_noise(image):
    return cv2.medianBlur(image,1)
# Seuillage
def thresholding(image):
    return cv2.threshold(image, 200, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

finalimage = remove_noise(thresholding(grayscale(image)))
plt.imshow(finalimage)
texteCI = pytesseract.image_to_string(finalimage)
print(texteCI)

Le résultat est guère meilleur en réalité, nous allons donc tenter une approche différente.

Approche ciblée

La qualité de informations étant difficile à interpréter, une bonne approche consiste sans doute à cibler les informations que l'on va envoyer à tesseract. Ainsi on va découper l'image en plusieurs morceaux. Chaque morceaux devra contenir les informations à récupérer. La carte d'identité est plutôt un bon exemple car les informations sont toujours placées à peu près au même endroit.

Nous allons commencer par récupérer les coordonnées du cadre contenant le nom. Nous avons besoin du point en haut à gauche et de celui en bas à droite. le plus simple est d'ouvrir l'image dans un outil de dessin (comme pinta sur ubuntu) et de regarder les coordonnées quand on passe la souris (cf. cadre en haut à droite en rouge) :

Une fois les deux points récupérés, il suffit de découper l'image via une opération de slicing avec numpy. Vérifions que le cadre d'identitication est bien le bon :

image = cv2.imread(imagePath)
x = 151
y = 49
w = 300
h = 69
plt.imshow(cv2.rectangle(image, (x, y), (w, h), (0, 255, 0), 2))

Maintenant, nous pouvons extraire l'image :

region_Nom = image[y:h, x:w]
plt.imshow(region_Nom)

Utilisons tesseract sur cette image découpée :

region_Nom = remove_noise(thresholding(grayscale(region_Nom)))
NomCI = pytesseract.image_to_string(region_Nom)
print(NomCI)
JACKSON

Suite ?

Il suffit maintenant d'appliquer la même méthode sur les autres zones à récupérer. Un petit bémol tout de même, nous avons découpé l'image selon des coordonnées fixes. Le soucis est qu'il peut y avoir des décalage lors des scan des différentes cartes d'identités: ces coordonnées risquent donc de ne par être bonnes d'une image à une autre. La technique consiste donc à repérer un élément fixe sur l'image (comme par exemple le R de République Française en haut) et d'en faire le point de référence pour les coordonnées de répérage.

Comme d'habitude vous trouverez les codes de cet article sur GitHub.

Partager cet article

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.

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