L'économe d'Ockham

faire le vide en côtoyant le néant

lundi 6 avril 2026

Créer une carte de zonage interactive

Si vous cherchez à mieux comprendre le règlement d’urbanisme de votre ville, il est très utile d’avoir une carte interactive qui permet de faire la correspondance entre adresses ou quartiers et zones. Des grandes villes, qui ont de l’expertise interne en géomatique et des abonnements coûteux à ArcGIS, publient souvent ce genre de carte sur leur site web, par exemple Laval, Montréal ou Sherbrooke. Des petites villes… pas tant que ça!

URBANISME

C’est pour ça que, quand j’ai été élu au conseil à Sainte-Adèle, j’ai créé ZONALDA, une carte de zonage interactive simple, gratuite et libre. Cet article est la première d’une série qui détaille la conception et l’implémentation d’une telle carte, en commençant par la base - c’est à dire, la base de données géomatique, qui contient les formes et emplacements de toutes les zones ainsi que leurs identificateurs et attributs.

Obtenir un plan de zonage

Idéalement, à défaut d’une carte interactive, votre ville ou MRC publie la géomatique du plan de zonage sur Données Québec (voici celle de Repentigny par exemple) mais généralement ce n’est pas le cas. Par contre, les villes publient presque toujours une carte de zonage sur leur sites web, la plupart du temps en format PDF, plus souvent dans la section des règlements d’urbanisme. On la trouve sous le rubrique Règlements - Urbanisme à Sainte-Adèle, sur la page Règlementation et Permis à Morin-Heights, et sur la page générale de réglementation municipale à Saint-Calixte.

Afin d’en obtenir la géomatique sous-jacente (habituellement sous forme d’un Shapefile) vous pouvez aussi essayer de faire une demande d’accès à l’information. Pour les petites villes, c’est généralement à la MRC qui il faut s’adresser - c’est la raison qu’on voit «Source: MRC des Pays d’en Haut» sur les plans de zonage de Sainte-Adèle et Morin-Heights.

Finalement, on peut aussi utiliser la carte publique pour reconstruire manuellement la géomatique des zones. Pour ce faire, on utilisera le logiciel libre QGIS, accompagné par GIMP et InkScape et assaisonné avec un peu de jus de bras.

Cas facile: Morin-Heights

Il faut d’abord savoir qu’un PDF n’est pas une seul et unique sorte de fichier, et il est nécessaire de savoir d’abord à quelle sorte de PDF vous avez affaire. Le plan de zonage de Morin-Heights est un très bon PDF parce qu’il est vectoriel et géoréférencé.

Comment le savoir? D’abord, on ouvre QGIS et on ajoute une carte de base OpenStreetMap. Maintenant, il faut simplement essayer d’ajouter le PDF comme couche vectorielle dans QGIS:

Ajouter une couche vecteur à QGIS

On voit que cette opération nous réussit à ajouter plusieurs couches vecteur et, même si les zones ne sont pas ajoutées comme polygones, les limites des zones sont présentes comme lignes et placées correctement sur la carte:

Un très bon fichier PDF

Dans ce cas-ci, il ne nous reste qu’à tracer les limites de chaque zone avec les options «accrochage» et «traçage» des outils de numérisation. On va aussi importer la carte comme couche matricielle (raster) pour être capable de voir les identificateurs de zone. Donc, il faut importer le PDF une deuxième fois, cette fois comme «raster»:

Ajouter une couche raster à QGIS

On est prêt à créer la géomatique des zones! Pour ce faire:

  1. Mettre la carte raster en-dessous des vecteurs dans la liste de couches.
  2. Créer une nouvelle couche temporaire en mémoire, avec une géométrie de polygone et un SCN de EPSG:4326 - WGS-84. Ajouter un champ “zone” de type texte aussi. Maintenant, cliquer avec le bouton droit sur la nouvelle couche et sélectionnez «Convertir en couche permanente», puis sauvegardez-la en GeoJSON.
  3. Activer la barre d’outils «accrochage» et sélectionner le bouton «trace» dans la barre. Très important: la fonction «trace» n’est pas toujours capable de prendre en charge plusieurs couches à la fois. Il faut donc aussi selectionner «Configuration avancée» dans le menu à droite de l’aimant, puis cocher seulement Layers_ZONAGE_2022_PG dans le menu sous l’œil qui apparaît à côté:
    Options d'accrochage QGIS
  4. Maintenant vous pouvez utiliser l’outil «Ajouter une entité polygonale» et cliquer avec le bouton gauche en suivant le contour d’une zone. L’accrochage fera en sorte que les points seront placés sur les limites de la zone, et la trace suivra les courbes et autres détails. Si vous faites une erreur, utilisez la touche «backspace» pour enlever le dernier point. Une fois rendu au point de départ, fermer le polygone avec le bouton à droite. Dans le dialogue, entrez l’identificateur de la zone tel qu’indiqué dans la carte raster:
    Créer une zone
  5. Pendant que vous tracez, vous pouvez effacer le dernier point avec la touche «Backspace», annuler la figure avec «Esc», ou bouger la carte en tenant la barre d’espace en bougeant la souris. Pour désactiver ou réactiver la trace pésez sur «T», et pour désactiver ou réactiver l’accrochage, la touche «S».
  6. N’oubliez pas de sauvegarder votre travail de temps en temps!

Après une demi-heure environ de traçage, vous aurez une couche vectorielle avec des polygones pour toutes les zones de Morin-Heights, et vous aurez aussi un fichier GeoJSON que vous pouvez visualiser avec uMap:

Cas plus difficile: Sainte-Adèle

Ce n’est pas toutes les villes qui produisent (ou demandent à leur MRC de produire) des fichiers PDF aussi futés. Ça se peut que vous aurez un PDF qui est tout simplement une image matricielle, qui ne contient que des pixels. Donc, QGIS va refuser de l’importer comme couche vecteur:

Erreur lorsqu'on ajoute un PDF matriciel

Pire encore, cette image peut aussi ne pas être géoréférencée. Donc, si vous l’importez comme raster, elle finira quelque part dans l’océan, ou dans les montagnes de l’Équateur, tout dépendant de votre SCN:

PDF matriciel dans les An(d)es

Sainte-Adèle figure malheureusement parmi ces villes moins douées en géomatique. Qui plus est, elle publie aussi deux cartes séparées de zonage, une pour la ville au complet et une autre plus détaillée pour le périmètre urbain. Mais tout n’est pas perdu! QGIS est très capable de faire quelque chose avec ce genre de PDF, avec un peu plus de travail.

D’abord, on n’ajoutera pas directement ces fichiers dans QGIS comme couche raster, car ils ne sont pas géoréférencés, mais aussi parce que QGIS par défaut va réduire la résolution de l’image qui les rend pas très lisibles. C’est très courant pour des cartes en PDF d’être composées d’une seule image matricielle, donc, on va extraire ces images avec PLAYA-PDF:

playa --images tout Plan-de-zonage-Tout-En-vigueur-20250716.pdf > tout.json
playa --images zoom Plan-de-zonage-Zoom-En-vigueur-20250716.pdf > zoom.json

En effet, si on regarde les fichiers tout.json et zoom.json on constate qu’il y a bel et bien une seule et très grande image dans chaque fichier (tout et zoom). Étant donné qu’on aura besoin de les géoréférencer de toute façon, on va d’abord ouvrir ces images avec GIMP pour les découper un peu:

  1. Ouvrir les images .jpg avec GIMP
  2. Découper l’image juste au-delà des limites de la ville, ou aux limites de la carte pour le plan plus détaillé
  3. Ajouter un canal alpha (Calque → Transparence → Ajouter un canal alpha)
  4. Exporter l’image en PNG (ou TIFF, peu importe…)

Ça nous donne tout.png et zoom.png. Par la suite on va les incorporer dans QGIS avec la fênêtre «Géoréférencer…» (dans le menu «Couche»). Mais, pour faire ceci, ça nous prend des points de référence fiable, comme les limites de la ville. Très important: N’utilisez jamais les limites administratives dans OpenStreetMap, elles sont incorrectes! On va alors télécharger les données ouvertes des découpages administratifs du Québec. Pour rendre ça plus rapide, on n’a qu’à sélectionner l’objet munic_s:

Ajouter les limites des villes

Il est sûrement possible de demander simplement la limite d’une seule ville avec le serveur REST, mais je n’ai pas réussi à en trouver la documentation…

On peut maintenant géoréférencer la carte complète de la ville par rapport aux limites administratives:

  1. Ouvrir le géoréférenceur et ouvrir tout.png comme raster (Ctrl+O ou Fichier → Ouvrir un raster…)
  2. Selectionner l’outil «Ajouter un point de contrôle» et placer un point à un point sur le contour de la ville, puis selectionner «Depuis le canevas de la carte…»
  3. Identifier le point correspondant sur les limites administratives. En activant l’accrochage (icône en forme d’aimant) sur cette couche spécifique on peut avoir un peu plus de précision.
  4. Le coin Sud-Est de la ville ne correspond pas exactement, alors il vaut mieux ne pas l’utiliser. Ces 5 points suffisent:
    Points de contrôle
  5. Modifier les paramètres de transformation pour utiliser «Polynomiale 1» et «Cubic» et définir le nom du fichier en sortie, puis débuter le géoréférencement.
  6. En superposant de nouveau la couche des limites administratives, on confirme qu’on a un très bon alignement:
    Nouvelle couche géoréférencée

Pour la carte d’agrandissement, on fera un processus semblable, sauf que les limites de l’agrandissement ne sont pas exactes, donc il vaut mieux définir des points de contrôle sur les points saillants des zones, au lieu des limites de la carte:

Points de contrôle

Après le géoréférencement, on peut réduire l’opacité de la nouvelle couche pour confirmer que les zones sont bien alignées, bien qu’il y ait un petit écart sur le haut de l’agrandissement:

Nouvelle couche géoréférencée

Ça nous fais une très belle carte, mais… il faut quand même tracer les zones. Pour celles qui sont plutôt rectiligne, et collées sur les limites de la ville, ce n’est pas trop difficile, mais plusieurs ont des formes très complexes. Il serait donc très utile de pouvoir extraire au moins quelque chose de vectoriel sur lequel on pourait accrocher pour faciliter le traçage.

Auto-traçage et géoréférencement

Pour obtenir une couche vectorielle qui nous aidera à guider le traçage, on peut ouvrir nos fichiers PNG avec InkScape, puis sélectionner «Chemin → Vectoriser un objet matriciel…». Pour l’agrandissement, des paramètres comme ceux-ci fonctionnent:

Paramètres InkScape

On peut masquer (ou carrément supprimer) l’image matricielle de base pour voir que ça nous donne déjà quelque chose un peu plus potable:

Traçage des zones avec InkScape

Après avoir detecté les lignes, il faut sauvegarder le projet en format DXF (pourquoi ce format? seul QGIS le sait…) et par la suite refaire le géoréférencement, mais en ajoutant les objets dans ce fichier comme vecteur:

Géoréférencer un DXF

La principale difficulté à tracer en utilisant ces vecteurs, c’est que parce que les lignes dans l’image originale sont épaisses, on se retrouve avec deux traces pour chaque ligne. Il faut aussi faire attention aux flèches et textes qui se font aussi tracer (la touche «T» est très utile).

Tracer le DXF

En fin de compte, ça nous permet d’avoir des pas pires resultats, mais ça prend du temps:

Par la suite, nous allons regarder comment géolocaliser des adresses pour les situer dans une zone, et comment réparer la base géomatique au cas où des géométries invalides empêchent ceci de fonctionner. QGIS est muni des «outils de numérisation avancés» qui permettent de nettoyer les données qu’on aura créées en traçant.

Il est aussi possible d’améliorer l’extraction de figures en détectant automatiquement les étiquettes textuelles des zones et les enlever de la figure… on regardera ça dans un deuxième temps!

mercredi 25 février 2026

Je vous présente PLAYA-PDF (et PAVÉS)

Si vous voulez fouiller dans les entrailles d’un document PDF pour en extraire des metadonnées, des images, et même du texte, j’ai des superbes logiciels libres pour vous: PLAYA-PDF et PAVÉS. Si vous voulez savoir comment je suis arrivé là, continuez à lire. Et si vous avez besoin d’un consultant pour vos besoins d’intelligence documentaire je suis bien sûr disponible pour des contrats de toute sorte!

Une jeune fille étourdie par un brouillard de papiers arborant le logo PDF

«Vous n’êtes qu’un paquet d’objets indirects!»

Comme vous savez peut-être (ou pas), je suis chercheur en linguistique informatique de formation et de métier. En 2021, fraîchement élu conseiller municipal dans une ville du grand St-Jérôme que je ne nommerai pas, j’ai quitté mon poste de scientifique principal chez une compagnie (que je ne nommerai pas non plus), maintenant division de Microsoft, car il était impossible pour moi de servir deux maîtres travailler à temps plein à Montréal tout étant un élu efficace et à l’écoute. La chose municipale me semblait aussi, à l’époque, bien plus intéressante que le raffinement des modèles d’apprentissage automatique pour la compréhension du langage naturel.

Entre-temps, il s’est passé des choses…

Un effet secondaire de ce changement de carrière plus ou moins bien avisé est que je suis devenu (en tout humilité) expert en analyse et manipulation des fichiers PDF, et ce, de la manière habituelle des informaticiens de mon genre: j’ai parti un projet de logiciel libre.

Pourquoi?

Lorsqu’on regarde les défis de gestion des documents dans une ville ou autre organisme, on se rend très vite compte que malgré les grands efforts des promoteurs de ODP, OOXML, HTML et autres formats universels, en fin de compte, le PDF, c’est la lingua franca de tous les échanges documentaires. C’est la triste conséquence de la domination du bureaucratique par nul autre que Microsoft, dont les logiciels font exprès de multiplier les incompatibilités non seulement avec d’autres produits (libres ou pas), mais ne sont souvent même pas compatibles entre eux-mêmes.

Comment?

J’avais des critères pour l’outil que je voulais utiliser, qui ne correspondaient pas à l’état actuel des logiciels disponibles:

  1. Licence libre et permissive (du genre BSD, MIT).
  2. Écrit en Python et portable entre différentes plateformes.
  3. Interface conviviale pour le programmeur.
  4. Accès direct aux structures interne du PDF, avec la capacité d’extraire non seulement du texte mais les éléments de mise en page et les metadonnées.
  5. Rapide et efficiente, autant que possible (c’est un peu en conflit avec #2 mais bon).

Le logiciel qui se rapproche le plus de ces critères à l’époque était pdfplumber, un très bon logithèque qui satisfait néanmoins aux critères 1, 2 et 3! J’y ai même contribué un module pour l’extraction des arborescences de structure logique. Par contre, l’efficacité n’est pas trop au rendez-vous, surtout parce que pdfplumber, comme d’autres projets populaires dont sa logithèque sous-jacente pdfminer.six, doit analyser chaque page au complet et construire toutes les structures de données avant de retourner des informations demandées.

De paresse et de parallélisme

C’est surtout ça l’innovation de PLAYA-PDF: il est «paresseux», ne traitant que les informations nécessaires pour extraire l’information que vous désirez. Si vous, par contre, vous êtes paresseux·se, il possède aussi un interface qui peut convertir les metadonnées d’un PDF en JSON, et ce, très rapidement:

with playa.open(path) as pdf:
    json.dumps(playa.asobj(pdf))

L’autre élément clé, PLAYA-PDF prend en charge plusieurs cœurs de processeur en parallèle, et ce, de manière très conviviale:

with playa.open(path, max_workers=4) as pdf:
    texts = list(pdf.pages.map(playa.Page.extract_text))

Par-dessus la PLAYA, les PAVÉS!

Parce que les objectifs de PLAYA-PDF sont surtout l’efficacité et l’absence de dépendances sur d’autres logiciels, il ne prend pas en charge des tâches de plus haut niveau, nécessitant de l’imagerie, des heuristiques ou des modèles d’apprentissage automatique.

Pour cette raison je suis aussi en train de construire PAVÉS qui prendra de plus en plus en charge:

  • L’analyse structurelle et textuelle des PDF, dont le traitement des tableaux et l’extraction d’unités logiques de texte.
  • La visualisation des objets dans un PDF ainsi que la conversion des pages en images.

Ce deuxième logithèque est encore en chantier mais sert déjà à faire l’analyse nécessaire pour alimenter mes projets tels que ZONALDA et SÈRAFIM.

Conclusion

Si vous faites partie du petit nombre de gens auxquels ça intéresse je vous invite à l’essayer! J’ai publié entre autres de la documentation et quelques carnets Jupyter qui démontrent la fonctionnalité.

Vous pouvez bien sûr aussi contribuer au développement sur GitHub (notez qu’il se peut que je le déplace bientôt vers Codeberg ou autre hébergement indépendant et au-dehors des États-Unis, mais il restera toujours disponible sur GitHub).

mardi 14 janvier 2025

Analyse Mise en Page 2

TL;DR: Vous pouvez utiliser docling directement car ses modèles sont les plus fiables et efficaces de ceux que j’ai testés. Mais pour comprendre comment ça fonctionne, continuez à lire!

Nous allons voir ici comment utiliser des modèles de vision computationelle pour faire de l’analyse de mise en page d’un PDF et en extraire les titres de sections, alinéas, listes, et tableaux. Pour ce faire, on fera appel à la logithèque libre Transformers qui facilite beaucoup le téléchargement et utilisation de ces modèles en Python. On prendra d’abord un document très simple d’une seule page, fait sur mesure pour ce genre d’analyse. Ceci nous permettra plus tard (dans un autre texte) de mettre en lumière des défaillances de certains modèles.

Dépendances

D’abord installons des dépendances nécessaires:

pip install pillow playa-pdf timm torch torchvision transformers \
    --extra-index-url https://download.pytorch.org/whl/cpu

On utilisera pillow pour manipuler et annoter des images des pages, playa-pdf pour extraire des metadonnées des PDFs, et le reste sont des nécessaires pour rouler les modèles de vision. On les installe ici en mode CPU pour éviter de télécharger des gigaoctets de n’importe quoi que nous impose NVidia, mais si vous avez un GPU pris en charge (même un petit GT1030 suffit) vous pouvez enlever le --extra-index-url.

Il faut dire tout de suite que les programmeurs de NVidia non seulement génèrent des logiciels obèses mais aussi peu fiables, alors, sous Ubuntu, il faut aussi gosser quelques affaires pour éviter d’être pris avec un fâchant problème de C++ (en réalité, c’est C++ le vrai problème, comme d’habitude):

sudo apt install gcc-10 g++-10
export CC=gcc-10
export CXX=g++-10

Traîtement des PDF en image

Si on veut faire de la vision, bon, ça prend des images matricielles. Pour le moment, on utilisera le bon vieux outil Poppler qui est installé partout sous GNU/Linux (et beaucoup moins ailleurs, désolé) pour convertir des PDF en images de pages.

Ce qu’il faut comprendre avec des modèles d’apprentissage automatique (et que les auteurs de certains logithèques populaires semblent ignorer) c’est que, lorsque possible, ces modèles sont plus performants lorsque les données qu’on leur demande de traiter ressemblent à celles sur lesquelles ils sont entraînés. Puisque tous les modèles d’analyse de mise en page sont entraînés sur DocLayNet, qui est composé d’images de page en format carré avec anticrénelage, et puisque PDF est un format vectoriel qui nous permet de générer des images de n’importe quelle taille et format, il est préférable de créer d’abord des images dans le format attendu.

D’ailleurs il ne sert à rien de créer des images de plus haute résolution que celle prise en charge par le modèle! C’est tout simplement du gaspillage d’énergie, de temps et de stockage (ou, autrement dit, un crime contre le climat et l’économie) puisqu’il faudra rééchantilloner par la suite ces images. Heureusement les bons modèles comme ceux de Docling nous diront leur format préféré.

Alors, on va construire une simple fonction pour nous donner des images du format souhaité, en utilisant les arguments -scale-to-x et -scale-to-y de Poppler:

import subprocess
import tempfile
from pathlib import Path
from typing import Iterator
from PIL import Image

def popple(path: Path, width: int, height: int) -> Iterator[Image.Image]:
    with tempfile.TemporaryDirectory() as tempdir:
        temppath = Path(tempdir)
        subprocess.run(
            [
                "pdftoppm",
                "-scale-to-x",
                str(width),
                "-scale-to-y",
                str(height),
                str(path),
                temppath / "ppm",
            ],
            check=True,
        )
        for ppm in sorted(temppath.iterdir()):
            yield Image.open(ppm)

Reconnaissance des éléments de mise en page

On utilisera un modèle RT-DETR pour identifier les éléments dans les images. Pour des raisons inconnues, le groupe Docling n’a pas mis son modèle dans un endroit standard, alors on ne peut malheureusement pas utiliser AutoModel.from_pretrained. Ce n’est pas grave, on va tout simplement télécharger les fichiers manuellement:

from huggingface_hub import hf_hub_download
processor_config_path = hf_hub_download(
    "ds4sd/docling-models",
    "model_artifacts/layout/preprocessor_config.json"
)
config_path = hf_hub_download("ds4sd/docling-models",
    "model_artifacts/layout/config.json")
weights_path = hf_hub_download("ds4sd/docling-models",
    "model_artifacts/layout/model.safetensors")

Pour la suite on va créer deux objets, un RTDetrImageProcessorFast et un RTDetrForObjectDetection:

import os
processor = RTDetrImageProcessorFast.from_json_file(processor_config_path)
model = RTDetrForObjectDetection.from_pretrained(os.path.dirname(config_path))

Maintenant on peut savoir le format attendu par le modèle:

width = processor.size["width"]
height = processor.size["height"]

Et les noms des éléments qu’il peut extraire (mais lisez plus loin…):

id2label = model.config.id2label

On va télécharger le document:

import requests
r = requests.get("https://ecolingui.ca/pdf_structure.pdf")
r.raise_for_status()
with open("pdf_structure.pdf", "wb") as fh:
    fh.write(r.data)

Et hop, utiliser le modèle est très simple:

import torch
with torch.inference_mode():
    for image in popple("pdf_structure.pdf"):
        inputs = processor(images=image, return_tensors="pt")
        outputs = model(**inputs)

Ces outputs ne sont pas dans un format super intéressant, alors on va utiliser le RTDetrImageProcessorFast pour avoir des coordonnées qui correspondent à l’image:

img_results = processor.post_process_object_detection(
    outputs,
    target_sizes=[(image.height, image.width)],
)[0]
print(img_results)

Ceci nous donne quelque chose plus intéressant, qu’on peut interpréter en utilisant le id2label mentionné ci-haut (notez qu’il faut extraire les valeurs des tensor qui nous retourne le modèle):

Mais oups! Les classifications sont un peu suspects, car il n’existe aucune image (Picture) dans notre document! Bon, il semble que les développeurs de DocLing se sont trompés un peu et il faut ajouter 1 aux indices des classes:

for score, label, box in zip(
    img_results["scores"], img_results["labels"], img_results["boxes"]
):
    label = id2label[label.item() + 1]
    box = [round(x) for x in box.tolist()]
    score = score.item()
    print(f"Élément: {label} à {box} avec confiance {score}")

Ce qui nous donne quelque chose d’intéressant:

Élément: Text à [59, 138, 575, 197] avec confiance 0.9866001009941101
Élément: List-item à [78, 309, 571, 369] avec confiance 0.9816325902938843
Élément: List-item à [97, 290, 234, 300] avec confiance 0.9407719969749451
Élément: List-item à [78, 271, 171, 279] avec confiance 0.9286511540412903
Élément: Table à [58, 400, 581, 438] avec confiance 0.9260659217834473
Élément: List-item à [78, 252, 170, 261] avec confiance 0.925058901309967
Élément: Section-header à [59, 216, 109, 226] avec confiance 0.9144930243492126
Élément: Section-header à [59, 384, 113, 393] avec confiance 0.9069509506225586
Élément: Section-header à [59, 98, 115, 109] avec confiance 0.8970564603805542
Élément: Section-header à [192, 59, 447, 76] avec confiance 0.8865164518356323
Élément: Text à [59, 119, 224, 128] avec confiance 0.8446756601333618
Élément: Text à [59, 235, 157, 242] avec confiance 0.8046810626983643
Élément: Section-header à [59, 235, 157, 242] avec confiance 0.5821080803871155
Élément: Section-header à [59, 119, 224, 128] avec confiance 0.5068144202232361

On peut vérifier que tout a été bien identifié en utilisant ImageDraw:

from PIL import ImageDraw
draw = ImageDraw.Draw(image)
for label, box in zip(img_results["labels"], img_results["boxes"]):
    label = id2label[label.item() + 1]
    box = [round(x) for x in box.tolist()]
    draw.rectangle(box, outline="red")
    draw.text((box[0], max(0, box[1] - 12)), label, fill="red")
image.save("pdf_structure.png")

Et voilà:

Analyse de mise en page

Mais attend, cette image a un aspect un peu bizarre! Si on veut vraiment utiliser les coordonnées, il faut plutôt les transformer pour correspondre à la page originelle. On peut le faire facilement en cherchant les informations avec PLAYA-PDF:

import playa
with playa.open("pdf_structure.pdf") as pdf:
    page = pdf.pages[0]
    page_results = processor.post_process_object_detection(
        outputs,
        target_sizes=[(page.height, page.width)],
    )[0]
    print(page_results)

Conclusion

Nous avons vu comment utiliser un modèle de vision pour identifier les éléments de mise en page dans un PDF. Pour la suite des choses, on regardera comment trouver les textes qui correspondent à ces éléments.

Comme mentionné dans le dernier billet de ce blogue, il existe d’autres modèles de vision qui fonctionnent essentiellement de la même manière, mais qui sont en général beaucoup moins rapides et fiables. Un prochain texte va en faire la comparaison.