Commit 17eecf48 authored by Roussey Catherine's avatar Roussey Catherine
Browse files

Update README.md

parent 561ed5e2
# Version python de pdf2blocks
## Objectif
## 1 Objectif
L'objectif de ce programme est de reconstruire
la structure logique (titre, sous-titre, paragraphe, ...) d'un document pdf.
......@@ -12,7 +12,7 @@ Ce programme est écrit en python (version 3). Il s’intitule pdf2blocks.py.
Il prend en argument un fichier pdf, contenant du texte, des tableaux
et des images.
## Utilisation
## 2 Utilisation
On l'exécute depuis la ligne de commande :
......@@ -21,7 +21,7 @@ On l'exécute depuis la ligne de commande :
Le résultat est écrit sur la sortie standard. Il est facile de la rediriger
dans un fichier html.
#### Exemple de résultat :
#### 2.1 Exemple de résultat :
<hr />
<header>page 7</header>
......@@ -41,13 +41,13 @@ dans un fichier html.
<h4>Le plus avancé</h4>
<p>fermeture de la grappe (33)</p>
## Dépendances
## 3 Dépendances
*pdf2blocks* utilise actuellement *pdftotext* et *pdftohtml*, deux outils basés
sur la librairie poppler, dérivée de Xpdf. Ces deux outils prennent en entrée
un fichier pdf.
#### pdftotext
#### 3.1 pdftotext
*pdftotext* est destiné à produire une sortie en texte brut,
lisible dans une console texte par exemple.
......@@ -79,7 +79,7 @@ polices de caractères : le nom de la police de caractères,
les styles (gras, italique, ...) et les couleurs du texte ne sont pas
décrits.
#### pdftohtml
#### 3.2 pdftohtml
*pdftohtml* est un outil qui vise à produire une page html qui ressemble
au document pdf. Pour cela, il n'a pas besoin de respecter un ordre
de lecture, car les éléments d'une page html peuvent être localisés.
......@@ -128,8 +128,10 @@ Par exemple, deux lignes situées à la meme hauteur mais dans deux colonnes
successives sont parfois regroupées dans le meme segment de texte.
## L'algorithme de pdf2blocks
### pdftotext
## 4 L'algorithme de pdf2blocks
### 4.1 pdftotext
Le programme *pdf2blocks* commence par lancer la commande suivante :
pdftotext -bbox-layout -eol unix /path/to/file.pdf
......@@ -179,12 +181,12 @@ Les éléments de la liste *blocks* ont donc la structure suivante :
### pdftohtml
### 4.2 pdftohtml
Ensuite, le programme *pdf2blocks* lance la commande *pdftohtml* :
pdftohtml -xml -i -stdout /path/to/file.pdf
#### Les fontes renvoyées par *pdftohtml*
#### 4.2.1 Les fontes renvoyées par *pdftohtml*
Les fontes de caractères renvoyées par *pdftohtml* sont stockées dans une liste
python, nommée **fontspec** (du nom de la balise xml associée).
Les éléments de cette liste sont des dictionnaires python ayant la structure
......@@ -204,7 +206,7 @@ suivante :
- **nb_cars** nombre de caractères qui ont cette fonte. Ce nombre n'est pas présent dans le résultat xml de la commande
*pdftohtml*. Il est calculé lors de l'extraction du texte.
#### Le texte renvoyé par la commande *pdftohtml*
#### 4.2.2 Le texte renvoyé par la commande *pdftohtml*
Les segments de texte renvoyés par *pdftohtml* représentent la plupart du temps
une ligne de texte entière. La liste qui les contient a été nommée **segments**.
Ses éléments, extraits du résultat xml de *pdftohtml*,
......@@ -216,7 +218,7 @@ ont la structure suivante :
- **top**, **left**, **width** et **height** : Les coordonnées du segment de
texte dans la page.
### Traitements
### 4.3 Traitements
À ce point, nous avons trois listes, **blocks**,
**fontspec** et **segments**, dont la structure est décrite ci-dessus.
......@@ -235,13 +237,15 @@ le cas de documents multi-colonnes. Ceci est dû aux limites de *pdftotext*.
Les chapitres suivants décrivent les traitements, effectués séquentiellement,
sur les données issues des deux commandes *pdftotext* et *pdftohtml*.
#### Taille de la fonte par défaut
#### 4.3.1 Détermination de la taille de la fonte par défaut
La fonte la plus utilisée (en nombre de caractères)
est considérée être la fonte par défaut. Elle est déterminée à partir
de la liste **segments** et **fontspec**, c'est à dire les sorties de pdftohtml.
(note CR dans le titre tu dis taille et dans le contenu tu ne parles que de la fonte)
#### Détection des pieds de page
#### 4.3.2 Détection des pieds de page
Les "pieds de page" d’un document sont une zone de texte répétée
à chaque fin de page contenant par exemple le numéro de la page
......@@ -261,7 +265,7 @@ on teste la ligne précédente, et ainsi de suite.
Les lignes détectées comme étant des bas de page ont la valeur BL_BOTTOM_PAGE dans leur attribut class.
#### Détection des en-tête
#### 4.3.3 Détection des en-tête
L'algorithme est similaire à la détection des pieds de page, mais au lieu
de s'appliquer aux dernières lignes de chaque page, il considère les premières
......@@ -276,7 +280,7 @@ et ensuite on teste si il exsite une en tete avec le meme contenu dans la premi
Les lignes détectées comme étant des en tete ont la valeur BL_TOP_PAGE dans leur attribut class.
#### Attribution de fontes aux blocs
#### 4.3.4 Attribution de fontes aux blocs
Il s'agit d'attribuer l'*id* d'une fonte de **fontspec** à chaque ligne
de la liste **blocks**.
......@@ -296,7 +300,7 @@ page est parfois différent entre les deux outils.
tester le principe, qui semble satisfaisant, mais il nécessite d'être
réécrit pour que son exécution soit plus rapide.
#### Réordonnancement des blocs
#### 4.3.5 Réordonnancement des blocs
Avant de reconstituer la structure du document, un réordonnancement des blocs
est effectué, en deux temps :
......@@ -306,7 +310,7 @@ est effectué, en deux temps :
Ceci est effectué page par page.
##### Détection de colonnes
##### 4.3.5.1 Détection de colonnes
La détection de colonnes ne considère que les blocs :
- de plus de 3 lignes
......@@ -342,68 +346,76 @@ En effet, certains blocs peuvent chevaucher plusieurs colonnes (par exemple
des titres). Les deux attributs ont la meme valeur quand le bloc
est entièrement contenu dans une seule colonne.
Avant la numérotation des colonnes pour définir l'ordre de lecture,
on effectue l'opération suivante. Les blocs ayant une fonte plus grande que la fonte par défaut (les titres potentiels)
Hypothèse de travail:
Si une page contient plusieurs colonnes et que un titre chevauche plusieurs colonnes
le sens de lecture sera de lire en premier tous les blocs au dessus du titre sur toutes les colonnes.
Si une page contient plusieurs colonnes et que les titres sont totalement contenu
dans une colonne, le sens de lecture se fera colonne par colonne.
Avant la numérotation des colonnes pour définir le sens de lecture,
on effectue l'opération suivante: Les blocs ayant une fonte plus grande que la fonte par défaut (les titres potentiels)
sont élargis autant que possible vers la droite de la page (accroissement de leur x_max)
jusqu'à rencontrer un autre bloc ou jusqu'au bord de la page.
Note de CR cela n'impacte pas la numerotation des colonnes donc pourquoi dire avant la numeroatation des colonnes?
Cette opération est nécessaire pour définir le sens de lecture correcte quand un titre est trop court pour déborder sur les deux colonnes.
Il devrait éborder sur les deux colonnes mais il est de fait entièrement contenu dans une colonne.
##### Parcours des blocs dans le sens de lecture
##### 4.3.5.2 Parcours des blocs dans le sens de lecture
l'objectif est d'ordonner les blocs d'une meme page dans leur sens de lecture,
c'est à dire de haut en bas et de gauche à droite.
Une nouvelle liste ordonnée L de blocs est créée pour une page donnée.
Les en-têtes sont tout d'abord insérée dans la liste L
Une nouvelle liste ordonnée **blocks_ordonnés** de blocs est créée pour une page donnée.
Les en-têtes sont tout d'abord insérées dans la liste **blocks_ordonnés**
dans l'ordre donné par pdftotext.
Au fur et à mesure que les blocs sont ajoutés dans la liste L, ils sont retirés
des blocs à parcourir. L'algorithme effectue une boucle jusqu'à épuisement
Au fur et à mesure que les blocs sont ajoutés dans la liste **blocks_ordonnés**, ils sont retirés
des blocs à parcourir (stockés dans la liste **blocks**). L'algorithme effectue une boucle jusqu'à épuisement
des blocs à parcourir.
On définit une zone rectangulaire à traiter inclue dans la page. Cette zone est initialisée à la première
colonne.
colonne (la colonne la plus à gauche).
La boucle principale de l'algorithme effectue les tâches suivantes :
- recherche du bloc B1 le plus haut dans la zone ; Ce bloc va définir l'arrete haute de la zone.
- recherche du bloc B1 le plus haut dans la zone ; Ce bloc va définir l'arete haute de la zone.
- si on n'en trouve pas, on élargit la zone vers la droite et on relance
une recherche,
- si on n'en trouve pas et que la zone comprend la dernière colonne,
on élargit la zone (à gauche) à l'ensemble des colonnes.
(note CR vu que la zone est initialisé à la premiere colonne , je comprends que c'est la colonne la plus à gauche donc je ne comprends pas cette etape)
- Le cas où l'on ne trouve pas de bloc et que la zone comprend l'ensemble
des colonnes algorithme se termine.
- parmi tous les blocs dont l'arrete haute est au même niveau que l'arrete haute de B1 (modulo un petit
- parmi tous les blocs dont l'arete haute est au même niveau que l'arete haute de B1 (modulo un petit
intervalle correspondant à la valeur de VERTICAL_ALIGMENT_THRESHOLD), on cherche le bloc le plus à gauche
intitulé B2 ; s'il existe ce sera le premier bloc a étre inséré dans la liste L (le bloc le plus haut et le plus à gauche).
intitulé B2 ; s'il existe ce sera le premier bloc a étre inséré dans la liste **blocks_ordonnés** (le bloc le plus haut et le plus à gauche).
- étant donné B2, trois cas sont considérés :
- Dans le général, B2 est ajouté à L et la zone
- Dans le général, B2 est ajouté à **blocks_ordonnés** et la zone
est ajusté à celui de B2 (pour que les blocs situés dans la même colonne
que B2 soient parcourus avant ceux, plus hauts, de la colonne suivante).
- sauf si il existe un bloc non traité qui commence plus haut dans une colonne
à gauche de la zone à traiter. Ceci se produit quand
un titre centré par exemple (s'il est centré il ne peut pas etre plus à gauche), ou un bloc situé à droite (à côté d'une
un titre centré par exemple (note CR s'il est centré il ne peut pas etre plus à gauche), ou un bloc situé à droite (à côté d'une
photo par exemple) vient d'être ajouté à la liste L.
Dans ce cas, on réinitialise la zone à l'ensemble des
colonnes (ce qui aura pour effet de traiter en priorité les blocs
de gauche).
- sauf si l'arrete droite du bloc B2 est au delà de l'arrete droite de la zone.
- sauf si l'arete droite du bloc B2 est au delà de l'arete droite de la zone.
C'est par exemple le cas d'un titre sur toute la largeur
de la page. Dans ce cas, la zone est agrandit jusqu'à l'arrete droite de B2.
Tous les blocs de la zone situé au dessus de B2 sont inséré dans la liste L avant B2.
Une fois cette boucle terminée, L contient la liste des blocs dans un ordre de
Une fois cette boucle terminée, **blocks_ordonnés** contient la liste des blocs dans un ordre de
lecture estimé convenable.
La liste L est enrichie des blocs marqués comme pieds de page.
La liste **blocks_ordonnés** est enrichie des blocs marqués comme pieds de page.
#### Reconstitution de la structure du document
#### 4.3.6 Reconstitution de la structure du document
Les en-tête et pieds de page ont déjà été identifiés.
Certaines lignes, ne comportant aucun caractère alphanumérique, sont ignorées.
Les lignes, ne comportant aucun caractère alphanumérique, sont ignorées.
L'algorithme de reconstitution de la structure du document se fait en deux
étapes :
......@@ -416,48 +428,45 @@ L'algorithme de reconstitution de la structure du document se fait en deux
Avant de rechercher à reconstituer la structure du document, on calcule
pour chaque bloc :
- un indicateur HAS_BULLET : S'il y a des lignes qui ne commencent pas par
- un booleen HAS_BULLET : S'il existe au moins une ligne du bloc qui ne commence pas par
un caractère alphanumérique.
- un indicateur FLAG_VERTICAL lorsque le bloc contient au moins une ligne
- un booleen FLAG_VERTICAL lorsque le bloc contient au moins une ligne
de plus de 3 caractères plus haute que large,
- *bloc_size* : le nombre de caractères contenus dans le bloc,
- *max_line_size* : la plus grande longueur de ligne,
- *max_line_size* : le plus grand nombre de caractères contenu dans une ligne,
- *not_numbers* : la proportion de caractères non-numériques dans le bloc,
- *last_character* : le dernier caractère du bloc (pour tester la présence
de ponctuation),
- *nb_lines* : le nombre de lignes,
- *font_class* : une caractérisation de la taille de la fonte, parmi
- *nb_lines* : le nombre de lignes contenu dans le bloc,
- *font_class* : une caractérisation de la taille de la fonte du bloc, parmi
les valeurs FONT_TINY, FONT_SMALL, FONT_DEFAULT, FONT_BIG et FONT_HUGE.
Les seuils pour distribuer ces tailles, exprimés en pixels par rapport
à la taille de la fonte par défaut, sont donnés dans le tableau
FONT_THRESHOLDS (actuellement [ -3, -1, 0, 2, 7]).
- *alignment* : une caractérisation de la forme du paragraphe, déterminée
pour les paragraphes de plus de deux lignes :
- ALIGN_JUSTIFIED : si le prargraphe fait au moins 3 lignes et que les
bords gauches et droits sont alignés,
- ALIGN_LEFT : si les bords gauches sont alignés,
- ALIGN_RIGHT : si les bords droits sont alignés,
- ALIGN_CENTERED : si les milieux de ligne sont alignés,
- *alignment* : une caractérisation de la forme du bloc, déterminée
pour les blocs de plus de deux lignes. Cet attribut contient l'une des valeurs suivantes :
- ALIGN_JUSTIFIED : si le bloc fait au moins 3 lignes et que les
aretes gauches et aretes droites des lignes sont alignés,
- ALIGN_LEFT : si les aretes gauches des lignes sont alignés,
- ALIGN_RIGHT : si les aretes droites des lignes sont alignés,
- ALIGN_CENTERED : si les milieux de lignes sont alignés,
- ALIGN_UNDEF dans tous les autres cas.
- (CR est ce que ce sont des valeurs exclusives si oui mettre une phrases indiquant alignement ne peut pas prendre qu'une)
L'alignement des blocs s'entend modulo une constante exprimée en pixels
et nommée VERTICAL_ALIGMENT_THRESHOLD.
##### 1. Recherche de caractéristiques génériques
##### 4.3.6.1 Recherche de caractéristiques génériques
La caractérisation d'un bloc s'appuie sur une série de règles. Lorsqu'un bloc
correspond à une des règles, on lui attribue une "classe" (titre, légende,
paragraphe, tableau, ...). On dira que le bloc est "marqué".
La liste des règles est ordonnée. Lorsqu'une une règle permet de marquer
La liste des règles est ordonnée. Lorsqu'une règle permet de marquer
un bloc, les règles suivantes ne sont pas testées sur ce bloc.
Lorsqu'un bloc est marqué, ses caractéristiques sont "stockées", c'est-à dire
qu'elles sont utilisées pour déterminer un "prototype"
de la classe attribuée au bloc. Ce prototypage est décrit au chapitre suivant.
Pour certaines règles, ce stockage n'est pas effectué, ce qui sera signalé
dans la description de la règle.
Certaines regles permettent de définir des prototypes. C'est à dire
Voici la liste des règles de détermination des classes qui sont appliquées :
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment