【问题标题】:Overlay/Fill country boundaries with image in用图像覆盖/填充国家边界
【发布时间】:2021-03-03 20:47:45
【问题描述】:

有没有办法使用自定义库here 用类似于 R 解决方案的图像填充国家/地区:

我有一个填充面部颜色的解决方案,例如下面的意大利是蓝色的。但是,我想添加意大利国旗。 Python中有没有办法(搜索后我没有找到太多)或者需要像QGIS这样的东西:

#create a map where I can load images in to fill the countries
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.io.shapereader as shpreader

flag = "italy.png" #this is a locally saved png.

plt.figure(figsize=(15, 15)) #size of plot
ax = plt.axes(projection=cartopy.crs.TransverseMercator(25))
ax.add_feature(cartopy.feature.BORDERS, linestyle='-', alpha=1)
ax.coastlines(resolution='110m') #simplifies the border lines
ax.add_feature(cartopy.feature.OCEAN, facecolor="#40e0d0") #colour of ocean
# ax.gridlines() #adds global grid lines
ax.set_extent ((-7.5, 50, 34, 69), cartopy.crs.PlateCarree()) #makes it european


shpfilename = shpreader.natural_earth(resolution='110m',
                                      category='cultural',
                                      name='admin_0_countries')

for country in shpreader.Reader(shpfilename).records():
    if country.attributes['NAME_LONG'] == "Italy":
        ax.add_geometries(country.geometry, ccrs.PlateCarree(),
                          facecolor="blue",
                          #no attribute like this img= "fd",

                          label=country.attributes['NAME_LONG'])

plt.show()

任何帮助,非常感谢!

【问题讨论】:

  • 仅供参考。对于新用户,在获得 25 分之前,您不能投票给我的答案吗?声望点。但是您可以将其标记为“已接受”,并获得“+2”声望。 stackoverflow.com/help/someone-answers

标签: python matplotlib geospatial matplotlib-basemap cartopy


【解决方案1】:

这是一个演示代码,可以满足您的需要。其实cartopy logo就是用这种技术来创作的。

import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.io.shapereader as shpreader
import matplotlib.patches as mpatches
import numpy as np

imdat1 = plt.imread('flag-of-italy.jpg', format='jpg') # use your flag

plt.figure(figsize=(8, 8))
ax = plt.axes(projection=cartopy.crs.TransverseMercator(25))
ax.add_feature(cartopy.feature.BORDERS, linestyle='-', alpha=1)
ax.coastlines(resolution='110m')
ax.add_feature(cartopy.feature.OCEAN, facecolor="#40e0d0")
# ax.gridlines() #adds global grid lines
ax.set_extent ((-7.5, 50, 24, 69), cartopy.crs.PlateCarree())

shpfilename = shpreader.natural_earth(resolution='110m',
                                      category='cultural',
                                      name='admin_0_countries')

italy_ctry = None  #use this to grab italy's

for country in shpreader.Reader(shpfilename).records():
    if country.attributes['NAME_LONG'] == "Italy":
        italy_ctry = country
        ax.add_geometries(country.geometry, ccrs.PlateCarree(),
                          facecolor="none",
                          alpha=0.7,
                          zorder=2,
                          label=country.attributes['NAME_LONG'])

# create mpatch from `italy` geometry
cg = italy_ctry.geometry
cg2 = cg.simplify(0.02)

if cg2.geometryType()=='MultiPolygon':
    # if == `Polygon`, dont need to loop
    for ea in cg2.geoms:
        cg2xy = ea.exterior.xy  # tuple of (x,y)
        xys = []
        for ea in zip(cg2xy[0], cg2xy[1]):
            #print(ea[0],ea[1])
            xys.append([ea[0],ea[1]])

        # add a patch
        poly = mpatches.Polygon(xys, closed=True, ec='r', \
                                lw=2, fc='yellow', \
                                transform=ccrs.PlateCarree(), \
                                alpha=0.5, zorder=30)

        plate_carree_transform = ccrs.PlateCarree()._as_mpl_transform(ax)

        xtent1 = (6.519950, 17.122259, 35.783370, 47.962952)
        imdat2 = ax.imshow(imdat1, origin='upper', extent=xtent1, \
            transform=ccrs.PlateCarree(), \
            zorder=15, alpha=.9)

        ##imdat2 = ax.stock_img()  #for testing
        imdat2.set_clip_path(mpatches.Path(xys), transform=plate_carree_transform) 
    pass

plt.show()

示例图(因使用的标志而异):

【讨论】:

  • 赞赏。您从哪里提取覆盖范围的 xtent1 值?如果它是动态的并且说我用西班牙取代了意大利,那么这些价值观肯定也必须改变吗?谢谢
  • @Andrew 每个country.geometry 都提供坐标,可以对其进行处理以获得其 LL 和 UR 角。我没有在代码中这样做,而是在地图上阅读它们。这是一个很好的问题,您可以将其作为新问题发布。
  • 谢谢,LL 和 UR:左下角和右上角?我怀疑其他两个是右下右上?只是为了确认一下,您在地图上阅读它们是什么意思?您是如何从 country.geometry 的输出中计算得出这些数字的?谢谢,我会在确认后问这个
  • 谢谢,您从哪里得到/如何计算 xtent1 的数字?是来自另一个答案还是类似的东西?谢谢
  • @Andrew 对于意大利的确切 LL/UR(角)边界,您可以使用 cg.bounds 并以度为单位获取 (lonmin,latmin,lonmax,latmax)。在我的代码中,我使用了它的粗略值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-10
  • 1970-01-01
  • 2023-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多