Featured image of post OCR: Extraction de texte haute qualité en une ligne de code

OCR: Extraction de texte haute qualité en une ligne de code

Cet article s’adresse aux utilisateurs ayant besoin d’extraire du texte depuis un lot d’images ou de scans, dans une optique d’archivage ou de récolte de données dans le cadre d’un projet Data Science. Les données textuelles sont une mine d’or d’informations, mais souvent peu disponibles car beaucoup de process se font encore sur papier aujourd’hui, d’où l’intérêt de pouvoir les extraire pour les rendre exploitables. Une toute petite connaissance de R est un plus, mais pas nécessaire pour comprendre ce qui suit.

I. L’OCR, pourquoi faire ?

L’Optical Character Recognition (Reconnaissance Optique des Caractères ou Océrisation) est un procédé permettant d’extraire du texte depuis une image ou un PDF vers fichier texte. L’OCR est particulièrement utile pour dématérialiser des documents papiers imprimés et les convertir en données exploitables par ordinateur.

Concrètement, on part d’une photo ou d’un scan de document (PDF ou dans un format d’image), et on arrive à un fichier texte. Les usages sont nombreux ensuite: NLP & analyses textuelles, dématérialisation documentaire, etc.

II. Un moteur d’OCR pour 0 €, 100% d’Open Source : pourquoi pas ?

Une des forces de R est son écosystème de librairies. Parmi celles-ci, on en trouve un grand nombre permettant d’utiliser simplement des milliers de services divers et variés, externes au langage R. Elles permettent de s’interfacer de manière aisée à des services ou outils parfois complexe, et de les exploiter sans difficulté.

C’est par exemple le cas de Tesseract, lancé par Hewlett-Packard Co en 1985 puis open sourcé en 2005. Depuis, il est maintenu et mis à jour par Google et disponible gratuitement.

Par souci de simplicité, nous utiliserons simplement un package R qui comprend déjà Tesseract. Pas besoin d’installation supplémentaire, donc.

En complément, on utilisera le package magick, qui permet d’éditer des images (un peu comme Paint, mais moins rigolo et avec du code)

1. C’est parti ! On met en place ce qu’il faut

a. Installation & chargement des packages R :

# install.packages('tesseract') install.packages('magick')
# install.packages('magrittr')

library(tesseract)  # interface R vers le moteur d'OCR Tesseract
library(magick)  # Ensemble d'outils d'image processing
library(magrittr)  # Pour chaîner les opérations avec %>%

b. Je récupère quelques pages de texte photographiées avec mon téléphone

Une première en anglais:

Et une seconde en français:

Je stock les liens vers les images dans des variables pour un usage facilité par la suite

fr_img <- "https://raw.githubusercontent.com/corridordigital/random-stuff/main/fr.jpg"
en_img <- "https://raw.githubusercontent.com/corridordigital/random-stuff/main/en.jpg"

2. Utilisation basique de Tesseract !

Pour appeler Tesseract et extraire le texte de l’image, rien de plus simple, on appelle la fonction ocr() du package tesseract :

text_en_raw <- tesseract::ocr(en_img)

cat() permet ensuite d’afficher le texte extrait tel quel, “sale” avec retours à la ligne et ponctuation.

On peut également faire la même chose en générant un indice de confiance pour chaque mot “OCRisé”, pour détecter les mots qui posent problème:

res <- ocr_data(en_img)
head(res, 10)
##            word confidence              bbox
## 1             :    0.00000 1195,409,1203,418
## 2            ye   62.43615   168,479,241,525
## 3         spent   96.43826   270,462,424,527
## 4       decades   96.08789   454,429,689,493
## 5      studying   96.81033   722,416,989,483
## 6           the   95.77077 1020,411,1117,464
## 7  hippocampus.   95.77077 1151,410,1579,479
## 8          It’s   96.51285 1615,412,1703,465
## 9          been   96.94233 1736,412,1887,465
## 10         good   96.77615 1919,413,2064,480

(bbox, pour bounding box donne la position du mot dans la page, dans une approche segmentation en vision artificielle)

On a pour ce cas précis pour l’indice de confiance (valeur minimale, 1er quartile, médiane, moyenne, 3e quartile, valeur maximale):

summary(res$confidence)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    0.00   92.88   96.38   83.07   96.73   97.02

Super ! malgré quelques erreurs de lecture, nous avons extrait le texte de l’image avec succés en quelques secondes seulement avec un niveau de confiance médian de 96,4%. C’est excellent au vu de l’effort fourni et de la complexité de la pipeline (nulle). Le texte obtenu doit bien sûr être traité pour le débarrasser des artefacts qui apparaissent fréquemment.

Pour notre page en français, on tente la même chose:

res <- ocr_data(fr_img)
head(res, 10)
##       word confidence              bbox
## 1      Des  96.994125   678,103,806,191
## 2        |  60.982018 2351,126,2352,130
## 3  mouches  92.386284  844,120,1169,190
## 4       du  96.811623 1200,134,1291,200
## 5   marché  95.742325 1325,157,1588,222
## 6       B0   0.000000 2011,189,2091,245
## 7        .   9.636871   442,280,461,295
## 8        ‘  37.786007   844,280,857,301
## 9        {  13.578598 2353,222,2365,278
## 10      La  95.915062   231,290,324,355
summary(res$confidence)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    0.00   56.55   91.60   73.42   96.06   97.02

91,6%, c’est pas mal du tout, mais probablement améliorable !

3. Pré-traitement des images et choix du bon moteur d’OCR

Voyons voir si l’on peut faire mieux. Je vais à présent:

  • Appliquer quelques traitements à notre image pour la rendre plus lisible pour Tesseract, en utilisant ImageMagick
  • Utiliser un moteur OCR entraîné sur du texte dans la langue de l’image que l’on cherche à traiter (français, donc). En effet, le moteur par défaut est entraîné sur de l’anglais, et sera moins performant pour reconnaître du français ou de l’allemand. Bien évidemment, il n’est pas question de l’essayer sur une langue utilisant les caractères autres que latins (Arabe, Chinois, Russe, etc.). Il faudra un moteur dédié pour chacune de ces langues.

Voyons si l’on peut améliorer facilement notre précédente performance sur le texte en français (+ traitement):

# tesseract::tesseract_download('fra')
fr_engine <- tesseract(language = "fra")

input <- image_read(fr_img)

text <- input %>%
    image_resize("2000x") %>%
    image_convert(type = "Grayscale") %>%
    image_trim(fuzz = 40) %>%
    tesseract::ocr_data(engine = fr_engine)

summary(text$confidence)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    0.00   91.13   95.76   85.33   96.40   97.00

Beaucoup mieux ! 😄 95% !

Merci Tesseract !

Ce package peut s’intégrer dans un processus de dématérialisation à grande échelle et permettre de numériser de grands volumes de documents à un coût logiciel et de développement nul. Le mieux quand même est de développer une pipeline adaptée à ses documents (langue, pré-traitements, et traitement du texte obtenu). Il existe des solutions open source supérieures à Tesseract qui méritent d’être explorées si votre besoin est plus avancé.

Tesseract n’est pas bon sur du texte manuscrit, il existe par contre des modèles à base de Transformers qui y arrivent assez bien comme HTR qui utilise PyTorch (lien).

Merci pour votre lecture ! 😊👋

~ Anas EL KHALOUI

Généré avec Hugo
Thème Stack conçu par Jimmy