以下代码生成美国地图,其中每个州都有等高线。问题是该图像看起来像是使用 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()
低质量图像是由库存图像(
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 Marble 或 ETOPO 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 文件中的条目匹配。
最后,根据这篇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())
不幸的是,我没有使上述解决方案发挥作用,因为它没有放大地图的相关部分: