matplotlib 提高CartopyMap的分辨率

ruarlubt  于 2023-10-24  发布在  其他
关注(0)|答案(2)|浏览(145)

下面的代码生成了一幅美国Map,每个州都有一条等高线。问题是图像看起来像是用20世纪90年代的技术生成的。我如何才能显著提高图像的质量,即提高背景的分辨率?

import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader

import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 400

fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1], projection=ccrs.LambertConformal())
ax.set_extent([-125, -66.5, 20, 50], ccrs.Geodetic())
ax.stock_img()

shapename = 'admin_1_states_provinces_lakes_shp'
states_shp = shpreader.natural_earth(resolution='110m', category='cultural',
                                     name=shapename)

ax.outline_patch.set_visible(False)  # don't draw the map border
ax.set_title('My map of the lower 48')

# example state coloring
colors = {
    'Minnesota': [0, 1, 0],
    'Texas': "#FF0000",
    'Montana': "blue",
}
default_color = [0.9375, 0.9375, 0.859375]

for state in shpreader.Reader(states_shp).records():
    facecolor = colors.get(state.attributes['name'], default_color)
    ax.add_geometries([state.geometry], ccrs.PlateCarree(),
                      facecolor=facecolor, edgecolor='black', alpha=0.5,linewidth=0.1)

# example data
df = pd.DataFrame(columns=['city', 'lat', 'lon'], data=[
    ('Hoboken', 40.745255, -74.034775),
    ('Port Hueneme', 34.155834, -119.202789),
    ('Auburn', 42.933334, -76.566666),
    ('Jamestown', 42.095554, -79.238609),
    ('Fulton', 38.846668, -91.948059),
    ('Bedford', 41.392502, -81.534447)
])

ax.plot(df['lon'], df['lat'], transform=ccrs.PlateCarree(),
        ms=8, ls='', marker='*')
#plt.show()
plt.savefig("usa.png")
plt.close()

b1zrtrql

b1zrtrql1#

低质量的图像是由库存图像(ax.stock_img())造成的,原因不明,我的质量非常差。我找到了以下解决方案:
(1)不使用任何背景,但添加一些功能:

fig = plt.figure()
ax = plt.axes(projection=cartopy.crs.PlateCarree())
ax.add_feature(cartopy.feature.LAND)
ax.add_feature(cartopy.feature.OCEAN)
ax.add_feature(cartopy.feature.COASTLINE,linewidth=0.3)
ax.add_feature(cartopy.feature.BORDERS, linestyle=':',linewidth=0.3)
ax.add_feature(cartopy.feature.LAKES, alpha=0.5)
ax.add_feature(cartopy.feature.RIVERS)
ax.set_extent([-125, -66.5, 20, 50])

此解决方案的另一个示例为here

(2)使用自定义背景图片。此解决方案需要下载底图背景图片,例如Blue MarbleETOPO Global Relief。根据这些instructions,下载后,您必须设置全局环境变量:CARTOPY_USER_BACKGROUNDS=path_to_map_folder,指向存储下载Map的文件夹。此外,你必须创建一个名为images.json的JSON文件,并将其存储在同一个文件夹中。JSON文件的示例内容:

{"__comment__": "JSON file specifying the image to use for a given type/name and resolution. Read in by cartopy.mpl.geoaxes.read_user_background_images.",
  "BM": {
    "__comment__": "Blue Marble Next Generation, July ",
    "__source__": "https://neo.sci.gsfc.nasa.gov/view.php?datasetId=BlueMarbleNG-TB",
    "__projection__": "PlateCarree",
    "low": "bluemarble1degrees.jpeg",
    "high": "bluemarble01degrees.jpeg"},
  "ETOPO": {
    "__comment__": "ETOPO",
    "__source__": "https://www.ngdc.noaa.gov/mgg/global/global.html",
    "__projection__": "PlateCarree",
    "high": "color_etopo1_ice_low.jpg"}
}

最后,可以使用以下代码添加所需的背景:

fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1], projection=ccrs.PlateCarree())
ax.set_extent([-125, -66.5, 20, 50], ccrs.Geodetic())
ax.background_img(name='ETOPO', resolution='high')

上面的代码将使用ETOPO背景。要使用Blue Marble背景,请将最后一行更改为:ax.background_img(name='BM', resolution='high')。请注意,name和resolution参数必须与JSON文件中的条目匹配。
ETOPO:

蓝色大理石:

最后,根据这个Kaggle post,它还必须能够直接加载底图作为图像背景。这将更加方便,因为它绕过了设置环境变量和编写JSON文件的步骤:

fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1], projection=ccrs.PlateCarree())
ax.set_extent([-125, -66.5, 20, 50], ccrs.Geodetic())
img = plt.imread('./bluemarble01degrees.jpeg')
img_extent = (-125, -66.5, 20, 50)
ax.imshow(img, origin='upper', extent=img_extent, transform=ccrs.PlateCarree())

不幸的是,我没有得到上述解决方案的工作,因为它不放大Map的相关部分:

wqnecbli

wqnecbli2#

我刚刚回答了一个非常类似的问题here-可能也是这篇文章感兴趣的。有了这个解决方案,人们可以添加高分辨率的自然地球背景images到任何CartopyMap投影。我用pyinterp而不是imshow来做图像的空间插值-因为后者对于高分辨率数据来说非常慢。这里是一个(放大)示例:x1c 0d1x

相关问题