提高 Cartopy 地图的分辨率

问题描述

以下代码生成一张美国地图,每个州都有一条等高线。问题是图像看起来像是用 1990 年代的技术生成的。如何显着提高图形的质量,即增加背景的分辨率?

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,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,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()

enter image description here

解决方法

低质量图片是由我不知道的质量很差的库存图片 (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

Simple map using features

(2) 使用自定义背景图片。 此解决方案需要下载底图背景图像,例如 Blue MarbleETOPO Global Relief。 根据这些instructions,下载后,您必须设置一个全局环境变量: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","high": "color_etopo1_ice_low.jpg"}
}

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

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

以上代码将使用 ETOPO 背景。要使用蓝色大理石背景,请将最后一行更改为:ax.background_img(name='BM',resolution='high')。请注意,名称和解析参数必须与 JSON 文件中的条目匹配。

埃托波: Etopo map 蓝色大理石: Blue marble map

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

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

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

enter image description here

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...