保存cartopy地图图像以供将来绘图使用

问题描述 投票:0回答:1

我正在使用 cartopy 在 GoogleTiles 卫星图像上绘制动画轨迹。我独立生成数千个帧,然后将它们 ffmpeg-ing 在一起,似乎保存地图图像并加载并用于未来的帧会更有效,而不是每次都从 Google 重新加载地图。

目前代码如下所示:

import cartopy.io.img_tiles as cimgt

google = cimgt.GoogleTiles(style='satellite')

ax = plt.axes(projection=google.crs)
ax.set_extent([west, east, south, north])
ax.add_image(google, 13)
ax.plot(data[t])

plt.savefig(fname = f'frame{t}.png')

并且此代码批量运行,其中

t
代表每个单独的帧。有没有办法保存然后加载地图图像以避免每次调用
cimgt.GoogleTiles()

python matplotlib cartopy
1个回答
0
投票

首先,我对相关代码行的评论:-

  google = cimgt.GoogleTiles(style='satellite')
  ax = plt.axes(projection=google.crs)
  1. 每次运行绘图时,都会请求多个 Google 平铺图像。
  2. 平铺图像(始终为正方形)总共将覆盖大于指定绘图范围的范围。
  3. 绘图过程会将平铺图像裁剪到指定的绘图范围。
  4. 始终使用上述代码的过程并未针对绘制使用公共底图的许多绘图的数组进行优化。

我的回答将尝试优化上述流程。

  1. Google 平铺图像将被请求一次并缓存(以供下次使用)
  2. 平铺图像将在第一次尝试中被裁剪到绘图范围,然后...
  3. 剪切的图像数据与其他相关信息(颜色图)一起提取
  4. 获得的图像数据数组及其颜色图是我们需要作为底图的本质 绘制一系列地图

以下是有效的演示代码。

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.io.img_tiles as cimgt
import matplotlib.cm as cm
import numpy as np
import matplotlib
import cartopy
import matplotlib.path as mpath

# For demo purposes
extentd = [99.65, 101.25, 12.5, 13.75] #west,east,south,north
zoomlev = 9
noproj = ccrs.PlateCarree()
#geodproj = ccrs.Geodetic()
mercator = ccrs.Mercator()

# Setup style of map
google = cimgt.GoogleTiles(style='satellite', cache=True)
# Setup proper projection that can do clipping
#  to meet the requirement
# There may be some warning about this

# Create a plot axes of choice
ax = plt.axes(projection=mercator)     
ax.set_extent(extentd, crs=noproj)
# Request and process the images
imgfactory = ax.add_image(google, zoomlev)

# Check plot of the extent 
ax.plot([extentd[0], extentd[1]], [extentd[2], extentd[3]], 'or-', 
        transform=ccrs.PlateCarree(), markersize=12, zorder=21)

# OK using plot_coords
#plot_coords(ax, polyx.exterior)
plt.title('Clipped Images from Google Tiles')
plt.show()

第一个绘图完成后,我们就可以获取在实际绘图中有用的隐藏信息。

# Get 'child0' object that contains the image data array
for ix,child in enumerate(ax.get_children()):
    #print(child, type(child))
    if isinstance(child, matplotlib.image.AxesImage):
        print("* Found image object.")
        child0 = child
        ccmap = child0.get_cmap()
        img_array = child0.get_array()
        break
    pass

在这一步,我们有

  • ccmap
    ,数据数组的颜色图
  • img_array
    ,代表剪切图像的数据数组。

两者都将在多张地图中重复使用。

它们可以保存到文件中以供将来使用。

接下来,我们使用数据数组进行检查图。

# Check plot of the image data array
# Note the use of 'img_array' and 'ccmap'
# This uses basic matplotlib axes
#  and use degrees as basic units
ax2 = plt.subplot(111)
ax2.imshow(img_array, extent=extentd , origin='lower', cmap=ccmap)

plt.title('Image_data array aligned to lat-long extent')
plt.show()

最后一步,获得需要公共底图的最终绘图数组。

# Plot 3x2 array of maps
rows = 3
cols = 2

# Prep (x,y) data for extra features on each plot
xss = np.linspace(99.65, 101.25, 36)
# yss = 13+np.random.random(36)/2

# This uses PlateCarree projection, other projection can be problematic
fig, ax = plt.subplots(nrows=rows, ncols=cols, figsize=(13, 15), 
                       subplot_kw={'projection': ccrs.PlateCarree()})

# This uses Mercator 
# Warning, image array takes v. long time to do image warping
#fig, ax = plt.subplots(nrows=rows, ncols=cols, figsize=(5.2, 6), 
#                       subplot_kw={'projection': ccrs.Mercator()})

for i in range(rows):
    for j in range(cols):
        # Plot base raster map, using data array
        ax[i][j].imshow(child0.get_array(), origin='lower', 
                        cmap=child0.get_cmap(), extent=extentd, zorder=10)

        # Plot individual data sets on subplots
        ax[i][j].plot(xss, 13+np.random.random(len(xss))/2, 
                      color='cyan', zorder=20, 
                      transform=ccrs.PlateCarree(), linewidth=2)
        # Write map title
        ax[i][j].set_title("Row:"+str(i)+", Col:"+str(j))
        ax[i][j].set_extent(extentd)
        gl=ax[i][j].gridlines(crs=ccrs.PlateCarree(), draw_labels=[1,1,0,0], 
                           lw=1, color='white', linestyle='--', zorder=20)
        gl.top_labels = False
        gl.right_labels = False
    pass

plt.tight_layout()
plt.show()

© www.soinside.com 2019 - 2024. All rights reserved.