使用 OSMNX Nearest_edges 的结果不正确

Posted

技术标签:

【中文标题】使用 OSMNX Nearest_edges 的结果不正确【英文标题】:Incorrect results using OSMNX nearest_edges 【发布时间】:2021-12-18 23:44:12 【问题描述】:

我正在编写一些代码,以根据所行驶给定路径的 GPS 数据从 OSM 获取道路中心线数据。我正在使用 OSMNX 与 OSM 数据交互,但在使用最近边缘将 GPS 数据从我的路径匹配到 OSM 数据时得到奇怪的结果。

这是输入路径(数据间距 enter image description here

这是使用nearest_edges 匹配后的路径: enter image description here

这是我用来生成这些结果的代码:

#!/usr/bin/python3
    
import osmnx as ox
import csv
import utm
from shapely.geometry import Point
import os
import simplekml

# get data from file
path = "C:\\Users\\nj5wdf\\OneDrive - Aptiv\\Projects\\Prodrive\\Curvature_Python\\tests\\"
filename = "map_provider_test_data.csv"
filename = os.path.join(path, filename)
with open(filename, 'r') as file:
    # create csv reader object
    data = list(csv.reader(file))            
    lat = []
    lon = []
    for row in data:
        lat.append(float(row[0]))
        lon.append(float(row[1]))

buffer = 0.002
north_lat = max(lat) + buffer
south_lat = min(lat) - buffer
east_lon = max(lon) + buffer
west_lon = min(lon) - buffer

# generate graph of all road networks within the bounding box
graph = ox.graph_from_bbox(
    north_lat, south_lat, east_lon, west_lon,
    network_type="drive",
    simplify=True,
    truncate_by_edge=True,
    clean_periphery=True)

# convert input lat / lon to UTM
x = []
y = []
for _lat, _lon in zip(lat, lon):
    _y, _x, _, _ = utm.from_latlon(_lat, _lon)
    x.append(_x)
    y.append(_y)

# get nearest edges
nodes, streets = ox.graph_to_gdfs(graph)
graph_proj = ox.project_graph(graph)
nearest = ox.nearest_edges(graph_proj, lon, lat) 
    
# remove redundant edges from result
last_near = nearest[0]
reduced_nearest = []
for near in nearest:
    if (near not in reduced_nearest) and (near[1] != last_near[0]):
        reduced_nearest.append(near)
        last_near = near

# get centerline points from nearest edges 
centerline_points = []
for edge in reduced_nearest:
    street_gdf = streets.loc[edge]['geometry']
    lat_list = list(street_gdf.xy[1])
    lon_list = list(street_gdf.xy[0])
    [centerline_points.append(Point(_lat, _lon)) for _lat, _lon in zip(lat_list, lon_list)]

# instantiate simpleKml
kml = simplekml.Kml()

coords = zip(lon_list, lat_list)

# plot line
ls = kml.newlinestring(name="matched")
ls.coords = coords
ls.style.linestyle.width = 2
ls.style.linestyle.color = simplekml.Color.red
ls.altitudemode = simplekml.AltitudeMode.relativetoground

# save points to file
output_filename = "tests/map_provider_matched.kml"
kml.save(output_filename)

这是我正在使用的测试数据:test_data

关于如何获得更好性能的任何想法?我尝试使用不同的最近邻函数,但它的性能比 ox.nearest_edges 更差。

【问题讨论】:

你能提供一个完整最小的示例代码sn-p来重现你的问题吗?目前您的代码不完整(其中包含未定义的变量,这些变量对于故障排除至关重要)也不是最小的(它包含与您关于最近边缘搜索的问题无关的其他几行)。 我编辑了上面的代码,使它更完整。我认为它尽可能小。我还附上了我正在使用的测试数据。感谢您的帮助! 许多变量仍未定义。您的示例需要是独立的、可复制粘贴运行的,以便其他人对其进行复制和故障排除。 感谢您的耐心等待。我更新了代码并且能够运行它。 看起来您只是在交换 x 和 y 坐标。经度是 x,纬度是 y,但你似乎把它颠倒过来了。 【参考方案1】:

这里发生了很多事情。很难排除故障,因为您没有将其提炼成最小示例,而且您最初的问题陈述不是很具体:

我正在使用 OSMNX 与 OSM 数据交互,但在使用最近边缘将 GPS 数据从我的路径匹配到 OSM 数据时得到奇怪的结果。

我不知道“奇怪的结果”是什么意思,但我已经提炼(我相信你正在尝试做的事情)这里是一个看起来工作正常的最小示例。

import geopandas as gpd
import osmnx as ox
import pandas as pd

# load the points
cols = ['lat', 'lng', 'a', 'b', 'c', 'd', 'e']
df = pd.read_csv('map_provider_test_data.csv', names=cols)

# download the graph
center = df['lat'].mean(), df['lng'].mean()
G = ox.graph_from_point(center, dist=1500, network_type='drive', truncate_by_edge=True)

# project graph and points to same CRS
Gp = ox.project_graph(G)
geom = gpd.points_from_xy(df['lng'], df['lat'])
gdf = gpd.GeoDataFrame(df, geometry=geom, crs='epsg:4326').to_crs(Gp.graph['crs'])

# calculate nearest edge to each point
ne = ox.nearest_edges(Gp, X=gdf['geometry'].x, Y=gdf['geometry'].y)

您可以根据需要绘制此图,以查看这些点是否捕捉到正确的最近边缘:

unique_edges = set(ne)
ec = ['r' if e in unique_edges else '#666666' for e in G.edges]
fig, ax = ox.plot_graph(G, edge_color=ec, edge_linewidth=1, node_size=0, show=False)
ax = ax.scatter(df['lng'], df['lat'], c='y', s=5, zorder=-1)

您也可以在 GIS 中打开它并平移和滚动:最近的边缘搜索看起来一切正常。

【讨论】:

以上是关于使用 OSMNX Nearest_edges 的结果不正确的主要内容,如果未能解决你的问题,请参考以下文章

OSMNX 操作与其他数据

将本地 XML 或 Shapefile 加载到 OSMNX 以创建图形

OSMNX 地理编码器返回不正确的坐标

查找 2 个节点之间的街道名称。 OSMnx

在 Python 中使用 osmnx 到距离内边缘的最近点

Osmnx 错误:模块“osmnx.elevation”没有属性“add_node_elevations_raster”