Tu as déjà eu cette image sous les yeux : une capture d'écran pleine de texte, un document scanné, une photo de facture — et pas moyen de copier le texte qu'elle contient. C'est là qu'intervient l'OCR, la reconnaissance optique de caractères. Avec Python et Pytesseract, tu peux extraire le texte de n'importe quelle image en quelques lignes de code. Dans ce tutoriel, on va installer l'outil, extraire du texte d'une image simple, puis améliorer progressivement le résultat grâce au prétraitement — parce que c'est là que se joue la vraie différence entre un OCR bâclé et un OCR fiable.
C'est quoi l'OCR, et c'est quoi Tesseract ?
L'OCR (Optical Character Recognition) est la technologie qui transforme une image contenant du texte en texte exploitable : une chaîne de caractères que tu peux copier, rechercher, indexer. C'est ce qui permet à Google Books de numériser des millions de livres, à ton appli de scanner tes factures, ou à la poste de trier les enveloppes en lisant les codes postaux.
Tesseract est un moteur OCR libre et open source, développé à l'origine par Hewlett-Packard puis repris par Google. C'est aujourd'hui l'un des moteurs OCR les plus utilisés au monde, et il prend en charge plus de 100 langues. Pytesseract, lui, est un simple wrapper Python : il fait le pont entre ton script et l'exécutable Tesseract installé sur ta machine.
Point important à comprendre tout de suite : Pytesseract n'est qu'une interface. Le vrai travail est fait par Tesseract, qui est un programme externe. C'est pourquoi l'installation se fait en deux temps : le moteur Tesseract d'un côté, la bibliothèque Python de l'autre.
Tesseract fonctionne en plusieurs passes : il détecte d'abord la disposition du texte (lignes, colonnes, blocs), puis il découpe chaque ligne en mots et chaque mot en caractères, et enfin il reconnaît chaque caractère avant de réassembler le tout. Ce découpage explique pourquoi la qualité de l'image est déterminante : si la détection des lignes échoue, tout le reste s'effondre.
Prérequis : installer Tesseract puis Pytesseract
L'ordre compte. On installe d'abord le moteur OCR via le gestionnaire de paquets du système, puis le wrapper Python. Sur Linux (Debian/Ubuntu), le paquet tesseract-ocr-fra ajoute la prise en charge du français.
# Linux (Debian/Ubuntu) : le moteur + la langue française
sudo apt install tesseract-ocr tesseract-ocr-fra
pip install pytesseract pillowSur macOS, on passe par Homebrew, et sur Windows par l'installeur officiel (à télécharger sur GitHub). Dans tous les cas, vérifie ensuite que Tesseract est bien accessible :
# macOS
brew install tesseract tesseract-lang
pip install pytesseract pillow
# Vérifier l'installation et les langues disponibles
tesseract --version
tesseract --list-langsSi la commande tesseract n'est pas reconnue sur Windows, il faudra indiquer explicitement le chemin de l'exécutable à Pytesseract :
import pytesseract
# Windows : préciser le chemin de l'exécutable si besoin
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"Extraire le texte d'une image simple
On attaque avec le cas le plus simple : une image nette, bien éclairée, avec du texte noir sur fond blanc. Le script minimal tient en quatre lignes.
import pytesseract
from PIL import Image
# Ouvrir l'image puis extraire le texte
image = Image.open("document.png")
texte = pytesseract.image_to_string(image)
print(texte)image_to_string() fait tout le travail : elle envoie l'image à Tesseract et récupère le texte reconnu. Si ton image est déjà dans un fichier, tu peux même sauter Pillow et passer directement le chemin du fichier. Le résultat, pour une image propre, est souvent bluffant dès le premier essai.
Choisir la langue de reconnaissance
Par défaut, Tesseract reconnaît l'anglais. Pour du texte français, précise la langue avec le paramètre lang : les accents et les caractères spécifiques seront bien mieux gérés.
# Reconnaître du texte en français
texte = pytesseract.image_to_string(image, lang="fra")
# Combiner plusieurs langues (français + anglais)
texte = pytesseract.image_to_string(image, lang="fra+eng")La langue doit correspondre à un paquet installé (on a vu plus haut comment vérifier avec tesseract --list-langs). Pour le français, c'est fra. Si tu traites des documents multilingues, la syntaxe fra+eng permet de combiner les modèles.
Prétraiter l'image avec Pillow pour de meilleurs résultats
Le secret d'un bon OCR tient rarement au moteur : il tient au prétraitement de l'image. Une image floue, inclinée, ou à faible contraste donnera toujours un résultat médiocre. En nettoyant l'image avant de la passer à Tesseract, tu peux transformer un résultat illisible en texte quasi parfait.
Les transformations les plus efficaces sont le passage en niveaux de gris, l'augmentation du contraste, et la binarisation — c'est-à-dire la réduction de l'image à deux couleurs, noir et blanc, avec un seuil. Voici un pipeline classique :
from PIL import Image, ImageOps, ImageFilter
image = Image.open("document.png")
# 1. Niveaux de gris : supprime les couleurs parasites
image = ImageOps.grayscale(image)
# 2. Augmentation du contraste (auto-contraste)
image = ImageOps.autocontrast(image)
# 3. Binarisation : tout ce qui est sombre devient noir, le reste blanc
image = image.point(lambda x: 0 if x < 140 else 255, "1")
# 4. Un léger filtre pour lisser le bruit
image = image.filter(ImageFilter.MedianFilter(size=3))
texte = pytesseract.image_to_string(image, lang="fra")
print(texte)Le seuil de 140 dans la binarisation est un bon point de départ, mais c'est un paramètre à ajuster selon l'image : trop bas, le texte disparaît ; trop haut, le fond devient du bruit. C'est le genre de détail qui se règle par essais successifs sur un échantillon d'images.
Redimensionner pour aider la reconnaissance
Tesseract est optimisé pour des caractères d'une certaine taille, autour de 30 pixels de haut. Si ton texte est minuscule, agrandir l'image peut nettement améliorer le résultat :
# Doubler la taille de l'image (resampling LANCZOS = meilleure qualité)
image = image.resize(
(image.width * 2, image.height * 2),
Image.Resampling.LANCZOS,
)
texte = pytesseract.image_to_string(image, lang="fra")Inversement, une image trop grande et trop dense peut perdre Tesseract : dans ce cas, un redimensionnement à la baisse ou un recadrage sur la zone d'intérêt aide à se recentrer sur l'essentiel.
Prétraitement avancé avec OpenCV
Pour les cas difficiles — photos prises de biais, ombres, fonds texturés — Pillow montre ses limites. OpenCV, la bibliothèque de vision par ordinateur, offre des outils plus puissants : redressement de l'inclinaison (deskew), débruitage, et seuillage adaptatif. Installe-la avec pip install opencv-python, puis enchaîne :
import cv2
import numpy as np
import pytesseract
# Lire l'image en niveaux de gris
gris = cv2.imread("photo.png", cv2.IMREAD_GRAYSCALE)
# Réduire le bruit
gris = cv2.medianBlur(gris, 3)
# Seuillage adaptatif : le seuil s'ajuste localement (idéal en cas d'ombres)
binaire = cv2.adaptiveThreshold(
gris, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 10
)
texte = pytesseract.image_to_string(binaire, lang="fra")
print(texte)Le seuillage adaptatif est l'arme fatale contre les éclairages inégaux : au lieu d'un seuil unique pour toute l'image, il en calcule un pour chaque zone. Une photo de document prise à la lumière du jour, avec une moitié à l'ombre, devient exploitable.
Configurer Tesseract avec les paramètres PSM et OEM
Tesseract expose deux réglages qui changent radicalement son comportement. Le PSM (Page Segmentation Mode) indique comment le document est organisé ; le OEM (OCR Engine Mode) choisit le moteur de reconnaissance. On les passe via le paramètre config de Pytesseract :
# PSM 6 : un bloc de texte uniforme ; OEM 3 : le moteur LSTM par défaut
config = "--psm 6 --oem 3"
texte = pytesseract.image_to_string(image, lang="fra", config=config)Les PSM les plus utiles : 3 pour une page entière (détection automatique), 4 pour une colonne de texte, 6 pour un bloc de texte uniforme, et 7 pour une seule ligne. Si Tesseract a du mal à repérer la structure de ton image, essayer un PSM plus spécifique débloque souvent la situation.
Récupérer la position des mots, pas seulement le texte
Parfois, le texte ne suffit pas : tu veux savoir où chaque mot se trouve dans l'image, par exemple pour cliquer dessus ou pour associer un mot à une zone. image_to_data() renvoie la position de chaque élément détecté, avec son niveau de confiance :
import pytesseract
data = pytesseract.image_to_data(image, lang="fra", output_type=pytesseract.Output.DICT)
# Filtrer les mots réellement détectés (conf > 0) et leur niveau de confiance
for i, mot in enumerate(data["text"]):
if mot.strip() and int(data["conf"][i]) > 60:
x, y = data["left"][i], data["top"][i]
print(f"{mot:20} -> position ({x}, {y}), confiance {data['conf'][i]}")Le niveau de confiance (conf) te dit à quel point Tesseract est sûr de sa détection : au-dessus de 90, c'est quasi certain ; en dessous de 60, méfie-toi. C'est un excellent moyen de filtrer automatiquement les zones douteuses et de ne garder que le texte fiable.
OCR sur un PDF : convertir les pages en images
Tesseract ne lit pas les PDF directement, mais c'est un obstacle facile à contourner : on convertit chaque page du PDF en image, puis on applique l'OCR page par page. La bibliothèque pdf2image (qui s'appuie sur poppler) fait la conversion, et Pillow fournit les images.
from pdf2image import convert_from_path
import pytesseract
# Convertir chaque page du PDF en image
pages = convert_from_path("document.pdf", dpi=300)
tout_le_texte = []
for i, page in enumerate(pages):
texte = pytesseract.image_to_string(page, lang="fra")
tout_le_texte.append(f"--- Page {i + 1} ---\n{texte}")
resultat = "\n".join(tout_le_texte)
with open("document.txt", "w", encoding="utf-8") as f:
f.write(resultat)La résolution de conversion (dpi) est cruciale : 300 dpi est un bon compromis entre qualité de reconnaissance et taille des images. Installe les prérequis avec pip install pdf2image et, sur Linux, le paquet système poppler-utils.
Automatiser : traiter tout un dossier d'images
Maintenant qu'on a les briques, on assemble le tout dans un script qui traite toutes les images d'un dossier et écrit les résultats dans des fichiers texte. C'est le genre d'outil qui te fait gagner des heures sur un lot de documents scannés.
import os
import pytesseract
from PIL import Image, ImageOps
DOSSIER = "images"
SORTIE = "textes"
os.makedirs(SORTIE, exist_ok=True)
for nom in sorted(os.listdir(DOSSIER)):
if not nom.lower().endswith((".png", ".jpg", ".jpeg")):
continue
chemin = os.path.join(DOSSIER, nom)
image = Image.open(chemin)
image = ImageOps.grayscale(image)
image = ImageOps.autocontrast(image)
texte = pytesseract.image_to_string(image, lang="fra")
with open(os.path.join(SORTIE, nom + ".txt"), "w", encoding="utf-8") as f:
f.write(texte)
print(f"Traité : {nom}")Ce script est volontairement simple : il prétraite chaque image en niveaux de gris avec un auto-contraste, avant de lancer l'OCR. Pour un lot de documents homogènes — par exemple les scans d'un même type de formulaire — il suffit amplement, et tu peux toujours enrichir le prétraitement si les résultats sont décevants.
Restreindre la reconnaissance avec une liste de caractères
Quand tu connais la nature exacte du texte à lire — par exemple des numéros de série, des codes postaux ou des plaques d'immatriculation — tu peux guider Tesseract en limitant les caractères autorisés. Cette option, nommée tessedit_char_whitelist, réduit drastiquement les confusions (un « 0 » pris pour un « O », un « 1 » pour un « l »).
# Ne reconnaître que des chiffres (pour une plaque, un code, un numéro)
config_digits = "--psm 7 -c tessedit_char_whitelist=0123456789"
texte = pytesseract.image_to_string(image, config=config_digits)
print(texte.strip())Ici, on combine un PSM 7 (une seule ligne de texte) avec une liste blanche limitée aux chiffres. Le résultat est spectaculaire sur les cas où la structure est connue : Tesseract ne peut plus inventer des lettres là où il n'y a que des nombres. Adapte la liste blanche à ton cas — lettres majuscules, chiffres, tirets — et la précision grimpe immédiatement.
À l'inverse, il existe aussi une liste noire (tessedit_char_blacklist) pour exclure certains caractères problématiques. Les deux options se combinent bien avec les PSM qu'on a vus plus haut : c'est en assemblant ces petits réglages qu'on obtient un OCR vraiment fiable sur un format de document précis.
Les limites de l'OCR, et comment les contourner
Aussi bon soit Tesseract, il reste des cas où l'OCR échoue. Le reconnaître te fera gagner du temps :
- Les textes manuscrits : Tesseract est entraîné sur du texte imprimé, l'écriture manuscrite le met en échec.
- Les polices très décoratives ou les logos : l'algorithme a besoin de caractères réguliers.
- Les tableaux complexes : la structure se perd, même si les cellules sont lues.
- Les images à très faible résolution : en dessous d'un certain seuil, les caractères sont illisibles.
Pour les documents manuscrits, il existe des modèles spécialisés ou des services cloud. Pour les tableaux, des outils comme Camelot ou des modèles de détection d'objets s'en sortent mieux. Mais pour l'immense majorité des documents imprimés — factures, livres, articles scannés — la combinaison Tesseract + prétraitement donne des résultats remarquables.
Redresser une image inclinée (deskew)
Un document scanné de travers est une cause fréquente d'échec : Tesseract s'attend à des lignes de texte horizontales. OpenCV permet de détecter l'angle d'inclinaison et de redresser l'image automatiquement. La méthode classique consiste à repérer les lignes de texte par transformation de Hough, puis à faire pivoter l'image de l'angle moyen.
import cv2
import numpy as np
def redresser(image_path):
img = cv2.imread(image_path)
gris = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Binarisation pour faire ressortir le texte
_, binaire = cv2.threshold(gris, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# On repère les lignes horizontales dans l'image
lignes = cv2.HoughLinesP(binaire, 1, np.pi / 180, 100,
minLineLength=100, maxLineGap=10)
angles = []
for ligne in lignes:
x1, y1, x2, y2 = ligne[0]
angles.append(np.degrees(np.arctan2(y2 - y1, x2 - x1)))
# L'angle médian est robuste face aux valeurs aberrantes
angle = np.median(angles)
# Rotation inverse pour remettre le texte à l'horizontale
h, w = img.shape[:2]
centre = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(centre, angle, 1.0)
redressee = cv2.warpAffine(img, M, (w, h), borderValue=255)
return redressee
image_redressee = redresser("scan_incline.png")
texte = pytesseract.image_to_string(image_redressee, lang="fra")Ce script est plus avancé, mais il illustre une idée simple : détecter l'angle dominant des lignes, puis pivoter en sens inverse. Pour des scans légèrement inclinés, le gain de précision peut être spectaculaire.
Comparer avant et après prétraitement
Pour juger objectivement si ton prétraitement est utile, mesure la confiance moyenne de l'OCR avant et après. C'est une métrique simple et efficace pour itérer sur tes transformations :
def confiance_moyenne(image):
data = pytesseract.image_to_data(image, lang="fra", output_type=pytesseract.Output.DICT)
confs = [int(c) for c, t in zip(data["conf"], data["text"]) if t.strip()]
return sum(confs) / len(confs) if confs else 0
brute = Image.open("document.png")
preparee = ImageOps.autocontrast(ImageOps.grayscale(brute))
print(f"Confiance image brute : {confiance_moyenne(brute):.1f}")
print(f"Confiance image préparée : {confiance_moyenne(preparee):.1f}")Une confiance moyenne en hausse confirme que ton prétraitement aide réellement, au-delà de l'impression visuelle. C'est ce genre de mesure qui te permet de converger rapidement vers le bon pipeline, plutôt que d'ajuster les seuils au hasard.
Conclusion
Tu sais désormais installer Tesseract et Pytesseract, extraire du texte d'une image, choisir la langue, configurer le moteur, prétraiter l'image avec Pillow ou OpenCV pour améliorer la reconnaissance, récupérer la position des mots, traiter des PDF et automatiser le tout sur un dossier entier. C'est un outil puissant et gratuit, qui ouvre la porte à la numérisation de documents, à l'extraction de données de factures, ou au tri automatique de captures d'écran.
Le conseil à retenir : ne te bats jamais contre une mauvaise image avec un meilleur moteur. Améliore l'image d'abord — niveaux de gris, contraste, binarisation, seuillage adaptatif — et tu verras que 90 % des difficultés disparaissent avant même d'atteindre Tesseract.
Ce qu'il faut retenir
Avant de te lancer, voici l'essentiel de ce tutoriel en quelques points :
- Installe Tesseract d'abord, Pytesseract ensuite, et vérifie que la commande tesseract est accessible.
- Commence toujours par l'image brute : si le texte est net et bien éclairé, l'OCR suffit sans prétraitement.
- Prétraite avec niveaux de gris, contraste et binarisation dès que l'image est imparfaite.
- Choisis la bonne langue (fra) et, si besoin, le bon PSM pour ta mise en page.
- Mesure la confiance pour valider objectivement tes réglages.






