没有河流的世界地图有matplotlib/Basemap?

Sam*_*der 20 python maps geography matplotlib matplotlib-basemap

有没有办法用Basemap绘制大陆的边界(或者没有底图,如果有其他方式),没有那些令人讨厌的河流出现?尤其是那条甚至没有到达海洋的孔戈河,令人不安.

编辑:我打算在地图上进一步绘制数据,比如在地图库中(并且仍然将大陆的边界线绘制为数据上的黑线,以提供世界地图的结构),所以虽然下面的Hooked解决方案很好,甚至是熟练的,它不适用于此目的.

世界地图

图片制作者:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(8, 4.5))
plt.subplots_adjust(left=0.02, right=0.98, top=0.98, bottom=0.00)
m = Basemap(projection='robin',lon_0=0,resolution='c')
m.fillcontinents(color='gray',lake_color='white')
m.drawcoastlines()
plt.savefig('world.png',dpi=75)
Run Code Online (Sandbox Code Playgroud)

Rut*_*ies 12

出于这样的原因,我经常完全避免使用Basemap并使用OGR读取shapefile并将其转换为Matplotlib艺术家.这是更多的工作,但也提供了更多的灵活性.

底图具有一些非常简洁的功能,例如将输入数据的坐标转换为"工作投影".

如果你想坚持使用Basemap,请获取一个不包含河流的shapefile.例如,Natural Earth在物理部分有一个很好的"Land"shapefile(下载'scale rank'数据和uncompress).见http://www.naturalearthdata.com/downloads/10m-physical-vectors/

您可以使用Basemap中的m.readshapefile()方法读取shapefile.这允许您在投影坐标中获取Matplotlib路径顶点和代码,然后可以将其转换为新路径.它有点迂回,但它为您提供Matplotlib的所有样式选项,其中大部分都不能通过Basemap直接获得.它有点hackish,但我现在不坚持Basemap的另一种方式.

所以:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from matplotlib.collections import PathCollection
from matplotlib.path import Path

fig = plt.figure(figsize=(8, 4.5))
plt.subplots_adjust(left=0.02, right=0.98, top=0.98, bottom=0.00)

# MPL searches for ne_10m_land.shp in the directory 'D:\\ne_10m_land'
m = Basemap(projection='robin',lon_0=0,resolution='c')
shp_info = m.readshapefile('D:\\ne_10m_land', 'scalerank', drawbounds=True)
ax = plt.gca()
ax.cla()

paths = []
for line in shp_info[4]._paths:
    paths.append(Path(line.vertices, codes=line.codes))

coll = PathCollection(paths, linewidths=0, facecolors='grey', zorder=2)

m = Basemap(projection='robin',lon_0=0,resolution='c')
# drawing something seems necessary to 'initiate' the map properly
m.drawcoastlines(color='white', zorder=0)

ax = plt.gca()
ax.add_collection(coll)

plt.savefig('world.png',dpi=75)
Run Code Online (Sandbox Code Playgroud)

得到:

在此输入图像描述


Hoo*_*ked 7

如何删除"恼人的"河流:

如果您想对图像进行后期处理(而不是直接使用Basemap),您可以移除未连接到海洋的水体:

import pylab as plt
A = plt.imread("world.png")

import numpy as np
import scipy.ndimage as nd
import collections

# Get a counter of the greyscale colors
a      = A[:,:,0]
colors = collections.Counter(a.ravel())
outside_and_water_color, land_color = colors.most_common(2)

# Find the contigous landmass
land_idx = a == land_color[0]

# Index these land masses
L = np.zeros(a.shape,dtype=int) 
L[land_idx] = 1
L,mass_count = nd.measurements.label(L)

# Loop over the land masses and fill the "holes"
# (rivers without outlays)
L2 = np.zeros(a.shape,dtype=int) 
L2[land_idx] = 1
L2 = nd.morphology.binary_fill_holes(L2)

# Remap onto original image
new_land = L2==1
A2 = A.copy()
c = [land_color[0],]*3 + [1,]
A2[new_land] = land_color[0]

# Plot results
plt.subplot(221)
plt.imshow(A)
plt.axis('off')

plt.subplot(222)
plt.axis('off')
B = A.copy()
B[land_idx] = [1,0,0,1]
plt.imshow(B)

plt.subplot(223)
L = L.astype(float)
L[L==0] = None
plt.axis('off')
plt.imshow(L)

plt.subplot(224)
plt.axis('off')
plt.imshow(A2)

plt.tight_layout()  # Only with newer matplotlib
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

第一幅图像是原始图像,第二幅图像是土地质量.第三个不是必需的,而是有趣的,因为它是每个独立的连续陆地.第四张照片是你想要的,删除了"河流"的图像.


Sam*_*der 3

按照 user1868739 的示例,我可以仅选择我想要的路径(对于某些湖泊): 世界2

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(8, 4.5))
plt.subplots_adjust(left=0.02, right=0.98, top=0.98, bottom=0.00)
m = Basemap(resolution='c',projection='robin',lon_0=0)
m.fillcontinents(color='white',lake_color='white',zorder=2)
coasts = m.drawcoastlines(zorder=1,color='white',linewidth=0)
coasts_paths = coasts.get_paths()

ipolygons = range(83) + [84] # want Baikal, but not Tanganyika
# 80 = Superior+Michigan+Huron, 81 = Victoria, 82 = Aral, 83 = Tanganyika,
# 84 = Baikal, 85 = Great Bear, 86 = Great Slave, 87 = Nyasa, 88 = Erie
# 89 = Winnipeg, 90 = Ontario
for ipoly in ipolygons:
    r = coasts_paths[ipoly]
    # Convert into lon/lat vertices
    polygon_vertices = [(vertex[0],vertex[1]) for (vertex,code) in
                        r.iter_segments(simplify=False)]
    px = [polygon_vertices[i][0] for i in xrange(len(polygon_vertices))]
    py = [polygon_vertices[i][2] for i in xrange(len(polygon_vertices))]
    m.plot(px,py,linewidth=0.5,zorder=3,color='black')

plt.savefig('world2.png',dpi=100)
Run Code Online (Sandbox Code Playgroud)

但这仅在对大陆使用白色背景时才有效。如果我将其更改color'gray'下一行,我们会看到其他河流和湖泊的颜色与大陆不同。(玩弄也area_thresh不会移除那些与海洋相连的河流。)

m.fillcontinents(color='gray',lake_color='white',zorder=2)
Run Code Online (Sandbox Code Playgroud)

世界3

白色背景的版本足以进一步对大陆上的所有类型的土地信息进行颜色绘制,但如果想保留大陆的灰色背景,则需要更复杂的解决方案。