Redresser un document textuel mal scanné avec deskew

Redresser, pourquoi ?

Vous devez récupérer les données provenant de document préalablement scannés. Evidemment vous pensez immédiatement à utiliser un OCR (Cf. cet article qui montre comment utiliser Tesseract) … mais voilà, si votre document est de bonne qualité, il n’est pas aligné correctement. il est de travers ! et votre OCR n’arrive pas à interpréter son contenu.

C’est tout à fait normal, en fait il faut au préalable redresser le document afin qu’il se présente de manière droite, prête à l’application de cet OCR. Nous allons voir dans cet article comment utiliser Python et la librairie deskew.

La librairie Python deskew

Ce qui est génial avec l’univers Python c’est qu’il y a une librairie pour tout. Après quelques recherches rapide sur votre moteur de rechercher vous en trouverez certainement un certain nombre qui ne demandent qu’à être essayé.

Je vais vous montrer l’une des plus simple : la librairie deskew que vous pouvez trouver ici.

L’installation est simple et rapide (le code sous-jacent l’est aussi d’ailleurs, si vous avez le temps regardez le). pour information, cette librairie utilise une autre librairie bien plus connue scikit-image, qui est aussi très pratique pour gérer des données images.

pip install deskew

Objectif

L’objectif est plutôt simple, nous devons récupérer l’information textuelle de l’image suivante :

Histoire de vérifier ce que je vous disais en introduction, essayons d’utiliser directement Tesseract sur cette image :

try:
    from PIL import Image
except ImportError:
    import Image
import pytesseract
image1 = Image.open('img_35h.jpg')
pytesseract.image_to_string(image1, lang='fra')
''

En effet, Tesseract ne voit strictement rien !

Redressons l’image avec deskew

Avant tout importons les librairies nécessaires :

import numpy as np
from skimage import io
from skimage.transform import rotate
from skimage.color import rgb2gray
from deskew import determine_skew
from matplotlib import pyplot as plt

Puis créons une petite fonction qui nous permettra de redresser l’image :

def deskew(_img):
    image = io.imread(_img)
    grayscale = rgb2gray(image)
    angle = determine_skew(grayscale)
    rotated = rotate(image, angle, resize=True) * 255
    return rotated.astype(np.uint8)

Cette fonction est plutôt simple. La librairie deskew encapsule en effet tous les appels nécessaire au redressement … excepté peut être la conversion en niveaux de gris qui est une étape indispensable pour détecter les angles d’inclinaison.

Créons ensuite une petite fonction pour tester et voir le résultat (avec matplotlib) de nos redressements :

def display_avant_apres(_original):
    plt.subplot(1, 2, 1)
    plt.imshow(io.imread(_original))
    plt.subplot(1, 2, 2)
    plt.imshow(deskew(_original))

Le résultat

J’ai pris quelques images inclinées pour tester le résultat. Un premier test avec une inclinaison de 35 degrés dans le sens horaire :

display_avant_apres('img_35h.jpg')

Puis avec une inclinaison de 15 degrés dans le sens anti-horaire :

display_avant_apres('img_15ah.jpg')

Le résultat semble plutôt concluant n’est-ce pas ? essayons d’utiliser Tesseract maintenant sur cette image :

io.imsave('output.png', deskew('img_35h.jpg'))
image1 = Image.open('output.png')
pytesseract.image_to_string(image1, lang='fra')
'Bonjour'

Et voilà ! le résultat est bien celui attendu.

Vous voulez automatiser ce type de tâches avec le RPA Blue Prism … jetez un coup d’oeil sur cet article.

La vidéo ci-dessous montre la solution en action :

Partager cet article

3 Replies to “Redresser un document textuel mal scanné avec deskew”

  1. Merci pour cet article très utile, qui m’a permis de redresser par mal de documents automatiquement. Reste le problème des marges. Existe-t-il une solution afin de cadrer automatiquement toutes les pages selon le même format ?

  2. bonjour,

    ayant eu une valeur d’angle à None pour un image générée par package ‘pdf2image’, j’ai modifié la fonction comme ci-dessous et qui ne génère plus d’erreur :

    def deskew(_img):
    image = io.imread(_img)
    grayscale = rgb2gray(image)
    angle = determine_skew(grayscale)
    print(angle)
    if angle == None:
    angle = 0.0
    rotated = rotate(image, angle, resize=True) * 255
    return rotated.astype(np.uint8)

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.