提高Cartopy地图的分辨率

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

以下代码生成美国地图,其中每个州都有等高线。问题是该图像看起来像是使用 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()

python matplotlib cartopy
2个回答
4
投票

低质量图像是由库存图像(

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])

此解决方案的另一个示例可以在此处

找到

(2) 使用自定义背景图片。 此解决方案需要下载底图背景图像,例如 Blue MarbleETOPO Global Relief。 根据这些说明,下载后,您必须设置一个全局环境变量:

CARTOPY_USER_BACKGROUNDS=path_to_map_folder
,它指向存储下载的地图的文件夹。此外,您必须创建一个名为
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背景。要使用蓝色大理石背景,请将最后一行更改为:

ax.background_img(name='BM', resolution='high')
。请注意,名称和解析参数必须与 JSON 文件中的条目匹配。

ETOPO: 蓝色大理石:

最后,根据这篇Kaggle帖子,还必须可以直接加载底图作为图像背景。这会更方便,因为它绕过了设置环境变量和编写 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())

不幸的是,我没有使上述解决方案发挥作用,因为它没有放大地图的相关部分:


0
投票

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

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