Structures des fichiers OSM pbf pour l'extraction d'adresses

Bonjour à tous,
je travaille sur un projet de GeoCoding OpenGeoCode similaire à Nominatim mais en mémoire et avec des capacités d’approximation.

Via le script suivant opengeocode/extract.py at master · scampion/opengeocode · GitHub, j’extrais des fichiers OSM PBF les adresses pour produire un CSV de la forme

@lon;@lat;addr:postcode;addr:city;addr:street;addr:housenumber

Si vous avez une bonne connaissance du modèle de données OSM, je cherche donc un conseil pour améliorer le parcours du fichier.
Comme vous le constaterez, c’est a base de if then else sur des Nodes et des attributs avec une double passe, bref laborieux et je pense que le modèle doit permetttre de faire les choses de manière plus exhaustive et propre …

D’avance merci,
Sebastien

Bonjour Sébastien et soit le bienvenu sur ce forum.

Je suis très intéressé par ton projet, vu que j’ai pas mal travaillé sur le sujet, en particulier sur le développement d’addok et sur la génération de fichiers adresses dans le cadre de BANO et de la BAN.

Se baser sur les données OSM n’est malheureusement pas suffisant pour obtenir un géocodeur de qualité car OSM est encore très loin de l’exhaustivité sur les adresses.
De plus, à la lecture de tes scripts d’extraction, tu ne récupères que des adresses sur des nodes, rien d’autre, là où Nominatim indexe bien plus que les adresses qui peuvent en plus figurer sur des way (adresse sur polygone de bâtiment).
Quid des adresses en associatedStreet où le nom de la rue ne figure pas sur le node ?
Quid des addr:city ou postcode qui proviennent de la relation boundary du découpage administratif ?

J’ai aussi du mal à imaginer la quantité de RAM envisagée… as-tu quelques éléments à partager sur ce point ?

Quels sont les temps de réponse et la pertinence des résultats ?
As-tu une instance de démo requêtable ?
As-tu comparé à ce que fait addok ?

Désolé pour toutes ces questions :wink:

1 Like

Bonjour Sébastien,
en complément de la réponse de Christian, tu peux regarder le projet BANO et surtout ses fichiers CSV générés quotidiennement, j’ai l’impression qu’ils peuvent t’être utiles pour ton projet

1 Like

Merci Christian, ta réponse est un miracle d’Internet :grinning:
Je ne sais pas pour ou commencer

La démo :
Je vais essayer de remonter la démonstration au plus vite pour réponde a tes questions et te donner un accès.

addok:
Je ne connaissais pas addok, merci a nouveau, ca serait peut-être plus simple d’y mettre mes contributions.
Mon besoin est à l’échelle européenne, je travaille pour la commission européenne sur ce sujet.
Je dois pouvoir traduire des adresses mal orthographié en coordonnées GPS pour des applications de machine learning.
Pour cela, je fais une indexation en ngrams en mémoire.

OSM data
Il faut effectivement que je regarde le code de Nominatim de plus près pour avec une extraction CSV simple et tu as répondu a mes questions. J’en déduis que je ne connais pas du tout le modèle :sweat_smile:
Je vais regarder l’extraction dans addok aussi notamment pour les polygones.
Idéalement, j’aimerais trouvé une librairie dédiée.

Tes questions :

Quid des adresses en associatedStreet où le nom de la rue ne figure pas sur le node ?

Je ne connaissais pas, merci

Quid des addr:city ou postcode qui proviennent de la relation boundary du découpage administratif ?

Idem, je suis un vrai newb’ sur le sujet sorry

J’ai aussi du mal à imaginer la quantité de RAM envisagée… as-tu quelques éléments à partager sur ce point ?

Avec 16Gb tu peux faire un pays de mémoire mais ca depend de plusieurs parametres notemment le niveau de détails d’OSM

Quels sont les temps de réponse et la pertinence des résultats ?

En nano secs

As-tu une instance de démo requêtable ?

En cours

As-tu comparé à ce que fait addok ?

Je suis passé a coté

addok fonctionne aussi avec des ngrams, en RAM (index dans redis) et gère les adresses mal orthographiées, dans une certaine limite bien sûr et gère aussi l’auto complétion (suggestion sur une saisie manuelle d’une adresse encore incomplète).

addok ne fait pas l’extraction des données OSM, ce n’est pas son but qui est d’indexer et de retrouver si possible ce qu’on cherche.

J’ai une instance de démo sur https://demo.addok.xyz qui contient pour la France non seulement les adresses mais aussi les points d’intérêt et intersections de rues/routes.

Pour les temps de réponse, je demande à voir pour de la ns… addok répond en moyenne en 30ms et est considéré comme très rapide :wink:

Si tu veux en savoir plus sur addok, voici un peu de lecture:

https://cq94.medium.com/sous-le-capot-du-géocodeur-addok-398ce9b2b1fa

Merci pour le lien medium, je regarde ca attentivement.

Comment alimentez vous addok depuis OSM ?

Pour info, j’ai aussi entrainer un réseau de neurones utilisant des convolutions.

Il est entrainer avec des fautes volontaires pour être robuste et donne des résultats intéressant a première vue pour des addresses très dégradées.

Merci, je cherche comment générer les datas depuis OSM mais je n’ai pas trouvé d’extracteur d’addresses dans le code du projet BANO , une idée ?

Tu as accès aux résultats d’extraction de BANO directement sous Index of /data . Pour répondre à ta question 2 posts plus haut, addok utilise ces fichiers, au format JSON

Merci, mais c’est justement l’extraction de BANO que je veux reproduire dans plusieurs pays avec OSM.

D’accord, je n’avais pas compris que tu pensais à étendre à l’Europe le code de BANO. Ce ne sera pas trivial car ça n’a pas du tout été pensé pour, c’est très franchouillard BANO :slight_smile:
Ce qui est simple à reprendre dans un premier temps c’est le principe d’une BD Postgres avec le contenu Adresses d’OSM qui alimente BANO. Je l’alimente avec un PBF France, aucune raison que ça ne fonctionne pas avec des PBFs d’autres pays voir un PBF Europe. Ca te donnera des tables sur lesquelles s’appuie ensuite l’extraction BANO, en CSV comme en JSON.
Tu peux regarder ce fichier comme point d’entrée

C’est déjà une bonne base de départ BANO pour passer à l’échelle européenne, je pense.
Mon objectif, c’est d’éviter de passer par la base de données mais c’est peut etre trop ambitieux.
Mon script parse un PBF et produit le CSV directement.

imposm import -mapping $BANO_DIR/bano.yml -read $DOWNLOAD_DIR/france_metro_dom_com_nc.osm.pbf -overwritecache -cachedir $IMPOSM_CACHE_DIR -dbschema-import public -diff -diffdir $DOWNLOAD_DIR

Je comprend pas ce que fait cette ligne ?

imposm import -mapping $BANO_DIR/bano.yml -write -connection 'postgis://cadastre@localhost/osm'?prefix=NONE -cachedir $IMPOSM_CACHE_DIR -dbschema-import public -diff -diffdir $DOWNLOAD_DIR

Celle ci importe dans la db localhost

psql -d osm -U cadastre -f $BANO_DIR/sql/finalisation.sql

Le contenu de finalisation.sql va peut etre m’aider pour le parsing

Merci pour ton aide et tes pointeurs, je vais retravailler le script

C’est le parsing du PBF avant chargement en BD. Le parsing dépend du contenu du fichier de conf (ici bano.yml) qui dit ce qu’on veut garder dans le PBF et comment on veut l’organiser.

Ambitieux je ne sais pas, mais (à mon avis) source de complexité. Une adresse dans OSM c’est parfois la réunion de plusieurs objets (par exemple un point avec juste le n°, et une relation qui référence ce point et qui indique le nom de la rue) et si tu veux tout recomposer en une passe ça va être tricky. Une BD comme espace de travail entre le PBF et ta sortie te permettra je pense d’avancer plus vite et de mieux comprendre les objets OSM que tu manipules

Tu m’as convaincu :slight_smile:
Je vais essayer de mettre le passage par la DB dans un conteneur pour faciliter l’usage.
Merci

Petite précision importante, imposm va générer les géométries des objets.

Pour les nodes, c’est pas un problème de les extraire directement des PBF, pour les way et relations, c’est une toute autre affaire et on en a besoin pour remettre les pièces du puzzle ensemble.

Le puzzle c’est:

  • des nodes addr:xxx mais sans tous les champs renseignés systématiquement (en particulier addr:city et addr:postcode, mais aussi addr:street)
  • retrouver city/postcode à partir des emprises des villes et zones de code postal (qui sont deux choses parfois identiques et parfois différentes, surtout en fonction des pays) en recherchant dans quel polygone se trouve le noeud adresse incomplet

Tu peux faire l’impasse en grande partie sur tout ça, en prenant directement des fichiers prétraités.
Ceci te permettra de te concentrer sur la partie géocodage, qui n’est pas triviale :wink:

Je suis vraiment curieux de voir ce qu’un réseau de neurones peut donner.
Il faudra comparer les résultats aux moteurs existants (addok, photon, etc).

Par expérience, on a vu souvent un côté résultat magique pour 80% des cas, et ensuite pour aller au delà c’est 80% (au mieux !) du travail qu’il reste à faire :wink:
Le côté boite noire de certains algo (typique elasticsearch, mais que pense que l’IA sera encore pire), empêche tout débug et amélioration à part en tatonnant.

Comme souvent, le problème c’est de trouver le temps de comprendre ce puzzle :slight_smile:
Je vais voir s’il y a une documentation du modèle de données quelque part.
Les nodes sans tous les attributs c’est le coté peu ragoutant de mon script.
J’aimerais passer à l’étape suivante mais je dois le faire à l’échelle européenne donc extraire un maximum d’addresses pour les 27 membres.

Pour le géocodage, on peux en discuter de vive voix si tu le souhaite, j’ai un usage qui diffère peut être.

Si l’on peut mutualiser les efforts et les codes pour un fonctionnement avec d’autres pays, ca serait top :slight_smile:

Pour info et mémo, le script d’import utilise Imposm3 qui n’est pas empaqueté dans Debian (en version 2 seulement)

Décidément c’est d’actualité :clap: :clap: :clap:

Pour la France et les 3.2 millions d’adresses extrait de OSM, ca tourne en quelques nanosecondes comme évoqué précédemment, cf le screen shot
La différence avec Redis, c’est dans la connexion je pense ou une erreur dans mon calcul de temps.

@cquest le serveur de test est ici : https://ogc.ssapilot.ovh/

image

[0] % wc -l france.csv
3211081 france.csv

Le calcul du temps :

    q = request.args.get('q')
    s = time.time()
    res = ind[country].find(q)
    e = time.time()
    return jsonify({'query': q,
                    'result': inv[country][str(res)],
                    'time': e - s
                    })

Petite erreur d’unité, non ? time.time() ce sont des secondes.

D’ailleurs, avec une chaine de recherche un peu plus longue patine un peu…

Bienvenue dans le monde merveilleux du géocodage :wink:

Effectivement il y a une erreur, dans le JS je multiplie par 1000 donc ce sont des millisecondes

Et oui elle rame bcp cette machine. Elle héberge d’autres services.
Par ailleurs, je n’ai pas mis de wsgi devant et flask est en mode debug, donc pas très bien configuré.
Je regarde dès que possible.

Merci pour le l’info sur openaddresses, je regarde ca de plus près également dès que possible