Skip to content

pclutton/map-to-gpx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

map-to-gpx

Turn a photograph of a guidebook map — the kind in Cicerone-style walking guides — into a GPX track you can load into gpx.studio and sync to a GPS watch.

You photograph the map, mark a handful of reference features by clicking the same point on your photo and on a real map, trace the printed route, and export GPX — optionally snapping the route onto real OpenStreetMap paths so the track sits cleanly on the trail. Works anywhere in the world (UK, Corsica, Australia, …) for any source map datum — GPX is always WGS84.

Reproduced route vs ground truth — Paglia Orba

A route traced from a photographed Corsica guidebook page (magenta) laid over the publisher's official GPX (green) on an OpenStreetMap basemap — median ~2.6 m apart.

How it works

A small local web app: a Python (FastAPI) backend does the coordinate maths and image processing; a two-panel Leaflet front-end shows your photo on the left and a real slippy map on the right.

  1. Load photo — HEIC straight off the phone is fine.
  2. Go to the walk area — type a place name, a lat/long, or a grid reference in your book's coordinate system (UK OS grid, UTM/MGA, Lambert-93, MGRS — pick it from the dropdown; the choice is remembered).
  3. Georeference — click a recognisable feature on the photo, then the same feature on the real map. Repeat for 6+ well-spread points (summits, tarns, lake/coast outlines, junctions, bridges). Each point shows its error in metres.
  4. Auto-refine (optional, for gridded/topographic maps) — aligns lake and coast outlines to OpenStreetMap and matches summit triangles to OSM peaks, adding ~15–25 accurate points automatically. Outliers are RANSAC-rejected.
  5. Trace route — click along the printed route. Two ways to turn a handful of clicks into a full line:
    • Snap to colour follows the printed route's colour between clicks, so a few clicks cover long stretches of the drawn line.
    • Route on paths snaps your clicked waypoints onto real OSM footpaths and bridleways with BRouter's hiking profile. A handful of points reproduce the on-path geometry, and it tolerates imprecise clicking (see Accuracy). Any stretch with no mapped path is bridged with a straight line and flagged as approximate.
  6. Preview on the real map, then Export GPX — or publish the aligned photo as a translucent overlay layer to trace over inside gpx.studio's own editor.

Quick start

Requires uv. OCR "Suggest points" additionally needs Tesseract (optional).

uv sync
uv run uvicorn app.main:app --port 8017

Open http://127.0.0.1:8017. Run the tests with uv run pytest.

Transform models

The georeference is fit in a global metric space (Web Mercator), so it works for any region/datum.

  • Smooth (default, 6+ points) — least-squares 2nd-order polynomial. Corrects camera tilt and page curvature while averaging out click imprecision. Best all-round choice; see Accuracy below.
  • Perspective (4+) — projective; corrects tilt only.
  • Affine (3+) — flat scans.
  • Piecewise (6+) — interpolates every point exactly.

Errors shown per point are leave-one-out: how far each point sits from where the others predict it — honest about real accuracy, and points outside the covered area are greyed as "can't verify, add points nearby".

Accuracy

Validated by rendering real published GPX tracks onto map tiles, tracing them back through the pipeline, and measuring the deviation (tools/roundtrip_test.py), and by tracing routes off real photographed guidebook pages and comparing to the publisher's GPX (tools/photo_test.py).

  • On flat/lightly-warped maps with ~10 well-placed points: mean ~5–15 m, the Smooth model beating projective/affine by 2–3× under page warp + click noise.
  • On real photographed pages where the whole route registered cleanly, the traced route matched the official GPX to ~3 m median (walk 10 above, 2.6 m; walk 4 Fango valley, 3.0 m).
  • With Route on paths, ~8 clicked waypoints reproduced a Lake District valley walk to mean 6 m / median 3.5 m against the ground-truth GPX (tools/routing_experiment.py), and the path-snapping absorbed 30–60 m of waypoint placement error. Accuracy there depends on OSM path coverage, so open fell with no mapped path is bridged straight and flagged rather than guessed.

Fango valley

Note on stylised maps: guidebook maps with no coordinate grid and few named features can't be georeferenced automatically — place your control points by hand (the map-match workflow above). The automatic OCR/feature matching is a bonus for proper topographic maps, not a requirement.

Attribution & licence

  • Basemaps © OpenStreetMap contributors; topographic tiles © OpenTopoMap (CC-BY-SA). Geocoding via OSM Nominatim; feature data via the OSM Overpass API; on-path routing via BRouter (set BROUTER_URL to use a self-hosted instance).
  • Coordinate transforms by pyproj/PROJ.
  • The evidence images show only tracks on open basemaps — no copyrighted guidebook imagery. Do not commit or publish photographed guidebook pages or publishers' GPX files; they are copyright of their publishers.

Licensed under the MIT Licence (see LICENSE).

About

Turn a photo of a guidebook map into a GPX track for your GPS watch, snapped onto real OSM paths. Works worldwide, any datum.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages