MapToPoster:用一行命令把任意城市路网变成极简装饰海报(OSM + OSMnx)

Python
开源
OpenStreetMap
可视化
装饰设计
2026/10/19
·

阅读时间: 大约 14 分钟

MapToPoster:用一行命令把任意城市路网变成极简装饰海报(OSM + OSMnx)

新加坡 neon_cyberpunk 主题海报:深色底上洋红色快速路与青色次干道分层描出路网,底部带城市名、国家名与经纬度(官方示例,© OpenStreetMap contributors)

MapToPoster(仓库原名 City Map Poster Generator)是 GitHub 用户 originalankur 开源的 Python 单脚本工具:输入城市名与国家,从 OpenStreetMap(OSM)取路网数据,渲染成一张极简风格的竖版地图海报 PNG。MIT 协议。本文基于仓库 README、requirements 与仓库页面做一手核对。

一、背景动机:把”城市轮廓”变成可打印的墙饰

城市路网本身具有强装饰性:曼哈顿的方格、威尼斯的运河网、东京的有机街道、巴黎的放射大道。现成的地图海报多为付费素材或手工设计,而 OSM 已经提供了开放的全球路网数据。MapToPoster 把”地理编码 → 取路网 → 按主题配色渲染”串成一条命令,让没有设计基础的人也能批量生成自己城市的装饰画。仓库页面(2026-10-19 快照)显示约 14.2k stars、1.3k forks、47 watching;Koala 项目库收录时(#1540)记录为 6900+ star,两个数字对应不同时间点,不宜混用。

二、是什么:CLI 脚本,不是 App

  • 形态:核心是 create_map_poster.py 一个脚本,配合 font_management.py 管理字体,主题放在 themes/ 目录的 JSON 文件里;无 Web 界面、无桌面 App。
  • 依赖:requirements.txt 锁定 matplotlib==3.10.8、osmnx==2.0.7;推荐用 uv(uv run ./create_map_poster.py --city "Paris" --country "France"),也支持 pip + venv。
  • 协议:MIT。
  • 输出:PNG 写入 posters/,命名 {city}_{theme}_{YYYYMMDD_HHMMSS}.png。

三、技术机制:地理编码 → OSMnx 取图 → matplotlib 分层渲染

README 的架构图把管线分为四段:CLI Parser(argparse)→ Geocoding(Nominatim)→ Data Fetching(OSMnx)→ Rendering(matplotlib)→ Output。

  1. 地理编码:get_coordinates() 调用 OpenStreetMap 的 Nominatim 服务,把城市名+国家名转成经纬度;也可用 --latitude/-lat、--longitude/-long 直接覆盖中心点。
  2. 路网获取:OSMnx 的 ox.graph_from_point(point, dist=dist, network_type=...) 以中心点为圆心、按半径拉取街道网络;network_type 可选 drive/bike/walk,README 性能提示推荐 drive(只取机动车道)以加速。
  3. 分层渲染(z-order):
z 值图层
z=11文字标签(城市名、国家、坐标)
z=10上下渐变压暗(gradient fades)
z=3道路(ox.plot_graph)
z=2公园(绿色面)
z=1水域(蓝色面)
z=0背景色
  1. 道路层级配色与线宽(get_edge_colors_by_type() / get_edge_widths_by_type() 按 OSM highway tag):
OSM 道路类型线宽视觉
motorway / motorway_link1.2最粗、最深/最亮
trunk / primary1.0粗
secondary0.8中
tertiary0.6细
residential / living_street0.4最细、最浅
  1. 排版与文字检测:is_latin_script() 用 Unicode 区间(U+0000–U+024F)判定,字母占比超过 80% 即视为拉丁文字,给城市名加字距形成 “P A R I S” 效果;日文、阿拉伯文、韩文等非拉丁文字保持自然间距。文字用 transform=ax.transAxes 归一坐标定位:y=0.14 城市名、0.125 装饰线、0.10 国家名、0.07 坐标、0.02 右下角 attribution。
  2. 多语言与字体:--display-city/-dc、--display-country/-dC 自定义显示名,--font-family 指定 Google Fonts 家族(如 Noto Sans JP / Noto Sans KR / Cairo / Noto Sans SC / Noto Sans Thai / Noto Sans Khmer),字体自动下载并缓存到 fonts/cache/。

东京 japanese_ink 主题:米白底、灰色密集有机街巷、褐色干线与橙色节点,呈现水墨留白感(官方示例)

四、关键参数与规格

项目默认 / 取值说明
必选--city/-c、--country/-C用于 Nominatim 地理编码
主题 --theme/-tterracotta内置 17 个,--list-themes 列出,--all-themes 全量生成
半径 --distance/-d18000 米4000–6000m 小城密集中心;8000–12000m 中等城市市中心;15000–20000m 大都市全景
画布 --width/-W / --height/-H12 × 16 英寸上限各 20 英寸
分辨率300 DPI默认 12×16in 即 3600×4800px

README 给出的 300 DPI 目标分辨率对照:Instagram 1080×1080 = 3.6×3.6in;手机壁纸 1080×1920 = 3.6×6.4in;HD 壁纸 1920×1080 = 6.4×3.6in;4K 3840×2160 = 12.8×7.2in;A4 印刷 2480×3508 = 8.3×11.7in。

17 个内置主题:gradient_roads、contrast_zones、noir、midnight_blue、blueprint、neon_cyberpunk、warm_beige、pastel_dream、japanese_ink、emerald、forest、ocean、terracotta、sunset、autumn、copper_patina、monochrome_blue。自定义主题只需在 themes/ 放一个 JSON,字段覆盖 bg/text/gradient_color/water/parks/road_motorway/primary/secondary/tertiary/residential/default。

威尼斯 blueprint 主题:藏青底、白色细线勾勒运河巷网,深色条带为大运河(官方示例)

五、评测方法与口径批判:它测的是什么、不是什么

  1. 无客观评测,只有视觉样例:README 给出的是 10 个城市的成品海报与推荐半径,没有渲染耗时、内存占用、定位成功率等量化指标;“好不好看”是主观判断,本文不把样例效果外推为对所有城市的保证。
  2. 星数是实时快照:14.2k 为浏览当日页面读数,随时间变动;Koala 条目里的 6900+ 是收录时点值,两者不是矛盾,而是时间差。
  3. 地图不是测绘产品:海报不提供比例尺、指北针与精确方位,中心坐标是城市中心点而非图幅范围;它是艺术化投影,不能用于导航、量距或选址。
  4. 半径靠经验推荐:4–6 / 8–12 / 15–20km 三档是作者按城市规模给的经验区间,同一座城市换半径会得到完全不同的构图,不存在”正确值”。

六、适用与不适用场景

适合:

  • 想为自己所在城市、母校、故乡做个性化装饰画或礼物的个人;
  • 需要批量出图(--all-themes)做壁纸、社媒封面的内容创作者;
  • 学习 OSMnx 取路网、matplotlib 分层绘图的 Python 学习者;
  • 愿意本地跑命令、不需要界面的技术用户。

不适合:

  • 想要网页上传即出图、零配置的非技术用户(README 的 Contributors Guide 明确不收 Web/桌面 UI);
  • 需要精确地图、可交互地图或商用测绘底图的项目;
  • 期望开箱支持铁路、建筑等高阶图层的用户(README 仅以代码片段示例如何自行加铁路层)。

七、客观分析:优势与局限

优势:

  1. 零设计门槛:一行命令出图,配色、线宽、排版全部预设;
  2. 主题扩展成本低:新增主题只是写一个 JSON,不必改代码;
  3. 管线透明:Nominatim + OSMnx + matplotlib 都是常见开源组件,方便二次改造;
  4. 多语言排版考虑周到:拉丁字距与非拉丁自然间距自动切换,支持中日韩阿泰柬文;
  5. MIT 协议,可自由修改与自用。

局限与官方/工程口径偏差:

  1. 地理编码依赖公共 Nominatim,有限流且可能定位错误:同名城市、拼写偏差会落到错误点位,作者建议本地缓存坐标;定位错了海报整张都错。
  2. 数据质量取决于 OSM 志愿贡献:偏远地区、新城路网可能缺失或不成体系,不同城市出图密度差异大。
  3. 大半径性能代价明确:README 自陈 dist>20km 下载慢、内存重;预览应把 dpi 从 300 降到 150;drive 网络比 all 快但丢步行/自行车道。
  4. 无界面、不 Docker 化:Contributors Guide 明确不收 Web/桌面 UI、暂不 Dockerize,大功能需先在 Discussions/Issue 征询;本地需自备 Python/uv 环境。
  5. 主题 JSON 只覆盖既有图层:加铁路、建筑等新图层必须改 Python 代码并给主题 JSON 加回退字段。
  6. ODBL 署名义务:海报右下角自带 ”© OpenStreetMap contributors”,这是 ODbL 许可要求;商用分发时不能去掉署名,也需遵守相同方式共享条款。
  7. 版权归属两层:脚本 MIT,但底图数据归 OSM 贡献者,二者不可混为一谈。

八、它意味着什么 / 谁该关注

MapToPoster 代表了”开放地理数据 + 轻脚本 + 审美模板”的小工具路线:不做平台、不做服务,把一件具体的装饰需求做到可复现。值得关注:想学习 OSMnx 的 Python/可视化开发者、需要个性化城市海报的个人与礼品场景、以及研究 ODBL 数据二次创作合规边界的作者。上手建议先小半径(如 5–8km)出预览,确认定位与构图后再放大到 300 DPI 正式渲染。

参考来源