[Tuto] Un moteur d'OCR ultra-performant & gratuit en quelques lignes de code R

August 11, 2018
R datascience machinelearning tutorial computerVision tesseract OCR LAD RAD

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, 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.

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 dans un fichier texte. L’OCR est particulièrement utile pour dématérialiser des documents papiers imprimés et les remplacer par des bases de données exploitables par ordinateur.

Les entreprises ayant énormémént d’archives papier coûteuses à stocker, pas mal de boîtes se sont donc lancées dans le créneau et proposent des solutions permettant d’aller dans le sens de la dématérialisation.

Et si on faisait notre propre moteur d’OCR pour 0€, uniquement à base d’Open Source ?

Une des forces de R est le fait qu’il ait accés à nombre d’API lui permettant de s’interfacer et d’exploiter des milliers de services divers et variés.

Parmi ces services se trouve l’outil 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 Tesseract. Pas besoin d’installation supplémentaire, donc.

En complément, on utilisera le package magick, qui permet de faire de la manipulation d’image (un peu comme Paint, mais moins rigolo et avec plus de code)

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

1. Installation & chargement des packages R :

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

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

Puis on choisit son répertoire de travail (mettez le votre pour tester)

wd <- "/chemin/vers/mon/dossier/de/travail"

On récupère un scan, j’ai choisi un thème d’actualité :

Prenons ce scan de la préface d’un livre au sujet du compost :

Téléchargeons cette image dans notre répertoire de travail et appelons-là scan.png :

# download.file(url =
# 'https://bernardkmartin.files.wordpress.com/2016/01/scan04.png', # URL de
# l'image destfile = paste0(wd,'scan.png'), # Fichier de destination mode =
# 'wb')

Okay on a tout, il est temps de faire appel à Tesseract !

On utlise image_read() pour lire l’image et la lier l’objet R que l’on appelle img_raw Pour appeler Tesseract et extraire le texte de l’image, rien de plus simple, on appelle la fonction ocr() : cat() permet ensuite d’afficher le texte extrait. Attention :

imgpath <- paste0(wd, "scan.png")
img_raw <- image_read(imgpath)

txt_raw <- ocr(img_raw)

cat(txt_raw)
## PREFACE
## 
## Les déchets de notre civilisation constituent l’une des faiblesses des systémes
## économiques qui se sont développés dans beaucoup de pays du monde, notamment
## dans les pays industrialisés.
## 
## “Prdduire plus, consommer plus", a été pendant longtemps' Ie leitmotiv de notre
## économie et constitue encore l’un des fers de lance de la croissance économique
## Iorsque le développement “va mal”. “
## 
## Tous 1es pays qui se sont engagés dans cette voie se sont trouvés tét ou tard
## confrontés avec un probléme préoccupant, celul de l’éllmination des déchets.
## L’évolution’ de la production de déchets dépend en effet principalement du niveau et
## de la structure des activités économiques de consommation et de production.
## 
## La quantité totale de déchets produits dans les pays de l’OCDE a atteint environ 8
## milliards de tonnes en 1980. Au début de cette méme année les déchets urbains
## représentaiem 350 millions de tonnes par an, soit 400 kg par habitant. Les déchets
## industriels atteignaient 1 milliard de tonnes (OCDE, 1985). Alors que dans la
## civilisation rurale la production de déchets était insignifiante, elle est devenue
## pléthorique avec la civilisation urbaine et le mode de consommation de masse qui
## l’accompagne. Tout‘ d’abord, comme nous Ie disions précédemment, tout nous
## incite a consommer plus, iI s’agit bien souvent de produits plus diversifiés ou moins
## durables, ensuite 'il est presque impossible aujourd’hui d’acheter un produit sans
## acheter son emballage... qui est trop souvent jeté.
## 
## Les statistiques établies par la société T.|.R.U. qui traite les déchets de
## I’agglomération parisienne fournissent un résumé saisissant de cette évolution (in
## I'Etat de I’Environnement, 1984).
## 
## En 20 ans, Ie tonnage collecté a augmenté de 30 %, I’augmentation en volume est
## nettement supérieure. Aujourd’hui les Frangais produisent environ 14 millions de
## tonnes d'ordures ménagéres par an, auxquels i1 convient d’ajouter 1,5 million de
## tonnes de déchets encombrants.
## 
## Nos compatriotes ignorent le plus souvent cette relation entre un type de
## production et i’augmentation des déchets. En développant la technique des
## élevages hors-sol notre pays se trouve a la téte de 30 millions de tonnes/an de Iisier
## comme le rappelle Michel MUSTIN...
## 
## Si nous en sommes arrivés la, c'est parce que, au moment on ont été lancées les
## grandes idées qui président a la destinée du monde industriel tel le Taylorisme ou Ie
## Consumérisme, les économistes ont oublié de raisonner en terme de systéme
## reproductible. Pour eux, en effet, Ie systéme économique se base sur la coexistence
## de deux catégories d’individus :
## 
## les producteurs et les consommateurs.
## 
## —_

Super ! malgré quelques erreurs de lecture (“L”" minuscule lu comme “I” majuscule, confusion entre accent grave et aigue, etc), nous avons extrait le texte de l’image avec succés en quelques secondes seulement.

Voyons voir si l’on peut faire mieux. Je vais à présent appliquer quelques traitements à notre image pour la rendre plus lisible pour Tesseract, et utiliser un moteur OCR de Tesseract entraîné sur du texte en Français :

img_proc <- image_read(imgpath) %>% image_resize("2000") %>% image_convert(colorspace = "gray") %>% 
    image_trim() %>% image_chop("150x0") %>% image_chop("0x550") %>% image_deskew(threshold = 40) %>% 
    image_background("white", flatten = TRUE) %>% image_noise() %>% image_enhance() %>% 
    # image_normalize() %>%
image_trim(fuzz = 20) %>% image_deskew()
print(img_proc)
##   format width height colorspace matte filesize density
## 1    PNG  1742   2436       sRGB FALSE        0 118x118

Allons-y pour l’extraction :

fr_engine <- tesseract(language = "fra")
txt_proc_fr <- ocr(img_proc, engine = fr_engine)
cat(txt_proc_fr)
## PRÉFACE
## 
## Les déchets de notre civilisation constituent l’une des faiblesses des systèmes
## économiques qui se sont développés dans beaucoup de pays du monde, notamment
## dans les pays industrialisés.
## 
## “Produire plus, consommer plus”, a été pendant longtemps le leitmotiv de notre
## économie et constitue encore l’un des fers de lance de la croissance économique
## lorsque le développement “va mal”. "
## 
## Tous les pays qui se sont engagés dans cette voie se sont trouvés tôt ou tard
## confrontés avec un problème préoccupant, celui de l’élimination des déchets.
## L’évolution de la production de déchets dépend en effet principalement du niveau et
## de la structure des activités économiques de consommation et de production.
## 
## La quantité totale de déchets produits dans les pays de l’OCDE a atteint environ 8
## milliards de tonnes en 1980. Au début de cette même année les déchets urbains
## représentaient 350 millions de tonnes par an, soit 400 kg par habitant. Les déchets
## industriels atteignaient 1 milliard de tonnes (OCDE, 1985). Alors que dans la
## civilisation rurale la production de déchets était insignifiante, elle est devenue
## pléthorique avec la civilisation urbaine et le mode de consommation de masse qui
## l’accompagne. Tout, d’abord, comme nous le disions précédemment, tout nous
## incite à consommer plus, il s’agit bien souvent de produits plus diversifiés ou moins
## durables, ensuite il est presque impossible aujourd’hui d’acheter un produit sans
## acheter son emballage... qui est trop souvent jeté.
## 
## Les statistiques établies par la société T.l.R.U. qui traite les déchets de
## l’agglomération parisienne fournissent un résumé saisissant de cette évolution (in
## l'Etat de I’Environnement, 1984).
## 
## En 20 ans, le tonnage collecté a augmenté de 30 %, l’augmentation en volume est
## nettement supérieure. Aujourd’hui les Français produisent environ 14 millions de
## tonnes d’ordures ménagères par an, auxquels il convient d'ajouter 1,5 million de
## tonnes de déchets encombrants.
## 
## Nos compatriotes ignorent le plus souvent cette relation entre un type de
## production et l'augmentation des déchets. En développant la technique des
## élevages hors—sol notre pays se trouve à la tête de 30 millions de tonnes/an de lisier
## comme le rappelle Michel MUSTlN...
## 
## Si nous en sommes arrivés là, c’est parce que, au moment où ont été lancées les
## grandes idées qui président à la destinée du monde industriel tel le Taylorisme ou le
## Consumérisme, les économistes ont oublié de raisonner en terme de système
## reproductible. Pour eux, en effet, le système économique se base sur la coexistence
## de deux catégories d‘individus:
## 
## les producteurs et les consommateurs.

C’est un tout petit peu mieux !

Faisons une comparaison de qualité des deux opérations d’OCR :

# install.packages(c('tidytext', 'SnowballC'))
library(tidytext)
library(SnowballC)

Pour ma comparaison, j’utilise un dictionnaire gratuit en français que j’ai trouvé sur le net. Ce dictionnaire contient 28997 radicaux de mots, et permet d’évaluer rapidement la qualité de notre océrisation. Si la racine d’un mot extrait de l’image est dans le dictionnaire, c’est que l’OCR a fonctionné.

library(readr)
library(dplyr)
dico <- data.frame(words = read_lines(paste0(wd, "francais.txt"))) %>% mutate(words = as.character(words)) %>% 
    unnest_tokens(word, words) %>% mutate(word = wordStem(word, language = "fra")) %>% 
    distinct()

Voici un aperçu du contenu du dictionnaire :


Afin de faire nos calculs de performance et de faciliter les comparaisons avec le dictionnaire, mettons le text extrait des deux images au format tableau, après avoir transformé tous les mots en leur radical (stem) :

text_1_df <- data.frame(text = read.delim(textConnection(txt_proc_fr),    # on met le texte dans un dataframe
                                          header = FALSE, 
                                          sep = "\n", 
                                          strip.white = TRUE)) %>%
  mutate(text = as.character(V1)) %>%
  unnest_tokens(word, text) %>%                                      # on sépare les mots
  mutate(word = wordStem(word, language = "fra"))                    # on remplace chaque mot par son radical

txt_raw <- gsub(pattern = '"',x = txt_raw,replacement = "”")  
txt_proc_fr <- gsub(pattern = '"',x = txt_proc_fr,replacement = "”")

text_2_df <- data.frame(text = read.delim(textConnection(txt_raw),   
                                          header = FALSE, 
                                          sep = "\n", 
                                          strip.white = TRUE)) %>%
  mutate(text = as.character(V1)) %>%
  unnest_tokens(word, text) %>%                                     
  mutate(word = wordStem(word, language = "fra"))                 

Puis calculons un indicateur de performance : parmi tous les mots extraits par Tesseract, quel pourcentage se retrouve dans le dictionnaire ?

Nous sommes autour de 77.5% de performance, dans les deux cas. Ici, le traitement n’a pas apporté grand chose car l’image de départ était de très grande qualité : centrée, droite, pas de bruit, excellent niveau de netteté. Il n’y avait donc pas vraiment besoin de traitement. Dans la réalité, il en est tout autrement, et c’est toujours une bonne idée de rajouter une étape permettant de gérer les ratés de numérisation. Il peut également arriver que le papier soit sale, froissé, jauni, etc.

Maintenant, que penser d’une performance de 77.5% ? Selon moi, c’est pas mal du tout pour si peu d’effort. D’autant plus que j’ai pris le premier dictionnaire trouvé sur le net. De plus, ce chiffre est sous-estimé du fait de la présence de noms propres et de sigles dans le texte. Avec un dictionnaire bien choisi, si possible amélioré pour inclure les termes spécifiques au corpus de documents que vous traitez et à votre secteur d’activité/métier, vous pouvez faire bien mieux.

De plus, vue la rapidité à laquelle se fait l’OCR avec Tesseract, on peut tout à fait envisager de l’inclure dans un processus temps réél (eh oui c’est possible avec R !). Il faut également savoir que l’on peut travailler avec des documents en PDF, JPEG, et tous les autres formats.

Merci Tesseract !

[Tuto] Boost ton ML : XGBoost facile & efficace avec R !

September 2, 2018
datascience data machinelearning R tools tutorial

[Tuto] Fabrique & comprends ton premier réseau de neurones en partant de zéro !

August 9, 2018
datascience machinelearning R tools DeepLearning AI NeuralNetwork

[Tools] R or Python ? Nobody Cares !

July 24, 2018
tools datascience R Python
comments powered by Disqus