Dominique Meeùs
Dernière modification le   
retour à la table des matières — à l’index — à ma page de départ

Scanner un livre pour en faire un document DjVu, avec le texte.

Up: Home Previous: Reconnaissance de caractères, Optical Character Recognition (OCR) Next: Scripts

J’ai voulu réaliser des DjVu de qualité de deux documents, de 1965 et de 1970, tapés à la machine à écrire. Je suis arrivé à la procédure suivante.

Pour avoir un DjVu lisible mais pas inutilement gros, je choisis de le faire en mode trait (line art, black and white). Pour produire ça, beaucoup de scanners, et le mien en particulier, scannent en gris et réduisent de manière assez fruste l’image en bitonal (bilevel), sans laisser de choix de contraste ou luminosité, ou du niveau de séparation entre noir et blanc. Pour avoir un résultat de qualité, il faut faire un scan de qualité en gris, donc avec des informations plus riches qu’un scan en mode trait, et le réduire soi-même. Il faut veiller à régler gamma, luminosité et contraste pour avoir une image à fond le plus blanc possible. Du grisé restant dans le fond peut donner de petits points noirs en noir et blanc et même si c’est peu visible, c’est beaucoup d’information inutile qui alourdit les fichiers que l’on veut réduire. Sur une page de photocopie sur papier raisonnablement blanc (mais qui donne par défaut un scan gris), j’avais une image de fond blanc avec caractères bien nets en choisissant gamma = 0.8, luminosité = 20, contraste = 30, avec un papier un peu plus jaune gamma = 1, luminosité = 20, contraste = 30, et j’ai choisi de scanner à 300 dpi pour le rapport qualité/temps et volume. Si on commence par une sortie PNG, appelons les pages book001.png.

À la dactylographie, à la photocopie ou au scanner, le papier peut être posé légèrement de travers. Il faut donc redresser les lignes de texte (deskew). Cela veut dire prendre toute l’image en mémoire, détecter les lignes de texte et l’angle qu’elle font avec les bords et écrire une nouvelle image redressée. C’est une opération relativement lourde qu’il y a intérêt à faire sur la version noir et blanc plutôt que grise (moins d’information à traiter et à récrire). Cependant, j’ai trouvé un excellent petit programme qui fait les deux en même temps. Il s’agit de Deskew dont j’ai trouvé et utilisé (juillet 2015) la version 1.10 de mars 2014. Le programme est entièrement contenu dans des exécutables (pour Linux, pour Mac et pour Windows) en ne demande pas d’installation. On peut le mettre simplement dans son dossier de travail. Je l’ai cependant, chez moi, placé en /opt/Deskew et j’ai créé en /usr/bin, sous le nom de deskew, un lien symbolique vers /opt/Deskew/Bin/deskew64, ce qui me permet d’appeler la commande deskew de n’importe quel répertoire. Je fais donc :

deskew -f b1 -b FFFFFF -o book001.tiff book001.png

À la commande appliquée sur le fichier PNG, je demande (-o) une sortie en TIFF de format (-f b1) noir et blanc. Attention que redresser une page fait apparaître de fins triangles sur les bords. Je demande donc pour ces surfaces nouvelles un fond (background, -b) blanc.

On est passé ainsi d’un coup, et pas trop lentement, d’un PNG de plusieurs centaines de ko (kB) à un TIFF noir et blanc de bonne qualité mais de quelques dizaines de ko seulement, et où le texte est redressé.

Pour passer en DjVu, on utilise la commande cjb2 de DjVuLibre en faisant :

cjb2 -dpi 200 book001.tiff book.djvu

Notre livre n’a encore qu’une page, mais on ajoutera les autres. Le paramètre -dpi 200 est important pour l’apparence. Il garantit que le DjVu s’ouvre à 100 % dans une fenêtre de largeur raisonnable. Cela ne change rien à la qualité. Cela évite simplement de devoir zoomer dans un sens ou dans l’autre pour trouver une dimension raisonnable. (Vous pouvez choisir une autre valeur. Avec 300, la page s’ouvrirait plus petite, et à 150 plus grande.) On pourrait ajouter l’option -lossy, pour éliminer des poussières du fond, mais il faut s’assurer qu’on ne perd pas des fragments isolés de caractères mal imprimés, surtout dans le cas de textes dactylographiés, reprographiés…

On applique les mêmes commandes pour la page 2, mais en numérotant cette fois la page DjVu : book002.png → book002.tiff → book002.djvu. On ajoute alors la page 2 au livre par :

djvm -i book.djvu book002.djvu

On peut ainsi épaissir le livre de manière incrémentale (-i). Mais la forme incrémentale de la commande djvm de DjVuLibre s’applique à un livre existant, qu’on doit donc créer d’abord avec la page 1.

Comme on a de bons scans de 300 dpi , on pourrait vouloir en conserver le texte, pour si un jour on a le courage de l’éditer. Je propose donc d’ajouter une commande tesseract. (Les anciens Tesseract n’acceptaient que des fichiers TIFF, mais à partir de Tesseract 3, ça marche aussi en PNG.) Si vraiment on ne veut qu’un DjVu image sans texte (avec texte pour les yeux et les neurones, mais pas pour l’ordinateur), on peut effacer les lignes avec tesseract. Si on les laisse, il faut que Tesseract 3 soit installé, avec les fichiers pour les langues qui vous intéressent (-l fra demande à Tesseract de se baser sur les données pour le français). Cela produit des fichiers hOCR qui sont des fichiers HTML avec des indications de position. La deuxième étape sera alors d’introduire le texte à la bonne position dans une couche texte du fichier DjVu. On verra ça plus loin.

On commence donc par les commandes de la première page pour amorcer la pompe (créer le livre) ; on efface les images PNG et TIFF de cette page pour ne pas les inclure une deuxième fois. Pour ne pas retaper à toutes les pages les mêmes commandes que celles de la page 1, et aussi pour pouvoir en traiter des paquets de quelques pages d’un coup, on met les commandes dans un script :

tesseract $f $j -c tessedit_create_hocr=1 -l fra
deskew -f b1 -b FFFFFF -o book001.tiff book001.png
cjb2 -dpi 200 book001.tiff book.djvu
#!/bin/bash
for f in book*.png
do
        j=`basename $f .png`
        tesseract $f $j -c tessedit_create_hocr=1 -l fra
        deskew -f b1 -b FFFFFF -o $j.tiff $f
        rm $f
        cjb2 -dpi 200 $j.tiff $j.djvu
        rm $j.tiff
        djvm -i book.djvu $j.djvu
        rm $j.djvu
done
#

Si je scanne en PNG, c’est pour la simplicité d’écriture du script. (Je suis fainéant par principe.) On a ainsi trois fichiers de même basename, différents par l’extension.

Le script prend toutes les pages qui s’appellent book*.png. Le script efface les fichiers utilisés (sauf les *.hocr donnant le texte), pour éviter de réintroduire les mêmes pages dans un traitement ultérieur. (On fait autant de pages qu’on veut, pas nécessairement toutes d’un coup.)

En résumé, on crée le livre avec la seule page 1. On scanne ensuite un paquet de pages, selon le temps et le courage qu’on a et on applique le script. On peut aller se coucher et continuer le lendemain. Le livre book.djvu grossit petit à petit.

J’ai longuement chipoté pour arriver à ça. J’ai commencé par scanner en TIFF parce que libtiff fournit la commande tiffdither pour passer en noir et blanc. Je voulais alors, pour redresser la page, utiliser d’Imagemagick les commandes convert ou mogrigy avec option deskew, mais j’obtenais un message d’erreur qu’on ne trouvait pas un entier attendu. Allez savoir ce que ça veut dire ! J’ai essayé Scan Tailor, qui existe aussi en ligne de commande, mais qui me faisait une autre erreur, je ne sais plus laquelle (n’accepte pas TIFF ?). La découverte du programme Deskew a résolu tous mes problèmes.

Deuxième étape, introduire en bonne position dans le DjVu les textes qu’on a en hOCR. Cela se fait les doigts dans le nez avec le script suivant :

#!/bin/bash

for f in book*.hocr
do
        j=`basename $f .hocr`
        cat $f | hocr2djvused > $j.script
        sed -i "1 c\select $j.djvu" $j.script
        djvused -f $j.script -s book.djvu
        echo $j

done
#

J’utilise la commande hocr2djvused, qui produit des scripts de commande pour djvused. Cependant le script venant de hocr2djvused sélectionne toujours la page 1 du DjVu par son numéro. J’utilise donc l’éditeur sed pour changer la première ligne du fichier script en y appelant la page par son nom ou titre et pas par son numéro (et certainement pas toujours numéro 1). Le processus de fabrication ci-dessus du DjVu sans texte fait que les noms des pages sont de la forme book001.djvu, book002.djvu… (Cela peut se vérifier par djvudump book.djvu.) Je demande alors à djvused d’exécuter les commandes du fichier (-f) script sur le fichier book.djvu en le sauvant chaque fois (-s).

Normalement, le programme ocrodjvu devrait prendre le book.djvu dans son état sans texte de la première étape et faire directement toute la deuxième étape mieux que moi. Mais le programme, dans les dépôts Ubuntu, est basé sur un état ancien d’OCRopus. Je lui ai emprunté la commande hocr2djvused pour me débrouiller par moi-même. Cependant on trouve chez Debian le paquet ocrodjvu_0.8-1_all.deb adapté. Il utilise maintenant par défaut Tesseract plutôt qu’OCRopus. La commande

ocrodjvu -o book.djvu -l fra bookimage.djvu

en appelant bookimage le livre sans texte, remplace les commandes tesseract dans la première étape et tout le script de la deuxième étape. Par contre, ma méthode plus manuelle permet de corriger les fichiers *.hocr ou *.script pour les erreurs de reconnaissance. Sinon, il faut utiliser d’autres outils (d’autres commandes de djvused). Ma méthode manuelle fait la reconnaissance sur le scan en gris (avant deskew). La méthode ocrodjvu fait la reconnaissance sur le djvu bitonal. Comparant deux versions d’une même page, je trouve aussi peu de fautes dans les deux cas, mais pas tout à fait les mêmes. J’ai comparé aussi dans ma voie manuelle la reconnaissance avant ou après la réduction de gris en trait. La reconnaissance semble légèrement meilleure en gris. Un avantage important du passage par une version en hOCR est que c’est du HTML — avec un peu de nettoyage, on a une page ordinaire, et du XML ce qui permet une ouverture à d’autres formes d’édition (comme TEI XML). Mais il existe aussi une commande djvu2hocr et la voie directe par ocrodjvu reste une possibilité sérieuse.

Supposons qu’on veuille corriger la page correspondant à 017, par exemple. Si c’est avant l’utilisation du deuxième script ci-dessus, on affiche en DjVu la page de book.djvu. On affiche book017.hocr dans un browser pour y voir les fautes. (On voit aussi tout de suite si la page du livre voulue correspond ou non à l’indice 017.) On ouvre le même book017.hocr dans un éditeur de texte et on y porte les corrections. Si on a déjà passé le script, on édite plutôt le fichier book017.script. Alors par djvused -f book017.script -s book.djvu, djvused va aller retirer l’ancien texte de la page 017 et y mettre le nouveau, corrigé. Le fichier book017.hocr a l’avantage de pouvoir s’afficher dans un browser, mais les indications de position en valeurs d’attributs d’éléments span en font un texte difficile à parcourir. Il est fastidieux d’y corriger beaucoup de fautes, si le document papier original était de particulièrement mauvaise qualité.

Up: Home Previous: Reconnaissance de caractères, Optical Character Recognition (OCR) Next: Scripts