Python下basemap画出的各种地图 您所在的位置:网站首页 凉山的地图 Python下basemap画出的各种地图

Python下basemap画出的各种地图

2023-08-08 08:26| 来源: 网络整理| 查看: 265

刚接触Python的basemap库时,被它所能产生的效果震撼了。

但是在深入的学习时发现网上很难找到系统的中文教程,仅能搜到一些博客文章里讲到的某些知识点,不成体系,就难以运用自如。

在网上看了看官方文档,又找到了这一使用手册《Basemap tutorial Documentation Release 0.1

Roger Veciana i Rovira》,原作者在这里深入浅出的系统讲解了basemap的用法,有实例、有方法、有探讨、有研究,我在学习的时候受益匪浅,同时边学习边简单的翻译一下,供以后使用之便。

 

正所谓 始于颜值,陷于才华,忠于人品。在翻译的时候,我在保持原手册知识框架的同时,结合我学习的收获,侧重于以下三个层次:

入门 始于颜值。这一章主要是基础的知识,能够从宏观上对basemap有一个直观的印象进阶 陷于才华。这一张主要是高级的用法,这些能让我们进一步领略到basemap的强大之处。 高级 忠于人品。这一张主要是实用技巧,通过各种实例,展现各种技巧,让我们用起来爱不释手,游刃有余!

 

开始吧。。。。(水平有限,文章粗糙,仅供参考

 

1 入门

安装

详细的安装教程在官方文档里已经有所阐述,所以这本使用指南侧重于向大家展示怎样使用Basemap。

在这些案例中,我使用的Linux系统的一些配置情况:

·在Ubuntu系统中,使用Synaptic安装库文件

·在Suse系统(一个老的Linux发行版)中,运行这些代码

以下为译者强行插入:

简单粗暴的安装方法(尤其对于Windows系统总是安装不成攻的时候):

在我经历了各种各样难以名状的坑之后,终于在moxigandashu 的文章种找到了终极解决办法(http://blog.csdn.net/moxigandashu/article/details/68945845)

确认电脑有pip 下载pypro和basemap

通过http://www.lfd.uci.edu/~gohlke/pythonlibs/ 下载两个文件

basemap-1.1.0-cp36-cp36m-win_amd64.whl

pyproj-1.9.5.1-cp36-cp36m-win_amd64.whl

根据电脑配置和使用的Python版本下载对应的文件

打开命令提示符,进入到上面两个文件所在文件夹 安装pypro和basemap:

pip install pyproj-1.9.5.1-cp36-cp36m-win_amd64.whl

pip install basemap-1.1.0-cp36-cp36m-win_amd64.whl

 

下载用户指南

包括示例代码在内的所有文件,都可以在GitHub上找到

https://github.com/rveciana/BasemapTutorial

如果安装有GIT客户端,可以直接用下面命令下载到本地:

git clone https://github.com/rveciana/BasemapTutorial.git

 

画第一张地图

画一张最简单的地图(当然不是小时候每个人都画过的地图#^.^#):

from mpl_toolkits.base import Basemap

import matplotlib.pyplot as plt

 

map = Basemap()

 

map.drawcoastlines()

 

plt.show()

plt.savefig(‘test.png’)

第一行代码引入了Basemap库和matplotlib,这两个都是必须的。 这张地图是由Basemap类创建的,这个类包含很多属性。如果使用默认值,则使用普通圆柱投影模式显示地图。 如果设置了属性,我们就能根据需要创建地图。在这个例子中,用drawcoastlines()方法画出海岸线,海岸线的数据已经默认包含在了库文件中。 最后使用mathplotlip中的方法显示和保存图片,在这个例子中,plt.show()打开一个新的窗口来显示运行结果,plt.savefig(‘file_name’)把运行结果保存为图片。

改变地图的投影方式非常简单,只用在Basemap()中加入projection参数和lat_0, lon_0参数。(关于更多的地图投影只是,可以参考百度百科https://www.baidu.com/link?url=d7mToqKOKCk3Ba60s2HtT-4pEuC4jzHhFqhytovCw2IKA6cu6GiBHuR-V7negpngoN8dKyHBNA8_8y8-GRs1tJ7Q6o2bwDLtuB9277b6L6UrIKTRv2DPJtbw87iv6NeA&wd=&eqid=8077e6880001a123000000025a600f50)

即使使用新的地图投影方式,生成的地图还是丑的一逼,用下面的代码可以给陆地和海洋填上不同的颜色:

From mpl_toolkits.basemp import Basemap

Import matplotlib.pyplot as plt

 

Map = Basemap(projection = ‘ortho’, lat_0 = 0, lon_0 = 0)

# 首先给地球涂上蓝色的一层

map.drawmapboundary(fill_color = ‘aqua’)

# 再给大陆涂上屎黄色,给江河湖泊涂上大海一样的颜色

map.fillcontinents(color = ‘coral’, lake_color = ‘aqua’)

 

map.drawcoastlines()

 

plt.show()

 

Duang~Duang~Duang~见证奇迹的时刻

 

管理地图投影

所有的地图都应该设置投影模式,在创建Basemap对象时要指定投影模式以及相关属性。设置的方法和别的别的库文件有很大的不同,理解到这一点对后面使用Basemap很重要。

 

投影模式

projection参数用来设置投影模式

 

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt map = Basemap(projection = 'cyl') map.drawmapboundary(fill_color = 'aqua') map.fillcontinents(color = 'coral', lake_color = 'aqua') map.drawcoastlines() plt.show()

 

创建的地图是酱紫的,和上面的球球有很大不同:

 

projection默认的值是 cyl,是cylindrical Equidistant projection (等距圆柱投影)的缩写,也叫作等距柱状投影图(Equirectangular projection)或者方格投影(Plate carree)

许多投影模式需要补充额外的参数

 

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt map = Basemap(projection = ‘aeqd’, lon_0 = 10, lat_0 = 50) map.drawmapboundary(fill_color = ‘aqua’) map.fillcontinents(color = ‘coral’, lake_color = ‘aqua’) map.drawcoastlines() plt.show()

 

(谁能告诉我这是什么鬼。。。。还是生我养我的地球吗?)

这张图是以东经10度,北纬50度为中心(欧洲大陆上)绘制的等距投影地图,不同的投影需要不同的参数,具体参阅(https://matplotlib.org/basemap/users/mapsetup.html)

 

利用epsg 设置地图投影

ESPG是一种标准的命名投影方式的数字编码。Basemap允许使用这些标记来创建地图,但只局限于某些特定的情况下。要使用ESPG标记,需要在Basemap()里面加上epsg参数。

Basemap中的/mpl_toolkits/basemap/data/epsg对这种EPSG提供支持,但是有时使用这种方法还是会报错(ValueError: 23031 is not a supported EPSG code),所以不建议使用。

Basemap对带有”utm”的projection支持不太好,但是对带有”tmere”都能很好的支持。

下面的例子是用UTM投影显示祖国宝岛台湾省。

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt map = Basemap(llcrnrlon = 119.3, llcrnrlat = 20.7, urcrnrlon = 124.6, urcrnrlat = 26, resolution = 'h', epsg = 3415) map.drawmapboundary(fill_color = 'aqua') map.fillcontinents(color = 'coral', lake_color = 'aqua') map.drawcoastlines() plt.show()

 

 

extension

 

到目前为止,所有的例子都是在整个地球上画出地图。只绘制某一个区域的地图,可以通过设置地图边界或者地图中心来实现。官方文档说大多数情况下两种方式都通用,但是还有一些例外。

 

注意:使用cyl,merc,mill,cea和gall投影时,如果没有设置边界,那么边界默认设置为-180,-90,180,90(也就是整个球体),其他投影都需要额外设置。

 

通过经纬度设置边界Passing the bounding box(以祖国第二大岛为例)

 

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt map = Basemap(llcrnrlon = 108.3, llcrnrlat = 18, urcrnrlon = 111.5, urcrnrlat = 20.3, resolution = 'i', projection = 'tmerc', lat_0 = 20, lon_0 = 111) map.drawmapboundary(fill_color = 'aqua') map.fillcontinents(color = 'coral', lake_color = 'aqua') map.drawcoastlines() plt.show()

 

 

左下角和右上角的经纬度作为参数传入,

 

在这个例子中,使用UTM(通用墨卡托Transverse Mercator)投影。在这种情况下边界框的方法很好用,因为在UTM中计算地图的宽度非常麻烦。

注意:使用sinu,moll,hammer,npstere,spstere,nplaea,splaea,npaeqd, spaeqd, robin, eck4, kav7,和 mbtfpq投影中,不能使用这种方法。一是因为在有些投影中,整个地球都被绘制出来,二是因为在有些投影中,无法通过地理坐标计算extension的值

 

通过地图坐标设置边界

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt map = Basemap(resolution = 'l', satellite_height = 3000000., projection = 'nsper', lat_0 = 30, lon_0 = 116, llcrnrx = 500000., llcrnry = 500000.,urcrnrx = 2700000.,urcrnry = 2700000.)

 

map.drawmapboundary(fill_color = 'aqua') map.fillcontinents(color = 'coral', lake_color = 'aqua') map.drawcoastlines() plt.show()

----------------------------------------------------------------------------------

 

在一些投影中(类似于卫星图像),使用地图坐标设置extension参数。projection参数必须设置(四个角的位置),然后显示球体的某一个区域。

 

注意:只有在ortho,geos和nsper投影中使用这种方法

 

通过中心坐标和长度、宽度

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt map = Basemap(projection = 'aeqd', lat_0 = 0, lon_0 = 90, width = 10000000,height = 10000000.) map.drawmapboundary(fill_color = 'aqua') map.fillcontinents(color = 'coral', lake_color = 'aqua') map.drawcoastlines() for i in range(0, 10000000, 1000000): map.plot(i, i, marker = 'o', color = 'k') plt.show()

 

在这个例子中,投影的中心,宽度和长度作为projection的参数传入。中心点坐标好确定,就是经纬度的坐标值,但是长和宽就有点复杂了:

长度的单位是米,(0,0)是左下角,(width,height)是右上角。所以说这里的原点不像GDAL中定义的那样。在这种投影里面,之定义区域的大小,不定义原点坐标。

在例子中用plothan函数画了几个点来说明上面原点和投影的关系。

 

 

基本函数

 

在地图上画一个点

 

在地图上画点通常用到plot方法:

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt map = Basemap(projection = 'ortho', lat_0 = 0, lon_0 = 120, width = 10000000,height = 10000000.) map.drawmapboundary(fill_color = 'aqua') map.fillcontinents(color = 'coral', lake_color = 'aqua') map.drawcoastlines() # x是经度,y是纬度 x, y = map(114, 22.4) map.plot(x, y, marker = 'D', color = 'm') plt.show()

通过上面代码,我们在中国的南海边画了一个圈【脑补BGM~~】

 

·用经纬度计算地图坐标的时候

–如果latlon关键字设置为true,x,y将被当做经纬度。但是在老版本的Basemap中不能这样使用。

 

·plot方法绘制点时需要这一点在地图上的坐标,maker和color参数如下

–默认maker是一个点,详细属性在这里http://matplotlib.org/api/markers_api.html

–默认color是黑色(k),详细属性在这里http://matplotlib.org/api/colors_api.html

 

如果要绘制不止一个点,那就用scatter方法吧。把一系列点的坐标收在一个数组里然后把传递到plot方法里,就能够画出一系列点,还能用线段把他们连起来。

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt map = Basemap(projection = 'ortho', lat_0 = 0, lon_0 = 120) map.drawmapboundary(fill_color = 'aqua') # map.fillcontinents(color = 'coral', lake_color = 'aqua') map.drawcoastlines() # 北上广郑四个城市 lons = [ 113.14,113.4,121.29,116.24] lats = [23.08,34.46,31.14,39.55] # x是经度,y是纬度 x, y = map(lons, lats) map.scatter(x, y, marker = 'o', color = 'm') plt.show()

注意:如果map.fillcontinents(),那么填充的颜色会覆盖掉这四个点

 

绘制栅格数据

 

有两个方法可以处理栅格数据,一个是contour/contourf,用来绘制或者填充轮廓;一个是pcolor/pcolormesh,用来创造一个虚拟色彩的点

 

contour

 

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt from osgeo import gdal from numpy import linspace from numpy import meshgrid map = Basemap(projection = 'tmerc', lat_0 = 0, lon_0 = 3, llcrnrlon = 1.819757266426611, llcrnrlat = 41.583851612359275, urcrnrlon = 1.841589961763497, urcrnrlat = 41.598674173123) ds = gdal.Open('dem.tiff') data = ds.ReadAsArray() x = linspace(0, map.urcrnrx, data.shape[1]) y = linspace(0,map.urcrnry, data.shape[0]) xx, yy = meshgrid(x, y) cs = map.contour(xx, yy, data, range(400, 1500, 100), cmap = plt.cm.cubehelix) plt.clabel(cs, inline=True, fmt='%1.0f', fontsize=12, colors='k') plt.show()

 

用range函数设置高层数据。由于是处理高度数据,所以从400到1400米,每根等高线代表100米。

地图没有使用默认的喷绘(对比下面例子),通过设置cmap参数实现

contour方法中的labels可以通过参数设定

--inline可以设定标签(labels)是显示在等高线的上面还是下面

inline = true时, inline = false时,

fmt 格式化数据

fontsize设置标签字体大小

colors 设置标签的颜色。默认和等高线一个色儿。

 

contourf

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt from osgeo import gdal from numpy import linspace from numpy import meshgrid map = Basemap(projection = 'tmerc', lat_0 = 0, lon_0 = 3, llcrnrlon = 1.819757266426611, llcrnrlat = 41.583851612359275, urcrnrlon = 1.841589961763497, urcrnrlat = 41.598674173123) ds = gdal.Open('dem.tiff') data = ds.ReadAsArray() x = linspace(0, map.urcrnrx, data.shape[1]) y = linspace(0,map.urcrnry, data.shape[0]) xx, yy = meshgrid(x, y) map.contourf(xx, yy, data) plt.show()

 

·这个地图和栅格图片一起被绘制出来。

·在绘制轮廓之前,先创建两个矩阵,这两个放的是每一个点的x和y的坐标

-linspace是一个numpy的函数,用来创建一个数组。在这种情况下,地图的坐标从0到map.urcrnrx或map.urcrnry,data.shape[1]和data.shape[0]表示把0到map.urcrnrx或map.urcrnry平均分成多少份。

-meshgrid也是一个numpy函数,把两个数组转化为一个矩阵。

·contuef方法把x,y和矩阵绘制在默认的colormap中,这个过程被称作是喷绘,并且根据高层数据(等高线)自动渲染图像。

·高层数据(等高线)可以在data数组中指定,具体使用方法可以在contour这一章节看到,有两种方法处理这种数据

-- 一个表示等高线的int数据,数据越大,颜色越深

-- 一个包含每一根等高线数据的列表,可以用range函数设置(range(0,3000,100)表示每根等高线高程差是100个单位)

 

 

 

实例中dem.tiff文件下载地址https://github.com/rveciana/BasemapTutorial/blob/master/code_examples/sample_files/dem.tiff

pccoloemesh(立体效果的颜色)

 

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt from osgeo import gdal from numpy import linspace from numpy import meshgrid map = Basemap(projection = 'tmerc', lat_0 = 0, lon_0 = 3, llcrnrlon = 1.819757266426611, llcrnrlat = 41.583851612359275, urcrnrlon = 1.841589961763497, urcrnrlat = 41.598674173123) ds = gdal.Open('dem.tiff') data = ds.ReadAsArray() x = linspace(0, map.urcrnrx, data.shape[1]) y = linspace(0,map.urcrnry, data.shape[0]) xx, yy = meshgrid(x, y) map.pcolormesh(xx, yy, data) plt.show()

 

 

计算地图上一点的位置

from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt map = Basemap(projection = 'aeqd', lat_0 = 50, lon_0 = 10,) print (map(10, 50)) print (map(20015077.3712,20015077.3712, inverse = True))

输出结果:

当invers设置为False时,输入的是经纬度,输出的是该点在以地图坐标表示的坐标值,设置为True时,效果相反

 

shape格式文件的处理

Basemap处理矢量图的方法和其他库文件有很大的不同。

 

基本用法

 

先从简单的入手,用最简单的办法显示一个矢量图(山东半岛)

frommpl_toolkits.basemap import Basemapimport matplotlib.pyplotas pltmap = Basemap(projection= ‘tmerc’,lat_0 = 37, lon_0 = 122,llcrnrlon = 120, llcrnrlat = 36,urcrnrlon = 123., urcrnrlat = 38.,resolution = ‘i’) map.drawmapboundary(fill_color = ‘aqua’) map.fillcontinents(color = ‘#ddaa66’,lake_color = ‘aqua’) map.drawcoastlines() map.readshapefile(‘CHN_adm_shp/CHN_adm1’,‘comarques’) plt.show()print (map(10,50))print (map(20015077.3712,20015077.3712,inverse = True))

·第一个参数 CHN_adm_shp/CHN_adm1不能包含后缀名,程序会假设.shp,.sbf和.shx文件同时存在并且文件名相同

·第二个参数是读取shapfile的方式,我们将在后面详细阐述。

 

使用时的一些限制条件

· 文件必须符合EPSG:4326,或者纬度/经度坐标。如果你的文件不是这种格式,可以使用ogr2ogr加以转换。

· 地图必须是二维地图

· 只要是多边形或者多段线,就能以地图形式显示出来

正如例子中那样,显示的结果只是线段或着多边形。要把这些图形填充起来,可以参照后面讲到的Filling polygons(图形填充)

 

读取点数据

 

在地图上绘制一系列点的话,着实有点复杂。首先读取shapefile中的点的数据,然后把点绘制在地图上,在这个过程中使用scatter,plot或者matplotlib函数。

 

frommpl_toolkits.basemap import Basemapimport matplotlib.pyplotas pltmap = Basemap(projection= ‘tmerc’,lat_0 = 39.5, lon_0 = 1,llcrnrlon = -0.5,llcrnrlat = 39.8,urcrnrlon = 4., urcrnrlat = 43.,resolution = ‘i’) map.drawmapboundary(fill_color = ‘aqua’) map.fillcontinents(color = ‘#ddaa66’,lake_color = ‘aqua’) map.drawcoastlines() map.readshapefile(‘shapefile/comarques’,‘comarques’) lightning_info = map.readshapefile(‘shapefile/lightnings’,‘lightnings’)print (lightning_info)for info, lightning in zip(map.lightnings_info, map.lightnings):if float(info[‘amplitude’])



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有