基于OSMnx提取城市全量人行横道的代码优化问询
问题
需要提取某一城市(如芝加哥)在OSM中所有已标注的人行横道(包括标记和未标记的),但当前使用的代码仅能捕获部分目标,仍有不少已映射的交叉口人行横道未被获取,现寻求代码修改方案。
当前代码
import osmnx as ox # Set console logging to True ox.settings.log_console = True # Set useful tags for walking network useful_tags = ox.settings.useful_tags_way + [ 'crossing', 'crossing:uncontrolled', 'crossing:zebra', 'crossing:marked', 'crossing:traffic_signals', 'crossing:school', 'crossing:island', 'crossing:refuge_island', 'crossing:island:central', 'crossing:island:central:traffic_signals', 'crossing:island:central:marked', 'crossing:island:central:zebra', 'crossing:unmarked', 'highway:crossing', 'pedestrian' ] ox.config(use_cache=True, log_console=True, useful_tags_way=useful_tags) # Download the network with specified tags G = ox.graph_from_place(query='Chicago, Illinois, USA', network_type='walk', simplify=False, retain_all=True) # Identify and remove non-walk edges non_walk = [] for u, v, k, d in G.edges(keys=True, data=True): is_walk = "walk" in d and d["walk"] == "designated" is_crossing = ( d.get("highway") in ["crossing", "pedestrian"] or "crossing" in d or "crossing:uncontrolled" in d or "crossing:raised" in d or "crossing:speed_table" in d or "crossing:hump" in d or "crossing:zebra" in d or "crossing:marked" in d or "crossing:traffic_signals" in d or "crossing:school" in d or "crossing:island" in d or "crossing:refuge_island" in d or "crossing:island:central" in d or "crossing:island:central:traffic_signals" in d or "crossing:island:central:marked" in d or "crossing:island:central:zebra" in d or "crossing:unmarked" in d or "highway:crossing" in d or "pedestrian" in d ) # Include pedestrian crossings at intersections without traffic signals is_intersection = "highway" in d and d["highway"] == "uncontrolled_intersection" if is_intersection and not is_crossing: is_crossing = True # Exclude pedestrian sidewalks is_sidewalk = "sidewalk" in d if not is_walk and not is_crossing and not is_sidewalk: non_walk.append((u, v, k)) G.remove_edges_from(non_walk) G = ox.utils_graph.remove_isolated_nodes(G) G = ox.simplify_graph(G) # Calculate and print total edge length stats = ox.stats.basic_stats(G) print("Total Edge Length:", stats["edge_length_total"]) # Plot the graph ox.plot_graph(G, node_color="w", node_size=15, edge_color="b", edge_linewidth=0.5, figsize=(20, 20))
问题现象
当前代码生成的结果(含GeoPackage文件)遗漏了部分已在OSM中标注的交叉口人行横道:
- 对比可见,右侧是需要捕获的交叉口人行横道,左侧是遗漏的部分
- 生成的芝加哥人行横道OSMnx图谱也存在明显遗漏
代码修改方案
1. 调整OSM数据查询方式,直接针对人行横道标签筛选
原代码基于步行网络下载,可能遗漏部分仅标注人行横道属性的道路段。改用ox.geometries_from_place直接获取含人行横道标签的要素,再转换为图结构:
# 替换原graph_from_place部分 tags = { 'highway': ['crossing', 'pedestrian'], 'crossing': ['*'] # 匹配所有crossing相关标签 } # 获取所有符合标签的几何要素 gdf = ox.geometries_from_place('Chicago, Illinois, USA', tags=tags) # 转换为图结构 G = ox.graph_from_gdfs(gdf[gdf.geometry.type == 'LineString'], gdf[gdf.geometry.type == 'Point'])
2. 优化人行横道判断逻辑,覆盖更多OSM标签规则
OSM中人行横道的标注方式多样,比如部分交叉口的人行横道会标注在道路的crossing属性中,而非单独的highway=crossing。修改判断逻辑:
# 替换原is_crossing判断 def is_valid_crossing(d): # 直接标记为人行横道的道路段 if d.get('highway') in ['crossing', 'pedestrian']: return True # 道路上标注了人行横道属性 if 'crossing' in d: crossing_val = d['crossing'] # 匹配所有有效人行横道类型,包括unmarked、marked等 return crossing_val not in ['no', 'none'] # 交叉口处的人行横道(部分交叉口会将人行横道关联到节点或道路属性) if d.get('highway') in ['uncontrolled_intersection', 'traffic_signals']: return True # 包含人行横道相关的子标签 for key in d.keys(): if key.startswith('crossing:') and d[key] not in ['no', 'none']: return True return False
3. 避免过早简化图结构导致丢失信息
原代码中ox.simplify_graph会合并相邻节点,可能丢失交叉口处的人行横道细节。建议先完成筛选再按需简化,或关闭自动简化:
# 移除G = ox.simplify_graph(G)这一行,或改为保留更多细节的简化 G = ox.simplify_graph(G, strict=False)
4. 补充标签集合,确保获取所有相关属性
扩展useful_tags,加入更多OSM中与人行横道相关的标签:
useful_tags = ox.settings.useful_tags_way + [ 'crossing', 'crossing:uncontrolled', 'crossing:zebra', 'crossing:marked', 'crossing:traffic_signals', 'crossing:school', 'crossing:island', 'crossing:refuge_island', 'crossing:island:central', 'crossing:island:central:traffic_signals', 'crossing:island:central:marked', 'crossing:island:central:zebra', 'crossing:unmarked', 'highway:crossing', 'pedestrian', 'crossing:raised', 'crossing:speed_table', 'crossing:hump', 'crossing:informal', 'crossing:light_signals', 'crossing:marked:no' ]
完整修改后代码
import osmnx as ox # 设置控制台日志 ox.settings.log_console = True # 扩展有用标签集合 useful_tags = ox.settings.useful_tags_way + [ 'crossing', 'crossing:uncontrolled', 'crossing:zebra', 'crossing:marked', 'crossing:traffic_signals', 'crossing:school', 'crossing:island', 'crossing:refuge_island', 'crossing:island:central', 'crossing:island:central:traffic_signals', 'crossing:island:central:marked', 'crossing:island:central:zebra', 'crossing:unmarked', 'highway:crossing', 'pedestrian', 'crossing:raised', 'crossing:speed_table', 'crossing:hump', 'crossing:informal', 'crossing:light_signals' ] ox.config(use_cache=True, log_console=True, useful_tags_way=useful_tags) # 直接查询含人行横道标签的要素 tags = { 'highway': ['crossing', 'pedestrian'], 'crossing': ['*'] } gdf = ox.geometries_from_place('Chicago, Illinois, USA', tags=tags) # 转换为图结构 G = ox.graph_from_gdfs(gdf[gdf.geometry.type == 'LineString'], gdf[gdf.geometry.type == 'Point'], simplify=False) # 筛选有效人行横道边 non_crossing = [] for u, v, k, d in G.edges(keys=True, data=True): def is_valid_crossing(edge_data): if edge_data.get('highway') in ['crossing', 'pedestrian']: return True if 'crossing' in edge_data: return edge_data['crossing'] not in ['no', 'none'] if edge_data.get('highway') in ['uncontrolled_intersection', 'traffic_signals']: return True for key in edge_data.keys(): if key.startswith('crossing:') and edge_data[key] not in ['no', 'none']: return True return False if not is_valid_crossing(d): non_crossing.append((u, v, k)) G.remove_edges_from(non_crossing) G = ox.utils_graph.remove_isolated_nodes(G) # 按需简化,保留更多细节 G = ox.simplify_graph(G, strict=False) # 统计并输出总长度 stats = ox.stats.basic_stats(G) print("总边长度:", stats["edge_length_total"]) # 绘制图谱 ox.plot_graph(G, node_color="w", node_size=15, edge_color="b", edge_linewidth=0.5, figsize=(20, 20))
内容的提问来源于stack exchange,提问作者mm13816
相关产品推荐
相关产品推荐

