Ber*_*Git 7 python openstreetmap
我想在我的python代码中包含开放街道地图(OSM).
我已经阅读了很多关于OSM的网页.但不幸的是,我有点迷失,关于我最好用的包.
我正在寻找一种在我的应用程序中获取OSM图像的简单方法.作为我的起点,我想的是:
import matplotlib.pyplot as plt
# Pseudo - Code for required function 'GetOSMImage'
Map = GetOSMImage(lat,long,delta_lat,delta_long)
imgplot = plt.imshow(Map)
Run Code Online (Sandbox Code Playgroud)
后来我想在这个plt中添加我的附加数据.(我知道我需要处理预测等)
我不需要/想要的东西:
你有一个很好的起点吗?或者我低估了这个主题的复杂性?
Ber*_*Git 11
根据您的输入,我能够实现我的目标.这是我的其他代码,它们正在寻找OSM的起点.(科西嘉还有很大的改进空间).
import matplotlib.pyplot as plt
import numpy as np
import math
import urllib2
import StringIO
from PIL import Image
def deg2num(lat_deg, lon_deg, zoom):
lat_rad = math.radians(lat_deg)
n = 2.0 ** zoom
xtile = int((lon_deg + 180.0) / 360.0 * n)
ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
return (xtile, ytile)
def num2deg(xtile, ytile, zoom):
n = 2.0 ** zoom
lon_deg = xtile / n * 360.0 - 180.0
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n)))
lat_deg = math.degrees(lat_rad)
return (lat_deg, lon_deg)
def getImageCluster(lat_deg, lon_deg, delta_lat, delta_long, zoom):
smurl = r"http://a.tile.openstreetmap.org/{0}/{1}/{2}.png"
xmin, ymax =deg2num(lat_deg, lon_deg, zoom)
xmax, ymin =deg2num(lat_deg + delta_lat, lon_deg + delta_long, zoom)
Cluster = Image.new('RGB',((xmax-xmin+1)*256-1,(ymax-ymin+1)*256-1) )
for xtile in range(xmin, xmax+1):
for ytile in range(ymin, ymax+1):
try:
imgurl=smurl.format(zoom, xtile, ytile)
print("Opening: " + imgurl)
imgstr = urllib2.urlopen(imgurl).read()
tile = Image.open(StringIO.StringIO(imgstr))
Cluster.paste(tile, box=((xtile-xmin)*256 , (ytile-ymin)*255))
except:
print("Couldn't download image")
tile = None
return Cluster
if __name__ == '__main__':
a = getImageCluster(38.5, -77.04, 0.02, 0.05, 13)
fig = plt.figure()
fig.patch.set_facecolor('white')
plt.imshow(np.asarray(a))
plt.show()
Run Code Online (Sandbox Code Playgroud)
建立在BerndGit的不错答案上,我添加了一个稍微修改过的版本,允许显示其他内容和图块(使用Basemap).顺便说一下,我遇到了一个专用的库,geotiler(http://wrobell.it-zone.org/geotiler/intro.html),但它需要Python 3.
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
import math
import urllib2
import StringIO
from PIL import Image
def deg2num(lat_deg, lon_deg, zoom):
lat_rad = math.radians(lat_deg)
n = 2.0 ** zoom
xtile = int((lon_deg + 180.0) / 360.0 * n)
ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
return (xtile, ytile)
def num2deg(xtile, ytile, zoom):
"""
http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
This returns the NW-corner of the square.
Use the function with xtile+1 and/or ytile+1 to get the other corners.
With xtile+0.5 & ytile+0.5 it will return the center of the tile.
"""
n = 2.0 ** zoom
lon_deg = xtile / n * 360.0 - 180.0
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n)))
lat_deg = math.degrees(lat_rad)
return (lat_deg, lon_deg)
def getImageCluster(lat_deg, lon_deg, delta_lat, delta_long, zoom):
smurl = r"http://a.tile.openstreetmap.org/{0}/{1}/{2}.png"
xmin, ymax = deg2num(lat_deg, lon_deg, zoom)
xmax, ymin = deg2num(lat_deg + delta_lat, lon_deg + delta_long, zoom)
bbox_ul = num2deg(xmin, ymin, zoom)
bbox_ll = num2deg(xmin, ymax + 1, zoom)
#print bbox_ul, bbox_ll
bbox_ur = num2deg(xmax + 1, ymin, zoom)
bbox_lr = num2deg(xmax + 1, ymax +1, zoom)
#print bbox_ur, bbox_lr
Cluster = Image.new('RGB',((xmax-xmin+1)*256-1,(ymax-ymin+1)*256-1) )
for xtile in range(xmin, xmax+1):
for ytile in range(ymin, ymax+1):
try:
imgurl=smurl.format(zoom, xtile, ytile)
print("Opening: " + imgurl)
imgstr = urllib2.urlopen(imgurl).read()
tile = Image.open(StringIO.StringIO(imgstr))
Cluster.paste(tile, box=((xtile-xmin)*255 , (ytile-ymin)*255))
except:
print("Couldn't download image")
tile = None
return Cluster, [bbox_ll[1], bbox_ll[0], bbox_ur[1], bbox_ur[0]]
if __name__ == '__main__':
lat_deg, lon_deg, delta_lat, delta_long, zoom = 45.720-0.04/2, 4.210-0.08/2, 0.04, 0.08, 14
a, bbox = getImageCluster(lat_deg, lon_deg, delta_lat, delta_long, zoom)
fig = plt.figure(figsize=(10, 10))
ax = plt.subplot(111)
m = Basemap(
llcrnrlon=bbox[0], llcrnrlat=bbox[1],
urcrnrlon=bbox[2], urcrnrlat=bbox[3],
projection='merc', ax=ax
)
# list of points to display (long, lat)
ls_points = [m(x,y) for x,y in [(4.228, 45.722), (4.219, 45.742), (4.221, 45.737)]]
m.imshow(a, interpolation='lanczos', origin='upper')
ax.scatter([point[0] for point in ls_points],
[point[1] for point in ls_points],
alpha = 0.9)
plt.show()
Run Code Online (Sandbox Code Playgroud)
编辑:OpenStreetMap 声明他们的 tile 服务器不能免费使用并且受使用政策的约束:
https : //operations.osmfoundation.org/policies/tiles/
请在使用示例之前阅读此内容。
由于我在 Python 3.8 中实现代码时遇到问题,我将一些答案合并在一起并修改了代码。现在它对我有用,我没有收到任何错误。
当我尝试在 Python 3 中运行来自 BerndGit 的原始代码时,我必须进行与他的回答中描述的 Joining Dots 相同的更改。我换了
import urllib2
import StringIO
Run Code Online (Sandbox Code Playgroud)
和
import requests
from io import BytesIO
Run Code Online (Sandbox Code Playgroud)
因为 urllib2 库不再适用于 Python 3。您必须使用 urllib.request 或 requests。
然后我不得不从 getImageCluster 函数中更改这两行
imgstr = urllib2.urlopen(imgurl).read()
tile = Image.open(StringIO.StringIO(imgstr))
Run Code Online (Sandbox Code Playgroud)
到
imgstr = requests.get(imgurl)
tile = Image.open(BytesIO(imgstr.content))
Run Code Online (Sandbox Code Playgroud)
之后,我可以无错误地运行代码,但仍然无法下载图像。结果我总是得到一块黑色的瓷砖。通过一些研究,我了解到在使用请求时伪造用户代理很重要,因为网站可以判断请求来自 Python 并且可能会阻止它。以下网站对此
进行了描述:
https : //www.scrapehero.com/how-to-fake-and-rotate-user-agents-using-python-3/
所以我按照网站上的建议添加了这一行就在 getImageCluster 函数的开头:
headers = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36"}
Run Code Online (Sandbox Code Playgroud)
现在我们需要将这些标头包含在请求调用中:
imgstr = requests.get(imgurl, headers=headers)
Run Code Online (Sandbox Code Playgroud)
整个代码现在看起来像这样:
import matplotlib.pyplot as plt
import numpy as np
import math
import requests
from io import BytesIO
from PIL import Image
def deg2num(lat_deg, lon_deg, zoom):
lat_rad = math.radians(lat_deg)
n = 2.0 ** zoom
xtile = int((lon_deg + 180.0) / 360.0 * n)
ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
return (xtile, ytile)
def num2deg(xtile, ytile, zoom):
n = 2.0 ** zoom
lon_deg = xtile / n * 360.0 - 180.0
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n)))
lat_deg = math.degrees(lat_rad)
return (lat_deg, lon_deg)
def getImageCluster(lat_deg, lon_deg, delta_lat, delta_long, zoom):
headers = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36"}
smurl = r"http://a.tile.openstreetmap.org/{0}/{1}/{2}.png"
xmin, ymax =deg2num(lat_deg, lon_deg, zoom)
xmax, ymin =deg2num(lat_deg + delta_lat, lon_deg + delta_long, zoom)
Cluster = Image.new('RGB',((xmax-xmin+1)*256-1,(ymax-ymin+1)*256-1) )
for xtile in range(xmin, xmax+1):
for ytile in range(ymin, ymax+1):
try:
imgurl = smurl.format(zoom, xtile, ytile)
print("Opening: " + imgurl)
imgstr = requests.get(imgurl, headers=headers)
tile = Image.open(BytesIO(imgstr.content))
Cluster.paste(tile, box = ((xtile-xmin)*256 , (ytile-ymin)*255))
except:
print("Couldn't download image")
tile = None
return Cluster
if __name__ == '__main__':
a = getImageCluster(38.5, -77.04, 0.02, 0.05, 13)
fig = plt.figure()
fig.patch.set_facecolor('white')
plt.imshow(np.asarray(a))
plt.show()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10172 次 |
| 最近记录: |