[OCR] Détection et extraction de texte d'une image à l'aide de Tesseract OCR et OpenCV
On installe Tesseract OCR :
sudo apt install tesseract-ocr
sudo apt install libtesseract-dev
On installe les bibliothèques Python OpenCV et Python Tesseract :
pip install opencv-python pytesseract
# On importe les bibliothèques Python
import numpy as np
import cv2
import pytesseract
# On charge l'image
img = cv2.imread("image.jpg")
# On convertit l'image en niveaux de gris
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# On applique un seuillage automatique à l'image en niveaux de gris afin de séparer le texte du fond, on récupère respectivement la valeur optimale du seuil et l'image.
ret, thresh = cv2.threshold(gray_img, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)
# On analyse la résolution et la densité de texte de l'image afin de déterminer la taille du noyau
# - On récupère les dimensions de l'image
img_height, img_width = img.shape[:2]
# - On détecte le nombre total d'objets trouvés dans l'image (arrière-plan compris), à quel objet appartient chaque pixel, les dimensions et positions de chaque objet, et les centres de chaque objet
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh)
# - On filtre les objets trop petits en excluant l'arrière-plan (qui est toujours à l'index 0)
characters_stats = [stat for stat in stats[1:] if stat[4] > 10]
if not characters_stats:
return None
# - On calcule la largeur et la hauteur moyenne des caractères
mean_character_width = np.mean([stat[2] for stat in characters_stats])
mean_character_height = np.mean([stat[3] for stat in characters_stats])
# - On estime l'espacement moyen entre les caractères
mean_area = np.mean([stat[4] for stat in characters_stats])
# - On calcule la densité de texte
density = len(characters_stats) * mean_area / (img_height * img_width)
# - On ajuste la taille du noyau en fonction de la taille moyenne des caractères et de la densité de texte
kernel_width = int(mean_character_width * 3.5 * (1 - 0.5 * density))
kernel_height = int(mean_character_height * 2.5 * (1 - 0.5 * density))
# - On assure une taille minimale du noyau et un nombre impair (meilleur pour les opérations morphologiques)
kernel_width = max(3, kernel_width if kernel_width % 2 == 1 else kernel_width + 1)
kernel_height = max(3, kernel_height if kernel_height % 2 == 1 else kernel_height + 1)
# - On crée un noyau rectangulaire qui sera utilisé pour la dilatation de l'image seuillée
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_width, kernel_height))
# On dilate les zones blanches de l'image seuillée afin de grouper les caractères par zone de texte
dilated_img = cv2.dilate(thresh, kernel, iterations = 1)
# On détermine les countours des zones de texte et leurs hiérarchies (relations parent-enfant)
contours, hierarchy = cv2.findContours(dilated_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# On parcourt les zones de texte selon leurs contours
for contour in contours:
# On récupère les coordonnées du contour
x, y, w, h = cv2.boundingRect(contour)
# On récupère la zone de l'image correspondant au contour
cropped = img[y:y + h, x:x + w]
# On applique la reconnaissance optique de caractères (OCR) à la zone de texte
text = pytesseract.image_to_string(cropped)
# On affiche le texte
print(text)
Dernière mise à jour