Cartes : annotation géographique avec des points, des lignes, des polygones et des régions
Tracez des points, des lignes et des polygones étiquetés sur une carte dans Potato, épinglez des lieux ou étiquetez des régions, sur un contour GeoJSON, une image géoréférencée, un GeoTIFF ou vos propres tuiles.
Nouveau dans la v2.12.0
geo_annotation place une carte sur la page d'annotation. Les annotateurs y tracent des points, des lignes et des polygones étiquetés, épinglent des lieux, ou attribuent des étiquettes aux régions d'un fond de carte. La carte est OpenLayers 10.9.0, que Potato sert lui-même ; aucune bibliothèque cartographique n'est donc chargée depuis Internet.
annotation_schemes:
- annotation_type: geo_annotation
name: land_cover
description: "Outline the land cover"
task: draw
tools: [polygon, freehand, point]
labels:
- {name: Water, color: "#0072B2"}
- {name: Forest, color: "#009E73"}
basemap:
geojson: maps/regions.geojsonLe dépôt Potato contient deux exemples exécutables. examples/advanced/dialect-map/ est une enquête dialectale par dessin sur carte portant sur un pays fictif, qui utilise les trois tâches (Dialectologie perceptive), et examples/image/geo-annotation/ délimite l'occupation du sol sur des images géoréférencées, une image par item, avec un polygone suggéré sur le premier item.
Tâches
task | Ce que fait l'annotateur | Ce qui est stocké |
|---|---|---|
draw (par défaut) | Trace des points, des lignes, des polygones et des polygones à main levée, et attribue à chacun une étiquette, plus un nom saisi avec feature_text | Une entité GeoJSON par tracé |
pin | Place un point pour chaque étiquette. Chaque étiquette est une question, comme "Where were you born?" | Un point par étiquette |
classify_region | Choisit une étiquette, puis clique sur des régions du contour du fond de carte pour leur attribuer cette étiquette. Cliquer de nouveau sur une région avec la même étiquette l'efface | Une entité par région étiquetée, avec geometry: null et l'identifiant de la région |
Le fond de carte
Chaque schéma a besoin d'un fond de carte, dans basemap ou par item via basemap_field, et sans fond de carte potato validate et le serveur refusent la configuration. Potato ne se replie pas sur une carte en ligne ; une étude ne charge donc aucune carte depuis Internet, sauf si sa configuration en désigne une.
| Source | Configuration | Remarques |
|---|---|---|
| Contour GeoJSON | basemap: {geojson: maps/regions.geojson} | Un fichier sous task_dir, intégré à la page. Gardez-le simplifié, quelques centaines de Ko au plus, car il fait partie de chaque page d'annotation |
| Image géoréférencée | basemap: {image: /media/area.png, extent: [min_lon, min_lat, max_lon, max_lat]} | Un PNG ou un JPEG en projection plate carrée (équirectangulaire) couvrant extent |
| GeoTIFF ou Cloud Optimized GeoTIFF | basemap: {geotiff: /media/area.tif} | Lu avec geotiff.js 3.0.5, fourni avec Potato. Le fichier doit être en EPSG:4326 ou EPSG:3857, et le navigateur doit prendre en charge WebGL |
| Tuiles XYZ | basemap: {tiles: "https://tiles.example.org/{z}/{x}/{y}.png", attribution: "..."} | Votre propre serveur de tuiles ou un fournisseur avec lequel vous avez un accord. attribution est obligatoire pour une URL externe, et {-y} est accepté pour la numérotation TMS |
Un contour GeoJSON peut être combiné avec une source raster, et le contour est tracé par-dessus.
Les serveurs de tuiles de l'OpenStreetMap Foundation fonctionnent grâce à des ressources données, et leur politique d'utilisation des tuiles interdit un usage intensif. Une étude où de nombreux annotateurs font défiler une carte constitue un usage intensif ; Potato accepte donc l'URL avec un avertissement dans le journal. Hébergez vos propres tuiles ou utilisez un fournisseur commercial.
basemap_field désigne un champ de l'item qui contient son fond de carte : une FeatureCollection GeoJSON, une URL sous forme de chaîne (.tif et .tiff sont lus comme GeoTIFF, tout le reste comme GeoJSON), ou un objet avec les mêmes clés que basemap. Le serveur vérifie le fond de carte de chaque item selon les mêmes règles avant d'envoyer l'item, et un item ne peut désigner un serveur externe que si le basemap du schéma lui-même désigne une URL sur cet hôte.
Pour classify_region, chaque entité du contour est une région. Son identifiant est la propriété region_id_property (id par défaut), puis l'identifiant de l'entité GeoJSON, puis r<index>, et son nom est la propriété region_name_property (name par défaut).
Options
| Clé | Valeur par défaut | Signification |
|---|---|---|
task | draw | draw, pin ou classify_region |
labels | obligatoire | Des chaînes ou {name, color, description}. Les couleurs suivent par défaut une palette Okabe-Ito. Mettez entre guillemets Yes, No et On, que YAML charge sinon comme des booléens |
tools | [point, line, polygon, freehand] | draw uniquement. Un outil de sélection et de déplacement est toujours ajouté |
feature_text | désactivé | true, ou {prompt, required, placeholder} : un champ de texte par entité, stocké dans properties.text |
basemap | aucune | geojson, image, extent, geotiff, tiles, attribution, max_zoom, region_id_property, region_name_property |
basemap_field | aucune | Champ de l'item contenant un fond de carte propre à l'item |
preannotation_field | aucune | Champ de l'item contenant les entités GeoJSON de départ (pas pour classify_region) |
coordinate_order | lonlat | latlon si les données de pré-annotation ou le contour écrivent la latitude en premier. La sortie est toujours [lon, lat] |
projection | EPSG:3857 | Projection d'affichage, EPSG:3857 (Web Mercator) ou EPSG:4326. Le stockage est toujours en EPSG:4326 |
center, zoom | ajusté au fond de carte | Vue initiale, avec center: [lon, lat] |
height | 440 | Hauteur de la carte en pixels, de 200 à 1200 |
snapping | false | Aimante les nouveaux sommets aux entités existantes et au contour |
min_features, max_features | 1 si obligatoire, aucune | draw uniquement. Les outils de dessin sont désactivés au maximum |
require_all_regions | false | classify_region : chaque région doit recevoir une étiquette avant Next |
label_requirement | aucune | {required: true} bloque Next tant que la condition propre à la tâche n'est pas remplie : min_features entités pour draw, une épingle par étiquette pour pin, au moins une région (ou toutes) pour classify_region |
Utiliser la carte
Pour dessiner, choisissez une étiquette, puis un outil. Un point se place en un clic. Une ligne se trace avec un clic par point et un double-clic sur le dernier. Un polygone se trace avec un clic par sommet, et se termine en cliquant sur le premier sommet, en double-cliquant ou en appuyant sur Entrée ; Retour arrière supprime le dernier sommet et Échap annule. La main levée se trace en appuyant et en faisant glisser. L'outil de sélection remodèle une entité par son contour ou par un sommet, et Suppr la supprime. Chaque entité apparaît dans la liste sous la carte avec un menu d'étiquette, le champ de nom, Show et Delete.
Pour les épingles, la liste affiche une ligne par étiquette, et cliquer sur la carte place l'étiquette active. Pour les régions, choisissez un bouton d'étiquette et cliquez sur des régions.
Au clavier, allez jusqu'à la carte avec Tab ; les touches fléchées font alors défiler la carte, et + et - zooment. Add point at map centre et Use map centre placent des points sans souris, et l'étiquette, le nom et la suppression de chaque entité sont accessibles depuis la liste.
Les entités issues de preannotation_field sont marquées "(suggested)". Elles ne sont enregistrées comme réponse de l'annotateur que lorsque celui-ci en modifie une ou appuie sur Accept suggestions ; un item que l'annotateur a seulement ouvert ne compte donc pas comme étiqueté.
Données stockées
La réponse est une FeatureCollection GeoJSON en EPSG:4326 conforme à la RFC 7946 : les positions sont [longitude, latitude], les anneaux extérieurs tournent dans le sens inverse des aiguilles d'une montre et les trous dans le sens des aiguilles, les coordonnées ont 7 décimales (environ 1 cm), et les longitudes sont ramenées entre -180 et 180.
{"type": "FeatureCollection", "features": [
{"type": "Feature", "id": "f1",
"geometry": {"type": "Polygon", "coordinates": [[[-29.0, -38.3], [-28.2, -38.3], [-28.6, -37.5], [-29.0, -38.3]]]},
"properties": {"label": "Very different", "text": "Coast talk", "tool": "polygon"}}
]}Le schéma fonctionne aussi sur les pages de questionnaire, où il n'y a pas d'item ; basemap_field et preannotation_field n'y ont donc aucun effet.
Export
# Every feature as GeoJSON, one file per item (geojson/<item>.geojson)
python -m potato.export --config config.yaml --format geojson --output out/
# ... or one file for the whole project
python -m potato.export --config config.yaml --format geojson --output out/ --option layout=single
# Heat maps of overlapping polygons, plus CSVs of names and region labels
python -m potato.export --config config.yaml --format geo_overlap --output out/L'export GeoJSON normalise de nouveau chaque entité et ajoute item_id, user_id, schema et feature_id à ses propriétés. Les entités qui ne peuvent pas être normalisées, comme une position hors limites ou un anneau sans superficie, sont laissées de côté et listées dans les avertissements de l'export. Les réponses classify_region récupèrent la géométrie de leur région depuis le contour. geo_overlap est décrit dans Dialectologie perceptive.
Limites
- Un polygone qui traverse le méridien de 180° n'est pas découpé ; tracez donc deux polygones.
- Un GeoTIFF dans une projection autre qu'EPSG:4326 ou EPSG:3857 ne s'affiche pas, pas plus qu'un GeoTIFF quelconque sans WebGL. La page le signale, et le contour fonctionne toujours.
- Un GeoTIFF est affiché sans interpolation ; zoomer montre donc les véritables limites des pixels.
- Pour des coordonnées en pixels sur une image ordinaire plutôt que des coordonnées géographiques, utilisez l'annotation d'images.
Pour aller plus loin
- Dialectologie perceptive - Enquêtes dialectales par dessin sur carte et cartes de chaleur des chevauchements
- Pièges photographiques - Revue de la sortie d'un détecteur avec export d'occurrences Darwin Core
- Annotation hors ligne (air-gapped) - Exécuter Potato sans accès à Internet
Pour les détails d'implémentation, consultez la documentation source.