如何在 python(笔记本)中使用高分辨率的卫星背景图像在 map 上绘制 (lat, lon, value)
数据?
我正在搜索整个互联网,但找不到任何有用的东西。 Folium不提供卫星图 block 。 SimpleKML和 googleearthplot似乎只对巨大的低分辨率地球数据有用。 EarthPy可以接受图像 block ,但它们到 NASA 网站的链接仅提供 >0.1 度的低分辨率图像。 Cartopy是 matplotlib 用户的新希望,但我找不到卫星图像 block 的任何示例。
挫败感特别大,因为使用 R
,使用 RGoogleMaps 可以非常轻松地完成这项工作。包,例如:
plotmap(lat, lon, col=palette(value), data=mydataframe, zoom = 17, maptype="satellite")
最佳答案
另一种选择是使用 gmplot
.它基本上是一个围绕 Google Maps javascript API 的 python 包装器,允许您生成 .html
文件,在后台使用 map 渲染您的绘图。
在这里我用它来绘制卫星图像背景下的随机游走(默认情况下不支持这种 map 类型,但让它工作非常简单):
from gmplot import GoogleMapPlotter
from random import random
# We subclass this just to change the map type
class CustomGoogleMapPlotter(GoogleMapPlotter):
def __init__(self, center_lat, center_lng, zoom, apikey='',
map_type='satellite'):
super().__init__(center_lat, center_lng, zoom, apikey)
self.map_type = map_type
assert(self.map_type in ['roadmap', 'satellite', 'hybrid', 'terrain'])
def write_map(self, f):
f.write('\t\tvar centerlatlng = new google.maps.LatLng(%f, %f);\n' %
(self.center[0], self.center[1]))
f.write('\t\tvar myOptions = {\n')
f.write('\t\t\tzoom: %d,\n' % (self.zoom))
f.write('\t\t\tcenter: centerlatlng,\n')
# This is the only line we change
f.write('\t\t\tmapTypeId: \'{}\'\n'.format(self.map_type))
f.write('\t\t};\n')
f.write(
'\t\tvar map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);\n')
f.write('\n')
initial_zoom = 16
num_pts = 40
lats = [37.428]
lons = [-122.145]
for pt in range(num_pts):
lats.append(lats[-1] + (random() - 0.5)/100)
lons.append(lons[-1] + random()/100)
gmap = CustomGoogleMapPlotter(lats[0], lons[0], initial_zoom,
map_type='satellite')
gmap.plot(lats, lons, 'cornflowerblue', edge_width=10)
gmap.draw("mymap.html")
您可以在浏览器中打开生成的 .html
文件,并像与 Google map 一样进行交互。
不幸的是,这意味着你不会得到一个漂亮的 matplotlib
图形窗口或任何东西,所以为了生成一个图像文件,你需要自己截屏或者破解一些东西来渲染 HTML你。
要记住的另一件事是您可能需要一个 Google Maps API key ,否则你会像我一样得到一张丑陋的深色水印 map :
此外,由于您希望将值描述为颜色,因此您需要手动将这些值转换为颜色字符串并使用 gmap.scatter()
方法。如果您对这种方法感兴趣,请告诉我,这样我就可以尝试编写一些代码来实现这一点。
更新
这是一个支持将值编码为卫星图像散点图中颜色的版本。为了实现这种效果,我使用了 matplotlib
的颜色图。如果需要,您可以更改颜色图,请参阅选项列表 here .我还包含了一些代码以从文件 apikey.txt
中读取 API key ,这允许每个研究人员使用他们自己的个人 key 而不更改代码(如果没有找到这样的文件,默认为没有像往常一样的 API key )。
import matplotlib.pyplot as plt
from matplotlib.colors import Normalize
from matplotlib.cm import ScalarMappable
from gmplot import GoogleMapPlotter
from random import random
class CustomGoogleMapPlotter(GoogleMapPlotter):
def __init__(self, center_lat, center_lng, zoom, apikey='',
map_type='satellite'):
if apikey == '':
try:
with open('apikey.txt', 'r') as apifile:
apikey = apifile.readline()
except FileNotFoundError:
pass
super().__init__(center_lat, center_lng, zoom, apikey)
self.map_type = map_type
assert(self.map_type in ['roadmap', 'satellite', 'hybrid', 'terrain'])
def write_map(self, f):
f.write('\t\tvar centerlatlng = new google.maps.LatLng(%f, %f);\n' %
(self.center[0], self.center[1]))
f.write('\t\tvar myOptions = {\n')
f.write('\t\t\tzoom: %d,\n' % (self.zoom))
f.write('\t\t\tcenter: centerlatlng,\n')
# Change this line to allow different map types
f.write('\t\t\tmapTypeId: \'{}\'\n'.format(self.map_type))
f.write('\t\t};\n')
f.write(
'\t\tvar map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);\n')
f.write('\n')
def color_scatter(self, lats, lngs, values=None, colormap='coolwarm',
size=None, marker=False, s=None, **kwargs):
def rgb2hex(rgb):
""" Convert RGBA or RGB to #RRGGBB """
rgb = list(rgb[0:3]) # remove alpha if present
rgb = [int(c * 255) for c in rgb]
hexcolor = '#%02x%02x%02x' % tuple(rgb)
return hexcolor
if values is None:
colors = [None for _ in lats]
else:
cmap = plt.get_cmap(colormap)
norm = Normalize(vmin=min(values), vmax=max(values))
scalar_map = ScalarMappable(norm=norm, cmap=cmap)
colors = [rgb2hex(scalar_map.to_rgba(value)) for value in values]
for lat, lon, c in zip(lats, lngs, colors):
self.scatter(lats=[lat], lngs=[lon], c=c, size=size, marker=marker,
s=s, **kwargs)
initial_zoom = 12
num_pts = 40
lats = [37.428]
lons = [-122.145]
values = [random() * 20]
for pt in range(num_pts):
lats.append(lats[-1] + (random() - 0.5)/100)
lons.append(lons[-1] + random()/100)
values.append(values[-1] + random())
gmap = CustomGoogleMapPlotter(lats[0], lons[0], initial_zoom,
map_type='satellite')
gmap.color_scatter(lats, lons, values, colormap='coolwarm')
gmap.draw("mymap.html")
作为示例,我使用了一系列单调递增的值,这些值在 coolwarm
颜色图中很好地从蓝色阴影映射到红色:
关于python - 在卫星 map 上绘制数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53873673/