Test d’EasyOCR : excellents résultats sur texte net, seuil brutal de taille et processus CPU de 1 Go

Dernière mise à jour le August 20, 2026
Test d’EasyOCR : excellents résultats sur texte net, seuil brutal de taille et processus CPU de 1 Go
Résumé IA

EasyOCR est la bibliothèque OCR prête à l’emploi de JaidedAI pour Python : pip install easyocr, deux lignes de code, et le texte intégré à une image revient sous forme de chaînes de caractères. Sous licence Apache-2.0, elle revendique plus de 80 langues et fonctionne comme un pipeline de deux modèles PyTorch — un détecteur CRAFT qui encadre tout ce qu’il identifie comme du texte, puis un recognizer qui lit les caractères à l’intérieur de chaque boîte. Les poids préentraînés se téléchargent automatiquement lors du premier appel. Dans son approche, c’est une alternative auto-hébergée à Tesseract et PaddleOCR, et non une API OCR cloud facturée à la page.

EasyOCR est la bibliothèque OCR prête à l'emploi de JaidedAI pour Python : pip install easyocr, deux lignes de code, et le texte noyé dans une image ressort en chaînes. Apache-2.0, 80+ langues annoncées, pipeline de deux modèles PyTorch — détecteur CRAFT qui encadre le texte probable, puis reconnaisseur qui lit les caractères de chaque boîte. Poids auto-téléchargés au premier appel. Alternative auto-hébergée à Tesseract ou PaddleOCR, pas une API OCR à la page.

L'API tient en deux lignes : Reader(['en']), puis readtext(). Le déploiement pèse plus lourd — ~2 Go de PyTorch, près d'un gigaoctet de mémoire résidente au pic. J'ai généré 36 PNG en anglais, fait tourner easyocr 1.7.2 sur CPU, et comparé les lectures caractère par caractère à une vérité terrain générée en même temps. Taille et orientation ont le plus fait chuter le taux d'erreur ; un dashboard synthétique a aussi révélé des ratés sur les jetons courts et une confusion récurrente sur le signe dollar.

Le paramètre que tout le monde recommande produit l'échec le plus frappant. rotation_info a la réputation d'être la solution contre les images pivotées, testé sur trois copies d'une phrase tournées à 90°. À 270°, promesse tenue : CER de 0,83 à 0,10. À 180°, ça ne marche qu'à moitié : 0,85 à 0,67, une expression disparue. À 90°, ça empire : 0,81 à 0,92, avec du texte en miroir. Même paramètre, mêmes angles, trois résultats — l'activer ne veut pas dire « rotation réglée ». Ces fixtures ont aussi montré une falaise nette de taille de police, une confusion systématique sur le dollar, et une prédiction fausse.

Deux modèles dans un seul manteau

EasyOCR n'est pas un modèle mais un pipeline de deux — savoir lequel a échoué change le débogage.

CRAFT, le détecteur, ne fait que localiser : décider où il y a du texte et renvoyer des boîtes, sans jamais lire un caractère. Le reconnaisseur CRNN — ResNet, BiLSTM, décodage CTC glouton — lit ensuite les caractères dans chaque boîte. Les deux tournent sur PyTorch ; sur CPU, le reconnaisseur est quantifié en int8 par défaut, d'où sa légèreté malgré son nombre de paramètres.

Schéma système : détection avant reconnaissance

Conséquence : deux modes d'échec, deux correctifs. Sans boîte détectée, peaufiner le reconnaisseur ne sert à rien. Boîte correcte mais chaîne fausse : problème de reconnaissance, qu'un prétraitement peut corriger. Presque tous les fils « EasyOCR a raté mon texte » confondent les deux.

État du projet au 27 juillet 2026 : 29 825 étoiles, 528 issues ouvertes, Apache-2.0, v1.7.2 datée de septembre 2024, dernier push sur master en décembre 2025. Ces dates ne garantissent ni stabilité ni maintenance active : vérifiez votre pile, la réactivité des mainteneurs, et les issues proches de vos entrées.

L'OCR évoque souvent le contournement de CAPTCHA — pas le sujet ici. Rien testé contre l'anti-bot, rien ici ne l'encourage. Le périmètre est la lecture de texte dans des images que vous avez le droit de lire.

Ce que j'ai mesuré, et ce que ça ne couvre pas

Le jeu de test : 36 PNG générés par mes soins — 35 images d'une ligne balayant sept polices, huit tailles, sept contrastes, sept inclinaisons, trois rotations orthogonales et trois arrière-plans, plus un dashboard synthétique avec 19 éléments étiquetés. Chaque image vient de la même chaîne (Sphinx of black quartz, judge my vow. 1234567890 — 48 caractères, casse mixte, chiffres, ponctuation), générée avec le label : les deux ne peuvent pas diverger.

Métrique : character error rate (CER), distance de Levenshtein en caractères divisée par la longueur de la vérité terrain. CER 0 = parfait, 0,10 = un caractère sur dix faux. Le CER sensible à la casse est le chiffre titre, l'insensible en complément — la casse concentre l'essentiel de « l'erreur ».

Limites :

  • Anglais seul, reconnaisseur english_g2 ; 80+ langues annoncées, une seule testée.
  • Synthétique seul : texte rendu, pas de photos, pas de bruit capteur, ni JPEG, ni éclairage, ni perspective.
  • Pas d'écriture manuscrite, non supportée selon le projet.
  • CPU seul. macOS arm64, gpu=False. MPS disponible mais inutilisé. Aucun chiffre GPU ici.
  • Une machine, une version : easyocr 1.7.2, torch 2.13.0, Python 3.12.

Des courbes contrôlées à variable unique montrant où la fidélité casse sur du latin propre — pas un score de corpus réel.

Preuves inspectables : fixtures dans tests/build_fixtures.py et tests/fixtures/ground_truth.json ; exécution dans tests/run_easyocr.py ; métriques dans tests/metrics.py ; résultats bruts dans artifacts/raw/. Rejouer la chaîne vérifie cette machine et cette version, pas vos photos ni vos mises en page.

Un piège a failli fausser le chiffre titre : ma première passe donnait 0,375 sur de l'Arial noir propre, catastrophique. Le détecteur avait scindé une ligne en boîte-mots et boîte-chiffres, et mon tri naïf y-puis-x plaçait les chiffres en premier. Corrigé par regroupement par recouvrement vertical, les polices propres retombaient à 0,04–0,10.

Installation : le paquet est léger, la dépendance ne l'est pas

Schéma système : installation légère, dépendance lourde

pip install easyocr

C'est tout, et ça ne dit presque rien. Le paquet est trivial ; ce qu'il entraîne, c'est PyTorch, ~2 Go. Au premier appel de readtext(), EasyOCR télécharge silencieusement ses poids dans ~/.EasyOCR/model/93,7 Mio au total, 79,30 Mio détecteur (craft_mlt_25k.pth) et 14,44 Mio reconnaisseur (english_g2.pth).

Aucun tutoriel ne le signale : le premier lancement a besoin du réseau, et un déploiement conteneurisé doit soit embarquer ces poids, soit encaisser le téléchargement au démarrage. Une fois en cache, tout fonctionne hors ligne.

L'initialisation à froid de Reader() a pris 1,3 à 1,7 seconde. Ensuite :

import easyocr
reader = easyocr.Reader(['en'], gpu=False)
result = reader.readtext('screenshot.png')

Deux lignes, rien à configurer. Le « easy » se justifie ici — la friction est dans la dépendance, pas dans l'API.

Le plancher du texte propre : caractères quasi parfaits, casse imparfaite

Sept polices système, noir sur blanc, 32 px, même phrase :

PoliceCER (sensible à la casse)CER (insensible à la casse)
Georgia0.06250.0000
Times0.04170.0417
Comic Sans0.04170.0208
Arial0.08330.0208
Verdana0.08330.0208
Impact0.08330.0208
Courier0.10420.0417
Moyenne0.07140.0238

CER moyen de 0,071, tombant à 0,024 casse normalisée. EasyOCR ne perd pas de caractères sur du latin propre, il trouve la forme mais se trompe sur la casse : vow devient VOW dans six polices sur sept (Comic Sans donne Vow), Impact ajoute ofOf, le point final ressort en : ou _. Georgia est parfaite hors casse.

Utile à savoir : pour une correspondance floue ou un LLM en aval, un basculement de casse ne coûte presque rien. Pour une comparaison exacte avec une clé de base de données, ça coûte tout. Normalisez la casse avant de comparer.

Courier au pire score (0,1042) est logique : l'espacement à chasse fixe gêne un décodeur CTC entraîné sur un espacement typique.

La falaise de taille tombe exactement là où la documentation le dit

Graphique de résultats mesurés : taux d'erreur caractère selon la hauteur de glyphe

readtext() a un paramètre documenté, min_size=10, qui écarte les boîtes de moins de 10 pixels. Presque tout le monde l'ignore, alors que c'est le chiffre le plus déterminant pour l'extraction de captures d'écran ou de PDF :

Px rendusCERCe qui s'est passé
80.7708Effondrement — boîtes sous le filtre min_size, éliminées ; fragments seuls survivent
100.1458Dégradé — au plancher, le détecteur fragmente la ligne en 3 boîtes
120.0417Récupéré
160.0000Lecture parfaite
200.0208Propre
280.0208Propre
400.0625Propre (le basculement de casse revient)
640.0625Propre (basculement de casse)

Le saut de 0,04 à 0,77 entre 12 px et 8 px n'est pas graduel, c'est un filtre qui fait ce que sa documentation annonce. Sous ~10 px, le texte devient invisible.

Zone idéale : 12–28 px, CER de 0 à 16 px. Au-delà de 40 px, le CER remonte un peu — pas parce que les caractères se perdent, mais parce que vowVOW revient.

Pour extraire du texte de captures : vérifiez la hauteur de glyphe avant d'accuser le modèle. Un dashboard capturé en 1× sur HiDPI, ou un PDF à 72 DPI, met le texte sous 10 px. Capturez en 2× pour éviter toute une classe de tickets « EasyOCR a ignoré ma page ». Sinon, baissez min_size, mais attendez du bruit.

Rotation : 10° de tolérance, correctif non symétrique

D'abord l'inclinaison. Petits angles, Arial 32 px, défaut contre rotation_info=[90,180,270] :

Angle d'inclinaisonCER (défaut)CER (avec rotation_info)
0.08330.0833
0.04170.0417
10°0.02080.0833
15°0.29170.3750
20°0.75000.7708
30°0.89580.8750
45°0.89580.8750

Par défaut, EasyOCR encaisse l'inclinaison jusqu'à ~10° (CER ≤ 0,083), vacille à 15°, s'effondre à 20°. rotation_info ne fait rien contre l'inclinaison — il ne retente qu'aux angles listés, et 15° n'est ni 90, ni 180, ni 270. À 10°, il aggrave même les choses (0,021 → 0,083).

Les rotations orthogonales sont plus étranges :

RotationCER (défaut)CER (avec rotation_info)Récupéré ?
90°0.81250.9167Non — pire
180°0.85420.6667Partiellement
270°0.83330.1042Oui

Même paramètre, mêmes angles, trois résultats.

À 270°, rotation_info tient la promesse du fil d'issue : CER de 0,83 à 0,10. À 180°, ça ne marche qu'à moitié — 0,67, mais my vow. disparaît. À 90°, ça empire : 0,81 à 0,92, et le reconnaisseur renvoie des chaînes en miroirVOW devient MOA, quartz devient zuuenb. Lus dans un miroir, c'est correct — joli tour de magie, pipeline inutilisable.

Vérifié sur les prédictions brutes, pas les métriques agrégées : « l'ordre de fusion a tout mélangé » était mon premier soupçon, mais non — c'est ce qu'EasyOCR a vraiment renvoyé.

Le mécanisme reste une hypothèse : Pillow rend les angles positifs sens antihoraire, donc seule l'image à 270° tombe sur une orientation bien gérée. rotation_info ne peut pas être supposé symétrique selon les orientations. Validez les rotations attendues dans vos entrées ; normaliser l'orientation en amont est une piste à tester, pas une certitude.

La prédiction que j'ai ratée

Je m'attendais à ce que le faible contraste soit le point faible d'EasyOCR, avec un chemin de secours documenté : contrast_ths=0.1 et adjust_contrast=0.5, qui relance les boîtes à faible contraste sur une copie rehaussée.

Il ne s'est jamais déclenché, faute d'en avoir besoin.

Gris de premier planContraste de WeberCER (défaut)CER (adjust_contrast=1.0)
0 (noir)1.0000.08330.0833
640.7490.08330.0833
1100.5690.08330.0833
1500.4120.10420.1042
1800.2940.06250.0625
2000.2160.04170.0417
2200.1370.04170.0417

Le CER ne quitte jamais la bande propre, jusqu'à un Weber de 0,14 — gris 220 sur blanc, assez pâle pour devoir plisser les yeux. La colonne « contraste rehaussé » est identique au défaut : le défaut réussissait déjà.

Les arrière-plans, texte noir tout du long :

Arrière-planCER
Panneau bleu clair uni0.083
Dégradé vertical0.021
Bruit gaussien (μ200, σ22)0.000

Lecture parfaite sur la fixture la plus bruitée du lot.

Périmètre étroit : faible contraste uni, sans bruit — pas un reçu photographié avec bruit capteur et JPEG. Ici, géométrie et jetons courts causent les plus gros échecs, pas la couleur.

Un cas réel : extraire des chiffres d'une capture de tableau de bord

C'est là où finit la plupart du travail OCR en Python : capture d'un dashboard interne, ou pipeline de scraping Python sur une page où les chiffres n'existent qu'en pixels rendus, à récupérer comme données.

J'ai rendu une fenêtre « Sales Dashboard » — en-tête sombre, titre, badge circulaire, trois panneaux KPI, trois boutons, un tableau 2×3 — étiqueté ses 19 éléments de texte avec chaîne exacte et boîte en pixels, puis comparé à la sortie d'EasyOCR par recouvrement de boîtes.

Rappel de détection : 16 sur 19. Les trois ratés :

  • le badge à une seule lettre, « A »
  • la cellule « Q1 »
  • la cellule « Q2 »

Et « Q3 » a été détecté. Même police, même taille, même colonne — le détecteur garde un jeton et en lâche deux autres. Détection incohérente sur des cellules similaires ; résultats déterministes, donc pas un hasard type pile-ou-face. Un problème voisin est référencé dans l'issue #460.

Sur les 16 éléments détectés, le texte était quasi parfait : CER moyen 0,027, 13 exacts sur 16. Titres, libellés, boutons (« Save », « Cancel », « Export CSV »), en-têtes de colonnes et nombres à séparateurs de milliers à CER 0. 1,284 a été lu correctement, virgule comprise.

Les trois lectures imparfaites relèvent de la même erreur : les montants en dollars.

Vérité terrainLecture EasyOCR
$57,912S57,912
$18,330S18,330
$25,178S25,178
$12,004$12,004 (correct)

Trois signes dollar sur quatre sont devenus un S majuscule. Visuellement compréhensible — mais chaque champ monétaire est à un caractère de la corruption, et un float() naïf plantera sur les trois.

Pour des libellés courts ou des montants, validez l'agrandissement, le recadrage avec marge, ou un post-traitement sensible aux symboles. Rien de tout ça n'a été mesuré ici, et une regex qui réécrit un S en tête peut corrompre des valeurs légitimes.

Ce que ça coûte à faire tourner

Chiffres sur la même machine (macOS arm64, CPU, hôte unique) :

MesureValeur
Poids du modèle sur disque93,7 Mio (79,30 détecteur + 14,44 reconnaisseur)
Mémoire résidente au pic, processus CPU neuf984,5 Mio
Initialisation à froid de Reader()1,3–1,7 s
Latence à chaud, une ligne propre de 48 caractères (p50)~0,062 s (p25–p75 : 0,059–0,067 s, n=20)
detail=0 contre detail=1~égal (0,062 contre 0,063 s en médiane)

Le vrai coût n'est pas les 94 Mo de poids, c'est environ un gigaoctet de mémoire résidente par worker, plus ~2 Go de torch. C'est ce chiffre qui décide si ça tient dans votre conteneur.

La vitesse est correcte sur le cas facile : moins de 0,1 s à chaud pour une ligne propre. Mais c'est le cas facile. Les plaintes « EasyOCR met des dizaines de secondes sur CPU » concernent de grands documents multi-régions, non reproduits ici.

Un mythe à enterrer : detail=0 ne rend pas EasyOCR plus rapide. Il retire juste boîtes et scores de confiance ; le calcul a déjà eu lieu.

Avantages et inconvénients

Avantages

  • Rappel de caractères quasi parfait sur latin propre rendu — CER moyen 0,071 sensible à la casse, 0,024 insensible, CER de 0 atteignable à 16 px.
  • Vraie API en deux lignes. Reader(['en']) puis readtext(), sans configuration.
  • Plus robuste au contraste que sa réputation ne le suggère : aucun effondrement jusqu'à Weber 0,14.
  • Quasi parfait sur les éléments de capture détectés : CER moyen 0,027, 13 exacts sur 16.
  • Déterministe, octet pour octet, sur deux exécutions indépendantes.
  • Apache-2.0, auto-hébergé, sans frais d'usage fournisseur.

Inconvénients

  • Effondrement net sous min_size=10 — CER 0,77 à 8 px.
  • Tolérance à l'inclinaison limitée à ~10°, effondrement à 20°.
  • rotation_info non symétrique : 270° récupère, 180° partiellement, 90° empire avec du miroir.
  • Le détecteur perd les jetons courts isolés en gardant une cellule voisine identique.
  • Confusion systématique $S sur les valeurs monétaires (3 sur 4).
  • ~1 Go de mémoire résidente par processus, plus ~2 Go de torch.
  • Dernière version de septembre 2024 ; stable plutôt qu'activement évolutif.

Qui devrait l'utiliser, et qui devrait passer son chemin

Évaluez EasyOCR pour du texte propre, droit, à taille raisonnable — captures d'écran, interfaces, PDF rastérisés — avec un pipeline Python auto-hébergé sans frais fournisseur. Photos, manuscrit, autres écritures demandent des tests séparés.

Passez votre chemin pour : des photographies ; de l'écriture manuscrite (non revendiquée par le projet) ; des écritures non latines (80+ langues annoncées, une seule testée) ; des entrées pivotées arbitrairement ; des déploiements contraints en mémoire.

Avant de choisir l'OCR, inspectez le DOM et les réponses réseau. Si les valeurs existent en texte structuré, extraire cette source évite les erreurs de l'OCR, réservé aux cas où les pixels sont la seule représentation.

Alternatives, et la place de notre pile

EasyOCR est Apache-2.0, auto-hébergé, sans frais d'usage fournisseur mais avec un vrai coût de calcul. PaddleOCR, Tesseract et les modèles vision-langage n'ont pas été testés ici, donc aucune conclusion tête-à-tête.

La comparaison la plus intéressante n'oppose pas deux OCR entre eux : c'est de savoir s'il faut faire de l'OCR du tout.

L'essentiel du travail d'extraction par capture d'écran contourne une page web difficile — tableau JavaScript, dashboard derrière une connexion. Capturer puis OCR-iser ressemble au chemin de moindre résistance, mais vous jetez du texte structuré pour payer ensuite une taxe sur le signe dollar.

Note de l'auteur : Thunderbit est notre option gérée pour extraire des pages web, non testée sur ces fixtures. Extraction DOM/réseau quand des données structurées existent, OCR quand les pixels sont la seule source.

Lectures liées : la comparaison des scrapers open source, le test de Crawl4AI, et l'extraction pilotée par IA.

Essayer Thunderbit pour l'extraction de données web

Verdict

Faut-il utiliser EasyOCR ? Oui, si vos images sont droites, vos glyphes font au moins 12 pixels, et vous lisez du latin. Dans ce cadre, c'est très bon — CER moyen 0,071 sur texte propre, 0,024 casse normalisée, lecture parfaite à 16 px. L'API tient en deux lignes, la sortie est déterministe.

Hors de ce cadre, les échecs sont précis et prévisibles. Le texte sous 10 px disparaît dans min_size. Une inclinaison au-delà de 20° détruit la lecture. rotation_info corrige une orientation, en corrige une autre à moitié, aggrave la troisième avec du miroir. Les signes dollar deviennent des S.

Les échecs viennent des deux étages : boîtes ratées côté géométrie, confusion dollar côté reconnaissance. Traitez agrandissement, normalisation d'orientation et réparation de symboles comme des pistes à valider, pas des correctifs universels.

Surtout, ne le testez pas comme j'ai failli le faire, avec un banc cassé et un chiffre incompris. Générez vos propres fixtures et trouvez votre propre falaise.

Essayer Thunderbit pour l'extraction de données web Get Started Free

FAQ

EasyOCR est-il assez précis pour extraire du texte de captures d'écran en production ? CER moyen de 0,027 avec 13 exacts sur 16 sur le dashboard synthétique. Trois éléments sur 19 non détectés, trois signes dollar sur quatre devenus S. À tester sur vos propres mises en page.

Quelle est la taille de police minimale qu'EasyOCR peut lire ? Environ 12 pixels de hauteur de glyphe rendue. min_size=10 écarte les boîtes de moins de 10 px : CER 0,77 à 8 px, 0,15 à 10 px, 0,04 à 12 px, 0 à 16 px. Bande propre : 12–28 px. Pour une capture HiDPI en 1× ou un PDF à 72 DPI, agrandissez avant l'OCR.

rotation_info corrige-t-il les images pivotées dans EasyOCR ? Pas de façon fiable, ni symétrique. 270° récupère proprement (CER 0,83 → 0,10), 180° partiellement (0,85 → 0,67), 90° empire (0,81 → 0,92) avec du miroir comme VOWMOA. Aucun effet sur les petits angles d'inclinaison.

Combien de mémoire et de disque EasyOCR demande-t-il ? Poids de 93,7 Mio — 79,30 Mio détecteur, 14,44 Mio reconnaisseur. Mémoire résidente au pic : 984,5 Mio, plus ~2 Go de torch. Initialisation à froid : 1,3 à 1,7 seconde ; une ligne propre tourne ensuite à ~0,062 seconde.

EasyOCR est-il gratuit pour un usage commercial, et toujours maintenu ? Licence Apache-2.0. Au 27 juillet 2026, le dépôt affiche 29 825 étoiles et 528 issues ouvertes, dernière version v1.7.2, septembre 2024, dernier push en décembre 2025. Stable plutôt qu'abandonné. Vérifiez la licence vous-même.

Ke
Ke
CTO chez Thunderbit | Data Scientist senior et expert en ML Forte d’une expérience de près de dix ans en machine learning et en data science, Ke Shen est diplômé de Columbia University et ancien Data Scientist senior chez Walmart Labs. Grâce à une expertise approfondie, reconnue par ses pairs, en Python, R, Java et statistiques, il partage des analyses éprouvées sur le passage d’algorithmes d’IA complexes de la théorie à une architecture prête pour la production.
Table des matières
Thunderbit · Agent IA de données web

Extrayez des données de n'importe quelle page en 1 clic

Approuvé par plus de 250 000 utilisateurs
formule gratuite disponible
De la page web au tableur
Décrivez ce dont vous avez besoin — l'agent IA de Thunderbit l'extrait et l'exporte vers Excel, Google Sheets, Airtable ou Notion. Gratuit pour commencer.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week