Journal Une brève introduction à l'utilisation des données OpenStreetMap

Posté par  (site web personnel) . Licence CC By‑SA.
98
21
avr.
2021

Sommaire

Introduction

Vous connaissez sans doute OpenStreetMap (ou OSM), une base de données géographiques libre et collaborative que chacun peut éditer, et qui a souvent été mentionnée sur LinuxFr (voir quelques liens rappelés en fin de journal). Si en théorie tout le monde peut réutiliser ces données (sous licence ouverte ODbl), il peut être difficile pour un nouvel arrivant de savoir par où commencer pour y accéder.

Ce journal s'adresse aux personnes curieuses au sujet d'OpenStreetMap et intéressées par un usage simple des données OSM. Le but est de fournir une brève introduction à l'accès et à la visualisation de ces données cartographiques, mais avec assez d'informations pour aller plus loin une fois le sujet débroussaillé !

À titre d'exemple, ce journal présente les étapes et le code nécessaire pour réaliser quelques cartes du Danemark. Pour vous mettre en bouche, voici le genre d'image qui peut être générée en suivant ce journal, à partir de quelques lignes de commandes et d'un peu de R (le langage destiné aux statistiques):

Carte de Saint-Pétersbourg réalisée à partir de données OSM

Vue de St-Pétersbourg (Russie) réalisée à partir des données OpenStreetMap. Seuls les éléments annotés highways sont utilisés dans cette figure, mais le Golfe de Finlande à l'ouest et le fleuve Néva qui traverse la ville sont bien visibles en filigrane.

Vue d'ensemble de l'écosystème OpenStreetMap

La façon la plus directe de visualiser les données du projet OpenStreetMap est tout simplement de visiter son site, qui permet de naviguer sur une carte du monde interactive. L'aide et le wiki du projet sont plutôt bien faits et permettent de se jeter à l'eau facilement, par exemple pour contribuer soi-même à la cartographie.

Comment télécharger les données OSM

L'accès aux données elles-mêmes peut sembler un peu plus intimidant: la base de données est très volumineuse (environ 100 Go pour la version compressée du monde entier en 2020), il existe de nombreux outils dédiés à différents aspects de la manipulation de ces données, et il peut être difficile de s'y retrouver au premier abord. Dans mon cas, je voulais pouvoir télécharger les données brutes de certaines régions pour générer mes propres visualisations cartographiques en amateur, mais j'ai longtemps eu l'impression que cela nécessitait des étapes ardues avec l'installation d'un serveur comme mapnik et d'une base de donnée comme PostGIS.

En réalité, il y a beaucoup de points d'entrée différents permettant d'utiliser les données brutes OSM ! Ces approches alternatives sont bien expliquées sur la page wiki correspondante. Certaines API ou bibliothèques permettent de télécharger au coup par coup uniquement ce dont on a besoin (par exemple les instances de l'API Overpass ou le paquet R osmar). Je préfère pour ma part télécharger en une seule fois toutes les données correspondant à une certaine région, et travailler ensuite en local en me focalisant sur la mise au point de la visualisation graphique : c'est l'approche choisie dans ce journal.

Une manière pratique de télécharger les données pour une région cible est d'utiliser les instantanés de la base de données OSM fournis par Geofabrik. Dans quel format les données sont-elles proposées ? Il existe deux principaux formats utilisés (mais il y en a d'autres): le format OSM XML (texte brut, organisé et clair) et le format PBF (format binaire, compact, rapide à manipuler par les outils dédiés). Les fichiers peuvent facilement être convertis d'un format à l'autre si besoin.

Les fichiers de données OSM par régions ou par pays peuvent être très volumineux, en fonction de la taille du territoire couvert et de la quantité de données enregistrées pour ce territoire. Par exemple, à l'heure où j'écris ces lignes, le fichier PBF pour l'ensemble de la France fait 3,7 Go (mais des fichiers préparés par département sont disponibles), celui pour les Açores seulement 11.2 Mo et celui pour les USA 7,3 Go.

Structure des données OSM brutes

Les données OSM sont vectorielles : il s'agit d'entités géométriques comme des points, des lignes, ou des polygones, que des moteurs de rendu peuvent utiliser pour générer des tuiles de carte à différent niveaux de zoom.

D'un point de vue technique, les données OSM brutes sont ainsi constituées d'éléments fondamentaux qui peuvent être:

  • un nœud (node), l'élément de base muni d'une latitude et d'une longitude. Il peut être utilisé pour décrire des objets ponctuels (comme un arrêt de bus, un arbre ou un feu tricolore) ou comme composant d'un élément plus complexe.
  • un chemin (way), formé par plusieurs nœuds connectés en une ligne ouverte (ex : route) ou en un polygone fermé (ex : lac).
  • une relation (relation), qui permet d'associer entre eux plusieurs éléments. Par exemple, plusieurs chemins peuvent être groupés en une voie cyclable continue.

Ces éléments (nœuds, chemins, relations) sont complétés par un système d'attributs (tags) de la forme key=value. Par exemple, un chemin avec l'attribut highway=motorway représente une route, et pourrait également être muni d'un attribut comme maxspeed=80.

Une fois familiarisé avec cette hiérarchie relativement simple, vous pourrez jongler avec les données brutes et extraire celles qui vous intéressent sans trop de difficulté, en particulier si vous êtes un peu habitué à manipuler des tableaux de données avec R, Python ou SQL par exemple. Cependant, une chose importante à retenir est que les attributs ne sont pas toujours parfaitement enregistrés par les contributeurs ! Par exemple, certains contributeurs peuvent avoir annoté un trait de côte avec l'attribut coastline, d'autres avec Coastline. Un cours d'eau peut avoir été annoté en tant que natural=water, mais l'attribut water=river peut avoir été oublié.

Un exemple: visualiser la géographie du Danemark

L'approche simple présentée ici pour générer une carte se découpe en trois étapes :

  1. télécharger les données de la région d'intérêt (ici le Danemark) au format PBF
  2. extraire du fichier PBF les données requises pour la carte que l'on veut dessiner, au format XML. Ce filtrage peut être fait en fonction de coordonnées géographiques définissant une zone à extraire et/ou du type de données recherchées (par exemple extraire uniquement les traits de côte et les cours d'eau).
  3. dessiner la carte en utilisant R et quelques paquets dédiés.

Télécharger les données

Pour l'exemple choisi dans ce journal (le Danemark), nous pouvons trouver les données OSM brutes à partir de la page de téléchargement de Geofabrik. Une fois arrivés sur la page pour le Danemark, on nous propose les données sous différents formats, y compris au format PBF qui nous intéresse ici (fichier denmark-latest.osm.pbf, 373 Mo).

La ligne de commande ci-dessous permet de télécharger le fichier PBF requis en utilisant wget:

# Télécharge le fichier denmark-latest.osm.pbf dans le répertoire courant
wget https://download.geofabrik.de/europe/denmark-latest.osm.pbf

Extraire les données cibles

La taille du fichier PBF téléchargé est relativement raisonnable (373 Mo), ce qui est une des raisons du choix du Danemark pour cet exemple. Une fois converties au format XML, les données pour le Danemark entier sont tout de même assez lourdes et la manipulation du jeu complet dans une session R serait un peu malaisée, d'où l'intérêt d'utiliser des outils en ligne de commande pour affiner le jeu de données directement à partir du fichier PBF.

Le programme osmium est un outil en ligne de commande qui permet de manipuler efficacement les fichiers PBF. (Plus généralement, Osmium est aussi une bibliothèque C++ avec des interfaces Python et NodeJS disponibles.) Sur un système Debian, on peut l'installer depuis les dépôts avec apt install osmium-tool. Si la région d'intérêt est connue (par exemple une ville en particulier), il est avantageux d'utiliser osmium pour extraire uniquement les données comprises dans un cadre de latitude et longitude données (une "bounding box" en anglais). De plus, osmium est aussi capable de filtrer les données en se basant sur les attributs.

J'utilise personnellement Marble pour trouver facilement les limites en latitude et longitude de ma zone d'intérêt. Pour cet exemple, je m'intéresse à deux zones du Danemark et je vais donc extraire deux fichiers PBF à partir du fichier PBF du Danemark métropolitain complet :

  1. un fichier centré sur le nord de la péninsule du Jutland. Il sera ensuite filtré par attributs pour garder uniquement les traits de côte ainsi que les rivières et autres éléments hydrographiques. Le cadre géographique est défini par une longitude comprise entre 8 et 11°E et une latitude comprise entre 56 et 58°N.
  2. un fichier centré sur Copenhague. Il sera ensuite filtré par attributs pour garder uniquement les traits de côte et l'hydrographie ainsi que les routes. Le cadre géographique est défini par une longitude comprise entre 12 et 13°E et une latitude comprise entre 55.5 et 56°N.

Péninsule du Jutland

Voici les lignes de commande utilisées pour extraire les données de la péninsule du Jutland :

# Extraire les données pour la région du Jutland
osmium extract --bbox 8,56,11,58 -s smart denmark-latest.osm.pbf -o jutland.pbf
# Filtrer les traits de côte, rivières et autres plans d'eau via les attributs
osmium tags-filter jutland.pbf wr/natural=water wr/natural=bay wr/natural=coastline wr/natural=Coastline wr/water wr/waterway -o jutland-cotes.xml

La commande osmium extract ci-dessus utilise l'option --bbox pour définir le cadre en longitude et latitude et l'option -s smart pour éviter de tronquer les polygones qui chevaucheraient le cadre défini par --bbox (page du manuel).

La commande osmium tags-filter est utilisée pour extraire uniquement les éléments qui nous intéressent (et les convertir au format XML en passant) (page du manuel). Ici, je requiers tous les éléments ways ou relations (préfixe wr/ dans la ligne de commande) avec un attribut natural égal à water, bay, coastline ou Coastline ou avec un attribut water ou waterway. Cela devrait correspondre plus ou moins aux côtes, rivières et plans d'eau, mais encore une fois l'annotation des attributs n'est pas forcément parfaite. Pour cette raison, il est parfois utile d'examiner systématiquement tous les attributs des éléments couvrant la région d'intérêt pour déterminer ceux qui nous intéressent (en utilisant un peu de grep, sort et uniq sur le fichier XML non-filtré de la région, par exemple). L'outil taginfo d'OpenStreetMap peut être utile (voir aussi la page du wiki consacrée aux attributs).

À ce stade, le fichier jutland-cotes.xml contient les données qui nous intéressent pour la visualisation. C'est ce fichier que nous allons pouvoir charger dans R pour dessiner la carte.

Région de Copenhague

Concernant la seconde zone géographique de notre exemple, voici les lignes de commandes utilisées pour extraire les traits de côte et les routes autour de Copenhague :

# Extraire les données pour la région de Copenhague
osmium extract --bbox 12,55.5,13,56 -s smart denmark-latest.osm.pbf -o copenhague.pbf
# Filtrer les traits de côte, rivières et plans d'eau
osmium tags-filter copenhague.pbf wr/natural=water wr/natural=bay wr/natural=coastline wr/natural=Coastline wr/water wr/waterway -o copenhague-cotes.xml
# Filter les routes
osmium tags-filter copenhague.pbf w/highway -o copenhague-routes.xml

À ce stade, deux fichiers sont prêts pour Copenhague : copenhague-cotes.xml et copenhague-routes.xml.

Dessiner les cartes

Une fois que les fichiers XML contenant les données nécessaires à la préparation des cartes sont prêts, il ne reste plus qu'à les charger dans R (ou le programme graphique de votre choix), à jongler un peu pour récupérer les latitudes et longitudes de chaque point et à dessiner le tout dans un fichier png.

C'est donc R qui est employé ici : il s'agit d'un langage de programmation et d'un logiciel libre très utilisé pour les statistiques, aussi bien dans le monde de la recherche académique que dans celui des entreprises privées. Une introduction à R est en dehors du cadre de ce journal, mais quelques pointeurs sont fournis dans la section Pour aller plus loin si vous êtes intéressé !

Les paquets R utilisés ci-dessous sont osmar pour le chargement des données OSM, tidyverse pour la manipulation des données, et ggplot2 et cowplot pour la partie graphique. Notez qu'osmar nécessite l'installation d'un programme tiers, osmosis, qui peut être installé sur un système Debian avec apt install osmosis.

Voici le code R nécessaire pour dessiner une carte des côtes du Jutland :

# Chargement des paquets
library(osmar)
library(tidyverse) # cela charge aussi ggplot2
library(cowplot)

# Chargement des données OSM
src <- osmsource_osmosis("jutland-cotes.xml")
bbox <- corner_bbox(0, 50, 20, 65)
jutland <- get_osm(bbox, src)

# Quelle est la structure de l'object `jutland` ?
str(jutland)

L'objet jutland est une liste qui contient les infos sur les nœuds (jutland$nodes), les chemins (jutland$ways) et les relations (jutland$relations). Le code ci-dessous manipule ces données pour obtenir un tableau final propre, avec les coordonnées de tous les points définissant des chemins ayant un attribut natural, water ou waterway :

target_ways_id <- jutland$ways$tags %>%
  filter(k == "natural" | k == "water" | k == "waterway") %>%
  pull(id) %>% unique()
target_refs <- jutland$ways$refs %>% filter(id %in% target_ways_id)
target_nodes <- left_join(target_refs, jutland$nodes$attrs, by = c("ref" = "id"))

Maintenant que le tableau target_nodes contient tous les nœuds intéressants, groupés par l'identifiant du chemin auquel ils appartiennent, nous sommes prêts à utiliser ggplot2 pour tracer la carte :

bkg_col <- grey(0.1)
p <- ggplot(target_nodes, aes(x = lon, y = lat)) +
  geom_path(aes(group = id), col = "chartreuse", size = 0.3) +
  coord_map(xlim = c(8, 11.5), ylim = c(56.4, 58)) +
  theme_void() +
  theme(plot.background = element_rect(fill = bkg_col, colour = bkg_col))
p <- cowplot::ggdraw(p) + theme(plot.background = element_rect(fill = bkg_col))
ggsave("jutland.png", p, width = 12, height = 6.75)

Carte du Jutland réalisée à partir de données OSM
Vue du nord de la péninsule du Jutland (Danemark). Le centre de la carte est à peu près localisé à 9.8°E, 57.3°N, et la hauteur totale nord-sud de la zone représentée est d'environ 200 km.

On peut jouer sur les couleurs pour différents styles de rendu :

bkg_col <- "dodgerblue3"
p <- ggplot(target_nodes, aes(x = lon, y = lat)) +
  geom_path(aes(group = id), col = "white", size = 0.5) +
  coord_map(xlim = c(8, 11.5), ylim = c(56.4, 58)) +
  theme_void() +
  theme(plot.background = element_rect(fill = bkg_col, colour = bkg_col))
p <- cowplot::ggdraw(p) + theme(plot.background = element_rect(fill = bkg_col))
ggsave("jutland-bleu.png", p, width = 12, height = 6.75)

Carte du Jutland réalisée à partir de données OSM, style diazographie
Même vue que précédemment, style diazographie.

Pour la seconde partie de notre exemple, Copenhague, le principe est le même. La seule différence est que l'on charge séparément les données pour les côtes et pour les routes avant de les afficher ensemble sur la carte finale :

# Chargement des données OSM (cela prend un moment)
src <- osmsource_osmosis("copenhague-cotes.xml")
cophg_cotes <- get_osm(bbox, src)
src <- osmsource_osmosis("copenhague-routes.xml")
cophg_routes <- get_osm(bbox, src)

# Préparation des données pour les côtes et l'hydrographie
target_ways_id <- cophg_cotes$ways$tags %>%
  filter(k == "natural" | k == "water" | k == "waterway") %>%
  pull(id) %>% unique()
target_refs <- cophg_cotes$ways$refs %>% filter(id %in% target_ways_id)
coast_nodes <- left_join(target_refs, cophg_cotes$nodes$attrs, by = c("ref" = "id"))

# Préparation des données pour les routes
target_ways_id <- cophg_routes$ways$tags %>% filter(k == "highway") %>%
  pull(id) %>% unique()
target_refs <- cophg_routes$ways$refs %>% filter(id %in% target_ways_id)
road_nodes <- left_join(target_refs, cophg_routes$nodes$attrs, by = c("ref" = "id"))

À ce stade les tableaux coast_nodes et road_nodes contiennent les données propres, prêtes à être dessinées :

# Le code ci-dessous trace deux fois les routes, avec la même couleur mais avec
# des largeurs et des transparences un peu différentes, afin de leur donner un
# léger effet de lueur.
bkg_col <- grey(0.1)
p <- ggplot(coast_nodes, aes(x = lon, y = lat)) +
  geom_path(data = road_nodes, aes(x = lon, y = lat, group = id),
            col = adjustcolor("magenta", alpha.f = 0.12), size = 0.5) +
  geom_path(data = road_nodes, aes(x = lon, y = lat, group = id),
            col = "magenta", size = 0.1) +
  geom_path(aes(group = id), col = "deepskyblue", size = 0.2) +
  coord_map(xlim = c(12.05, 12.9), ylim = c(55.52, 55.79)) +
  theme_void() +
  theme(plot.background = element_rect(fill = bkg_col, colour = bkg_col))
p <- cowplot::ggdraw(p) + theme(plot.background = element_rect(fill = bkg_col))
ggsave("copenhague.png", p, width = 12, height = 6.75)

Carte de Copenhague réalisée à partir de données OSM
Vue de Copenhague (Danemark). Côtes et réseau hydrographique en bleu, routes en magenta. La largeur totale de la zone représentée est d'environ 60 km.

En utilisant des limites en x et y plus étroites dans la fonction coord_map(), on peut zoomer sur une partie de la ville :

p <- ggplot(coast_nodes, aes(x = lon, y = lat)) +
  geom_path(data = road_nodes, aes(x = lon, y = lat, group = id),
            col = adjustcolor("magenta", alpha.f = 0.1), size = 1) +
  geom_path(data = road_nodes, aes(x = lon, y = lat, group = id),
            col = adjustcolor("magenta", alpha.f = 0.1), size = 0.6) +
  geom_path(data = road_nodes, aes(x = lon, y = lat, group = id),
            col = "magenta", size = 0.2) +
  geom_path(aes(group = id), col = "deepskyblue", size = 0.4) +
  coord_map(xlim = c(12.5, 12.7), ylim = c(55.642, 55.705)) +
  theme_void() +
  theme(plot.background = element_rect(fill = bkg_col, colour = bkg_col))
p <- cowplot::ggdraw(p) + theme(plot.background = element_rect(fill = bkg_col))
ggsave("copenhague-zoom.png", p, width = 12, height = 6.75)

Carte de Copenhague réalisée à partir de données OSM (zoomée)
Vue agrandie de Copenhague (Danemark). La largeur de la zone représentée est d'environ 14 km.

Pour aller plus loin

Quelques contenus apparentés à OSM déjà existants sur LinuxFr

Avant 2015

Conclusion

J'espère que ce journal aura permis de démystifier un peu l'accès aux données brutes OSM et leur utilisation en amateur. De belles cartes n'attendent que quelques lignes de code pour jaillir de votre imagination :)

  • # Merci !

    Posté par  . Évalué à 5. Dernière modification le 21 avril 2021 à 13:48.

    Merci pour ce journal très intéressant.

  • # Merci pour ce journal

    Posté par  (Mastodon) . Évalué à 6.

    Pour faire des belles cartes on peut aussi mentionner la bibliothèque Leaflet avec son package R

  • # Merci !

    Posté par  (Mastodon) . Évalué à 10. Dernière modification le 21 avril 2021 à 21:53.

    Pour rappel

    Les dépêches servent à publier de l’information sur les thèmes principaux de LinuxFr.org, à savoir Linux et les logiciels libres.

    Ton journal aurait eu toute sa légitimité comme dépêche. OSM et R sont des "logiciels" libres.

    L'intérêt d'une dépêche c'est que l'équipe de modération de LinuxFR t'offre gratuitement une relecture bienveillante et que visiblement la page des dépêches est plus visitées que celle des journaux.

    Seul éventuel inconvénient, la relecture par la modération prend un peu de temps (mais pas tellement).

    Surtout, ne pas tout prendre au sérieux !

    • [^] # Re: Merci !

      Posté par  (site web personnel) . Évalué à 9.

      Merci pour ce conseil et ces précisions ! Je dois admettre que pour ma première tentative de contribution à LinuxFr, je me sentais plus à l'aise à l'idée d'expérimenter avec un journal plutôt qu'avec une dépêche publiée en page d'accueil :)

      Au passage, merci à toutes et tous pour ce site et la communauté très accueillante qui existe autour ! Même si ce journal est mon premier contenu publié, je visite régulièrement le site avec intérêt depuis plusieurs années.

  • # Démo

    Posté par  . Évalué à 3. Dernière modification le 22 avril 2021 à 18:56.

    Merci pour cet article.

    Voici également un bel exemple de ce qu’il est possible de faire : https://demo.openstreetmap.fr/map

    Je pensais écrire une nouvelle dépêche sur OSM prochainement, je vais devoir la travailler sérieusement ! (_)

    « Y a même des gens qui ont l’air vivant, mais ils sont morts depuis longtemps ! »

  • # Historique sur LinuxFr

    Posté par  (site web personnel) . Évalué à 4.

    Si tu veux pousser l'historique de la cartographie libre sur LinuxFR un peu plus loin que mon journal de 2006, il y a des journaux où on a discuté du fait de pouvoir faire un "Wikipedia des cartes" avant la création d'OSM.

    Bon il y a une grosse différence entre une idée et un projet qui se lance. Et une grosse différence encore entre un projet qui se lance et un projet qui réussi (je viens d'aller voir upct.org, le domaine est à vendre donc je suppose que l'association n'existe plus)

  • # Merci et bravo pour ce journal

    Posté par  (site web personnel) . Évalué à 4.

    J'en parle ce matin sur Dessinetaville, la liste de diffusion sur laquelle je partage ma veille autour d'OpenStreetMap mais aussi de l'opendata et des communs numériques.

  • # Données altimétriques

    Posté par  . Évalué à 3.

    J'arrive longtemps après la tempête, en plus pour piailler le bec ouvert, mais je serais intéressé de savoir comment on peut intégrer des données altimétriques comme avec opentopomap.org.

    C'est particulièrement utile lorsqu'on se balade du coté de la frontière italienne, pays n'ayant pas de site comme geoportail et que l'IGN refuse à publier la cartographie pour une raison inconnue. C'était médiocre il y a qq années, c'est passé inexistant, puis c'est aujourd'hui redevenu médiocre.

    De ce que je comprends, c'est les données de 2003 de la mission SRTM de la NASA offrant une précision de 100m qui ont été intégrées dans le cas d'OTM. N'y a-t-il pas des données plus précises et plus récentes aujourd'hui ? Et comment intégrer ces données pour obtenir des tiles affichables ?

    • [^] # Re: Données altimétriques

      Posté par  (site web personnel) . Évalué à 2.

      J'arrive moi aussi longtemps après ton commentaire :) et je n'ai malheureusement pas vraiment d'expérience avec l'utilisation des données SRTM. J'y ai jeté un œil par le passé par curiosité, mais à l'époque cela me semblait demander un peu trop d'efforts pour trouver comment y accéder facilement.

      Aujourd'hui, un bon endroit pour commencer à débroussailler le sujet est sans doute cette page du wiki d'OpenStreetMap. Il y a notamment une section "Data in OSM format (XML)" qui semble intéressante.

      Des ressources un peu plus éloignées, mais qui pourraient peut-être t'intéresser (en particulier si tu es déjà utilisat[eur|rice] de R) :

      • le paquet leaflet, mentionné par Bruno plus haut, permet d'avoir accès très facilement à de nombreux fournisseurs de tuiles précalculées ("Third-Party Tiles" dans la doc). Parmi les fournisseurs, il y a notamment des entrées liées à GeoportailFrance et une entrée OpenTopoMap.
      • le paquet R spacey permet d'accéder facilement aux données altimétriques pour les USA via les bases de données USGS et ESRI et de produire de jolies vues en quelques lignes de code (doc).
      • le paquet spacey est lui-même basé sur le paquet rayshader de Tyler Morgan-Wall pour la visualisation (doc), qui est très utilisé pour faire de jolies vues 3D du relief d'une zone géographique donnée (le fil Twitter de Tyler Morgan-Wall présente de nombreuses visualisations de terrain, souvent très jolies, mais cela est peut-être éloigné de ton objectif).

      Bon courage dans ta recherche de données altimétriques, et n'hésite pas à partager tes retours d'expérience si tu trouves quelque chose de bien ! Je suis sûr que cela en intéresserait plus d'un sur ce site :)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.