Ressources numériques en sciences humaines et sociales OpenEdition Nos plateformes OpenEdition Books OpenEdition Journals Hypothèses Calenda Bibliothèques OpenEdition Freemium Suivez-nous

Annotation GéoIA

Dans ce billet, nous allons nous intéresser à l’annotation de données sous QGIS vis-à-vis d’autres outils plus classiques en IA comme Label Studio ou LabelMe, en nous intéressant à l’objet parking.

L’annotation de données sous QGIS peut être considérée comme une variante très proche, finalement, voire même équivalente, de la digitalisation de données (au sens où peuvent l’entendre les dessinateurs classiques).

Sur un outil carto, les finalités de la digitalisation et de l’annotation sont assez différentes : pour l’une, le porter-à-connaissance, l’observation et l’analyse du territoire, pour l’autre l’entraînement d’IA, mais la technique demeure assez similaire.

Une différence notable entre les deux concerne le contenu de la tâche : tandis que la digitalisation de données cartographiques concerne en général, dans un même continuum, soit une diversité d’objets : des routes, des infrastructures, des bâtiments, soit une diversité d’attributs, comme des niveaux de caractérisation (par exemple pour l’occupation du sol), l’annotation IA, elle, se concentre en général sur un objet bien précis qu’on vise à détecter sur des images, que l’on saisira à la chaîne, si nécessaire en le déclinant sur un nombre limité de classes, ce qui confère à l’opération un caractère moins esthétique et gratifiant, plus répétitif et monotone.

Le séquençage d’opérations pour l’annotations sous QGIS se différencie d’outils comme Label Studio ou LabelMe sur plusieurs points.

Label Studio

Les logiciels classiques d’annotation IA fonctionnent image par image, en général non géoréférencées, bien que cela n’empêche nullement d’utiliser des jpeg ou encore des png auxquels associer des world files (que QGIS peut d’ailleurs générer lors d’atlas), respectivement jpw et pngw.

Sous Label Studio, on crée un projet, par exemple Parkings :

Il faut préciser quelle interface d’annotation utiliser, ici segmentation par polygones.

Il faudra ensuite définir les classes d’objet. Pour cela, un petit état de l’art s’impose.

Standards de données et configuration de l’annotation

Nous nous intéresserons à la forme du stationnement.

Pour l’état de l’art, on peut regarder :

  • les schémas de données liés au stationnement ;
  • les données existantes sur le sujet.

Concernant les schémas de données, nous pouvons aller sur :

  • schema.data.gouv.fr;
  • le wiki d’OSM.

Sur schema.data.gouv.fr, il existe un schéma associé aux emprises de stationnement :

https://schema.data.gouv.fr/macaron-ai/onstreet-parking-schema

Le schéma définit les champs suivants :

🙁Nous ne voyons pas de champ sur la forme de stationnement.

Par contre, nous voyons un champ places calculées. Or, le calcul du nombre de places dépend de la forme du stationnement, en plus de ses dimensions en largeur et longueur.

En effet, un rangement en bataille comporte plus de places qu’un rangement en épi sur la même surface.

Il est important de connaître la forme du stationnement pour déduire le nombre de places

Il est dommage que ce champ Forme n’apparaisse pas dans le schéma. Mais il est toujours possible de faire une proposition pour améliorer le standard !

En revanche, nous trouvons l’information de la forme de stationnement sur le Wiki d’OpenStreetMap

https://wiki.openstreetmap.org/wiki/FR:Street_parking

OSM peut être d’une aide très précieuse, à la fois pour récupérer des données d’annotation, mais aussi pour accéder à des standards folksonomiques très complets.

Nous trouvons la même modélisation pour la donnée d’emprises de stationnement de la Ville de Paris :

Revenons-en à notre annotation sous Label Studio.

Nous définissons nos classes de cette façon :

On importe les images et on commence à saisir les données.

Concernant la saisie proprement dite, on choisit le libellé, puis on dessine.

A noter qu’on peut utiliser un raccourci clavier pour chaque classe, 1 pour bataille, 2 pour épi et 3 pour longitudinal.

Aussi, le combinaison Ctrl+Enter permet de soumettre l’annotation, et de passer à l’image suivante.

Les raccourcis clavier permettent d’être beaucoup plus rapide et sollicitent moins les articulations que la souris.

On voit que le processus est différent sous Label Studio par rapport à QGIS, car sous QGIS, on dessine l’objet, puis on le classe (logique pour un logiciel de carto).

On peut noter que Label Studio ne permet donc pas de procéder en deux phases, à savoir :

  • Une tâche graphique consistant à dessiner les objets, qui pourrait être confiée à un dessinateur expert ;
  • Une tâche sémantique consistant à classer chaque objet selon sa catégorie, qui pourrait dans le cas présent être confiée à n’importe qui.

De ce point de vue, QGIS autorise une certaine souplesse et une organisation du travail que ne permet pas Label Studio (séparation du dessin et de la sémantisation).

A noter qu’on pourrait très bien alimenter Label Studio pour la tâche de caractérisation sémantique à partir des produits de QGIS.

Cela aurait un intérêt afin de profiter de l’interface de labellisation de Label Studio mais cela demande en revanche de l’ingénierie de la donnée pour exporter, réaffecter les classes à la géodonnée d’origine. L’intérêt est selon moi assez faible.

Il vaut mieux essayer de faire de QGIS une station d’annotation performante, ce que nous approfondirons par la suite, d’autant plus que si vous amenez des collègues à contribuer, cela peut être le prétexte à une mini-formation QGIS 😉.

Label Studio est néanmoins un excellent outil d’annotation. Il permet d’annoter collaborativement grâce son accès web, de suivre facilement l’état d’avancement du projet d’annotation, et d’identifier l’auteur.e de chacune.

QGIS permet néanmoins de s’en approcher par l’utilisation de bases de données type PostgreSQL, de vues ou de Virtual Layers, ce que nous verrons dans un prochain billet.

Voici comment exporter les annotations sous Label Studio :

Par souci de commodité, j’ai choisi de limiter l’annotation à un objet surfacique.

Voici le résultat.

[
    {
        "id": 36,
        "annotations": [
            {
                "id": 30,
                "completed_by": 1,
                "result": [
                    {
                        "original_width": 981,
                        "original_height": 822,
                        "image_rotation": 0,
                        "value": {
                            "points": [
                                [
                                    50.67154310273576,
                                    42.736486486486484
                                ],
                                [
                                    27.88350276882387,
                                    71.62162162162163
                                ],
                                [
                                    26.32655591371188,
                                    84.7972972972973
                                ],
                                [
                                    27.034259029671876,
                                    86.82432432432432
                                ],
                                [
                                    35.243615174807836,
                                    81.25
                                ],
                                [
                                    36.65902140672783,
                                    73.1418918918919
                                ],
                                [
                                    59.588602363831725,
                                    43.41216216216216
                                ]
                            ],
                            "closed": true,
                            "polygonlabels": [
                                "épi"
                            ]
                        },
                        "id": "r1KkcNC-WY",
                        "from_name": "label",
                        "to_name": "image",
                        "type": "polygonlabels",
                        "origin": "manual"
                    }
                ],
                "was_cancelled": false,
                "ground_truth": false,
                "created_at": "2025-08-18T06:22:54.603031Z",
                "updated_at": "2025-08-18T06:36:13.453192Z",
                "draft_created_at": "2025-08-18T06:20:50.017499Z",
                "lead_time": 937.94,
                "prediction": {},
                "result_count": 1,
                "unique_id": "47da71f6-5e78-4b57-a4a6-21c8acb2bf46",
                "import_id": null,
                "last_action": null,
                "bulk_created": false,
                "task": 36,
                "project": 20,
                "updated_by": 1,
                "parent_prediction": null,
                "parent_annotation": null,
                "last_created_by": null
            }
        ],
        "file_upload": "bcc78a2c-01.jpeg",
        "drafts": [],
        "predictions": [],
        "data": {
            "image": "\/data\/upload\/20\/bcc78a2c-01.jpeg"
        },
        "meta": {},
        "created_at": "2025-08-18T06:16:25.727527Z",
        "updated_at": "2025-08-18T06:36:13.522814Z",
        "inner_id": 1,
        "total_annotations": 1,
        "cancelled_annotations": 0,
        "total_predictions": 0,
        "comment_count": 0,
        "unresolved_comment_count": 0,
        "last_comment_updated_at": null,
        "project": 20,
        "updated_by": 1,
        "comment_authors": []
    }
]

points comprend les coordonnées de chaque point du polygone. Cependant, il s’agit de coordonnées relatives aux dimensions de l’image, et non de coordonnées géographiques.

Les données annotées sont à des formats JSON, ou XML, non natifs pour les SIG si bien que pour les intégrer à ces derniers, il sera nécessaire de réaliser quelques transformations, et de créer quelques scripts.

LabelMe

Sur LabelMe, le processus est un peu différent, et plus proche de QGIS.

On saisit un objet, puis on renseigne sa classe.

Les classes s’alimentent au fur et à mesure qu’on progresse dans l’annotation.

Finalement, ce comportement peut être atteint sous QGIS en utilisant le type “Valeurs uniques” dans la configuration du formulaire QGIS (bien cocher “Editable”)

Nous obtiendrons ceci à la saisie d’un objet :

IA et géo

La librairie GeoAI de Qiusheng Wu vise à spatialiser l’ensemble des traitements de données IA.

Ce sont comme des branchements aux librairies IA les plus communes (telles que torch), ce qui est bien pratique pour consolider l’environnement de travail et ne pas faire des aller-retours entre un environnement IA classique et SIG.

Signalons aussi l’outil geodeep qui permet de détecter des arbres, voitures, routes depuis des images aériennes.

Une des réalisations de Qiusheng Wu est la librairie SamGeo.

Segment Anything est un modèle qui, sur la base d’un point ou d’un rectangle posé sur une image, parvient à deviner la surface à considérer. On voit rapidement l’intérêt pour la géomatique.

SamGeo peut fournir un objet surfacique géoréférencé à intégrer directement dans votre SIG à partir d’un point géoréférencé ou d’une BBOX.

Voici un résultat que l’on peut obtenir avec SamGeo :

Notons d’ailleurs l’existence du plugin GeoOSAM qui intègre SAM dans QGIS.

QGIS

L’annotation de données sous QGIS peut emprunter une variété de chemins.

Grilles

Sous QGIS, pour une tâche de segmentation, ou de détection, on doit découper la zone à investiguer en carreaux afin de préparer les données nécessaires à l’entraînement d’une IA. Chacun de ces carreaux fournira l’image sur laquelle réaliser l’entraînement.

Dans certains cas, les dalles à utiliser fourniront naturellement les images sur lesquelles réaliser l’entraînement.

Dans ce cas, pour avoir la grille associée, il suffit d’en créer le tableau d’assemblage. en choisissant le tableau contenant les dalles

Ce tableau d’assemblage fournira la grille de suivi de l’état d’avancement des annotations. Nous verrons comment activer ce suivi dans un prochain billet.

Dans le cas où la zone serait très grande ou les données d’une précision telle que cela nécessiterait de considérer un tamis plus fin, il sera nécessaire de réaliser soi-même la grille.

Voici comment générer une grille sous QGIS :

On utilisera l’atlas pour générer les images le long de la grille.

Remarque sur d’autres objets de couverture

On pourrait se dire que des objets type parcelles fourniraient des objets corrects à partir desquels réaliser l’atlas et les images d’entraînement, mais cela a plusieurs inconvénients :

  • Les parcelles seront de taille différente, et les images en sortie correspondront à des échelles différentes ;
  • Si deux parcelles saisies sont contigües, certains objets pourront apparaître sur deux images, voire plus, ce qui équivaut à surentraîner le modèle IA sur ces objets.

La grille garantit une homogénéité des tailles et qu’il n’y ait pas de recouvrement, et donc d’objets surreprésentés.

Sachant qu’il est d’usage d’associer aux IA une fonction d’augmentation qui génèrera une variante synthétique, augmentée, du jeu de données, où les images auront été tournées, changées d’échelle (zoomées/dézoomées), ce qui permettra d’envisager une variété de situations possibles, soit de généraliser un maximum, sans avoir à réaliser davantage d’annotations.

Ici, nous avons considéré sous QGIS le cas d’usage “saisie de parkings”.

Masques basiques

Sur une tâche de type classification, où l’on doit classer des places préalablement détectées, par exemple en place PMR / place non PMR, QGIS permettra, par le biais des masques, dans l’atlas, de faire abstraction de ce qui environne la place de façon à ce que l’IA ne cherche pas à y trouver des motifs.

Sous QGIS, on utilisera le style :

  • Polygones inversés ;
  • Ensemble de règles ;
  • L’expression @atlas_featureid = $id

Voici comment générer l’atlas dans ce cas de figure :

(1) Dans un premier temps, on choisit la couche Places sur laquelle réaliser l’export.

(2) Il est important que l’identifiant de l’objet apparaisse dans le fichier d’export image, sinon on ne retrouvera pas nos petits 🐥.

On insère la carte. Comme on ne peut préjuger de l’orientation de la place, on choisit une image carrée de même hauteur et largeur

Voici le rendu pour cette place :

On exporte les images dans un dossier datasets dans lequel on mettra un dossier :

  • IS-PMR (pour les images de places PMR)
  • NOT-PMR (pour les images de places non PMR)

Pour cela, on utilise l’option de filtrage lors de l’export de l’atlas :

Ici, les images seront à mettre dans le dossier IS-PMR.

L’expression handicapee is False sera à utiliser pour le dossier NOT-PMR

Masques avancés

Dans d’autres cas où l’on devrait considérer l’environnement proche, par exemple pour l’élimination de faux positifs lors d’une détection de places de parkings, on pourra :

  • Appliquer une marge autour de la place assez significative pour intégrer l’environnement :
  • Réaliser différents types de masques, plus ou moins progressifs, et tester les performances du modèle selon ces derniers.

Voici un exemple avec un masque de type “dégradé selon la forme” :

Cas d’une place qu’on a notée comme “bien détectée”, qui servira à l’entraînement

Cas d’une place qu’on a notée comme “mal détectée”, qui servira à l’entraînement

Nous sommes sur cette image à proximité d’un terrain de sport et l’IA a détecté le marquage du terrain comme celui d’une place de parking.

Sous Label Studio ou LabelMe, la réalisation de ces masques nécessiterait de post-traiter les images et de réaliser un script, par exemple sous Python, ce qui serait plus complexe.

En résumé

Nous avons :

  • Pressenti que QGIS pouvait fournir un environnement approprié pour annoter des images ;
  • Analysé qu’il permettait d’organiser le travail et de répartir les tâches en fonction des envies et compétences de chacun, notamment en séparant les tâches géométriques des tâches de caractérisation sémantique ;
  • Observé qu’il fournissait un environnement de choix pour produire les images d’entraînement, sans nécessité de programmation, grâce à la fonction Atlas.

A suivre

Dans de prochains billets, nous verrons :

  • Comment configurer QGIS afin de saisir/annoter des objets de manière efficace, toujours sur l’exemple des parkings ;
  • Comment utiliser les expressions pour pré-renseigner certaines valeurs ;
  • Comment suivre l’avancement des annotations dans un cadre collaboratif.