GeeMap笔记
GeeMap是Google Earth Engine代码编辑器的python版本,接入了其平台的各类API接口以及其自定义函数,从而实现了在Python中调用平台资源和进行各种运算、输出等功能,由于笔者并非计算机科班出身,因此一开始接触编程也是以Python为主,在学习到Google Earth Engine时,发现其官方平台以及网络上大多数资源都是以js语言为主,与其学习一门新语言,不如把一门语言学的更透一点,抱着这样的想法,我开始学习geemap,学习资源主要来自吴秋生1老师。
geemap包安装
这里不再赘述,在该网站上有详细教程2
首次授权以及初始化
import gemap
import ee
import os
geemap.set_proxy(port=10809) # 国内的用户要先设置代理端口
ee.Authenticate() # 后续会弹出网页,登录Google earth engine后创建一个工作空间类似的东西后继续点下去会有一个授权码一样的东西,复制过来回车就行
ee.Initialize() # 初始化方法1
Map = geemap.Map() # 初始化方法2,同时也是创建一个实例化地图交互对象
创建地图
Map = geemap.Map() # 最基础的
Map = geemap.Map(center=[lat, lon], height=value, width=value, basemap="str") # 依次是显示的中心经纬度、显示高度、宽度和要添加显示的底图
Map.add_basemap("str") # 同时也可以向创建好的地图中添加底图
geemap.basemap.keys() # 其中存放着geemap库中包含的所有底图名称,可以用列表推导式或者for循环给打印出来
# 同时可以添加在线底图,不是目前学习的重点,因此不再赘述
Map = geemap.Map(center=[35.531978, 112.951408], zoom=9, height=500, width=800, basemap="OpenStreetMap.CH") # 显示效果如下图
Google Earth Engine(下文简称GEE或gee)的数据获取
gee数据类型
数据类型/对象方法 | 简单描述 |
---|---|
Geometry | 没有属性表的单一形状 |
Feature | 带有属性表的单个矢量要素 |
FeatureCollection | 带有属性表的矢量要素数据集 |
Image | 单幅栅格影像 |
ImageCollection | 栅格影像数据集 |
Reducer | 用于计算统计或者汇总的对象 |
Join | 某些数据集按照某种规则(如相同时间范围、相同位置、或者某些相同属性)的交集集合 |
Array | 数组 |
Chart | 图表 |
gee中对这些属性的大致解释如下3
Geometry数据类型的多种形式4。
几何类型 | 说明 |
---|---|
Point | 点 |
LineString | 线段 |
LinearRing | 多边形 |
Rectangle | 矩形 |
Polygon | 多边形面 |
Geometry对象的几种手动创建方式
# 可以创建点、线段、多边形、矩形、多边形面
point = ee.Geometry.Point([113.598234, 35.18936]) # 点坐标,注意是经度在前,纬度在后
lineString = ee.Geometry.LineString([[113.898234, 35.18936], [114.898234, 36.18936], [114.398234, 36.28936]]) # 线段顶点坐标,不闭合
linearRing = ee.Geometry.LinearRing([[113.398234, 35.08936], [114.598234, 36.08936], [114.398234, 36.28936]]) # 多边形顶点坐标,最后一个点自动与第一个点连接,闭合
rectangle = ee.Geometry.Rectangle([113.398234, 35.08936, 114.598234, 36.08936]) # 矩形顶点坐标,闭合
polygon = ee.Geometry.Polygon([[[113.398234, 35.08936], [113.198234, 35.18936], [113.098234, 34.98936]]]) # 多边形顶点坐标,最后一个点自动与第一个点连接,闭合,并且可以创建多个,因此[]个数也与其他几个不一样
# 该部分不再可视化
geometrySet = ee.Geometry.MultiPoint([[114.898234, 36.18936], [114.398234, 36.28936]]) # 多点坐标
pointSet = geometrySet.geometries() # 拆分要素
point1 = pointSet.get(0) # 获取第一个要素
point2 = pointSet.get(1) # 获取第二个要素
Map.addLayer(point, {"color": "red"}, 'point')
Map.addLayer(lineString, {"color": "blue"}, 'lineString')
Map.addLayer(linearRing, {"color": "green"}, 'linearRing')
Map.addLayer(rectangle, {"color": "yellow"}, 'rectangle')
Map.addLayer(polygon, {"color": "purple"}, 'polygon')
Map
大地几何和平面几何
我们都知道地球坐标系一般分为地理坐标系和投影坐标系(就是从小到大学的平面直角坐标系)定位,因此当我们要将几何形状投影到底图上时也要选择是使用经纬度投影还是平面投影
rectangle1 = ee.Geometry.Rectangle([130.398234, 35.08936, 180.00, 39.08936], None, geodesic=False) # 设置为平面坐标系
rectangle2 = ee.Geometry.Rectangle([130.398234, 35.08936, 180.00, 39.08936], None, geodesic=True) # 设置为地理坐标系
Map.addLayer(rectangle1, {"color": "red"}, 'rectangle1')
Map.addLayer(rectangle2, {"color": "blue"}, 'rectangle2')
Map
关于Geometry对象的一些操作
操作 | 作用 | 备注 | 编号 |
---|---|---|---|
geometry.buffer(value) | 对当前形状取缓冲区 | 单一Polygon(单位为m) | 1 |
geometry.centroid() | 获取当前形状中心点坐标 | 单一Polygon | 2 |
geometry.contains(object) | 判断object是否包含在当前形状中 | 返回一个类字典,要想像js一样获得True或者False需要在后加上.getInfo() | 3 |
geometry.intersection(anotherGeometry, ee.ErrorMargin(1)) | 获取两个形状的交集形状 | ee.ErrorMargin(1)为容许误差(m),以下同理 | 4 |
geometry.union(anotherGeometry, ee.ErrorMargin(1)) | 获取两个形状的并集形状 | 5 | |
geometry.difference(anotherGeometry, ee.ErrorMargin(1)) | 从当前形状中删除其与另一个形状的交集的余下形状 | 6 | |
geometry.symmetricDifference(anotherGeometry, ee.ErrorMargin(1)) | 获取两个形状的交集形状互斥的形状 | 7 |
# 1、2操作演示
polygon = ee.Geometry.Polygon([[[-5, 40], [-6, 41], [-7, 42], [-8, 43], [-9, 43]]], )# 创建一个多边形
buffer = polygon.buffer(10000) # 获对多边形使用缓冲区
centriod = polygon.centroid() # 获取点
Map.addLayer(polygon, {"color": "red"}, 'polygon')
Map.addLayer(buffer, {"color": "blue"}, 'buffer')
Map.addLayer(centriod, {"color": "green"}, 'centriod')
Map
# 3:操作演示
point = ee.Geometry.Point([-50, 30]) # 创建一个点
poly1 = ee.Geometry.Point([-50, 30]).buffer(1e6) # 创建一个点并取缓冲区1e6m
poly2 = ee.Geometry.Point([-40, 30]).buffer(1e6) # # 创建一个点并取缓冲区1e6m
Map.setCenter(-45, 30) # 设置底图显示的中心坐标
Map.addLayer(poly1, {"color": 'FF0000'}, 'poly1') # 添加到地图进行显示
Map.addLayer(poly2, {"color": '0000FF'}, 'poly2')
intersection = poly1.intersection(poly2, ee.ErrorMargin(1)) # 进行相交操作
Map.addLayer(intersection, {"color": '00FF00'}, 'intersection')
union = poly1.union(poly2, ee.ErrorMargin(1)) # 进行合并操作
Map.addLayer(union, {"color": 'FF00FF'}, 'union')
diff1 = poly1.difference(poly2, ee.ErrorMargin(1)) # 进行擦除操作
Map.addLayer(diff1, {"color": 'FFFF00'}, 'diff1')
symDiff = poly1.symmetricDifference(poly2, ee.ErrorMargin(1)) # 进行交集取反操作
Map.addLayer(symDiff, {"color": '000000'}, 'symmetric difference')
print(poly1.contains(poly2).getInfo()) # 判断poly1是否包含poly2
print(poly1.contains(point).getInfo()) # 判断poly1是否包含point
Map
False
True
![]()
![]()
![]()
![]()
以上依次为:
ploy1是否包含poly2,输出为False
ploy1是否包含point,输出为True
ploy1和poly2可视化
相交可视化
合并可视化
擦除可视化
交集取反可视化
Feature&FeatureCollection
Feature
- 前面已经说过,Feature就是在Geometry的基础上添加了属性表,FeatureCollection就是多个Feature的集合
display(object)
可以像gee编辑器里那样显示对象的结构
# Feature
# 1. 创建一个Feature
poly1 = ee.Geometry.Polygon([[[-122, 37],
[-123, 38],
[-124, 36],
[-125, 35]]]) # 首先创建一个几何形状
fea1 = ee.Feature(poly1, {'name': 'feature1'}) # 通过添加字典的形式添加属性表,使其转换为要素
Map.addLayer(fea1, {}, 'feature1')
# Feature中几何形状不是必须的,只创建一个属性表(通过字典的形式)也可以,甚至可以在某个字段进行运算
dic = {'foo': ee.Number(8).add(88), 'bar': 'nihao'}
nowhere_feature = ee.Feature(None, dic)
display(fea1) # 可以像gee编辑器里那样显示对象的结构
Map
- Feature(后面都叫要素了)仍有缓冲区、相交等操作,每一个Feature(要素)都存在一个主要的Geometry(后面都叫形状了)存放在geometry属性中,而其余的形状则存在在其他的属性中(后半段话我没太理解)
FeatureObject.set("字段名", "属性"/数值)
可以用来设置属性表,由于要素只有一个,因此也只能设置一个属性或者数值
# 创建一个点要素并设置属性表
feature = (
ee.Feature(ee.Geometry.Point([-122.22599, 37.17605]))
.set('genus', 'Sequoia')
.set('species', 'sempervirens')
)
# 获取指定字段属性
species = feature.get('species')
display(species)
# 新增一个字段并设置属性
feature = feature.set('presence', 1)
# 覆盖原有的字段名和属性
new_dic = {'genus': 'Brachyramphus', 'species': 'marmoratus'}
feature = feature.set(new_dic)
display(feature)
2024_07_06
FeatureCollection(要素数据集)
-
FeatureCollection的构造方式(
ee.FeatureCollection(features)
)- 1.1. 提供一个要素的列表, 单个要素也可以被转为要素数据集
features = [ ee.Feature(ee.Geometry.Rectangle(30.01, 59.80, 30.59, 60.15), {'name': 'Voronoi'}), ee.Feature(ee.Geometry.Point(-73.96, 40.781), {'name': 'Thiessen'}), ee.Feature(ee.Geometry.Point(6.4806, 50.8012), {'name': 'Dirichlet'}), ] # 构建要素列表 from_list = ee.FeatureCollection(features) # 转化为要素数据集 display(from_list)
- 1.2. gee上的要素数据集
fc = ee.FeatureCollection('RESOLVE/ECOREGIONS/2017') # 获取在gee上的要素数据集 m = geemap.Map() m.set_center(12.17, 20.96, 3) m.add_layer(fc, {}, 'ecoregions') display(m)
- 1.3. 在一个要素范围内随机生成样点(
ee.FeatureCollection.randomPoints(region)
)
# 定义一个形状区域 region = ee.Geometry.Rectangle(-119.224, 34.669, -99.536, 50.064) # 在该区域范围内随机生成1000个样点 random_points = ee.FeatureCollection.randomPoints(region) # 显示 m = geemap.Map() m.center_object(random_points) m.add_layer(random_points, {}, 'random points') m.add_layer(region, {'color': '000000'}, 'region') display(m)
-
要素和要素数据集的可视化
- 2.1. 通过前面的例子我们也可以知道,在将栅格影像或者几何形状等可视化时,都使用了
Map.addLayer(visObject, visParams(dict), name(str))
的函数,其中控制显示化效果的就是visParams的设置,其为字典形式,其中常见的是颜色控制{"color": "red"}
或者{"color": "FF0000"}
,前者是预设好的颜色字符串,后者是R-G-B三原色数字分别转换为16进制后组成的字符串,即FF代表R颜色十进制编码,00和00分别代表G和B颜色十进制编码。 - 2.2. 要素数据集使用其他显示渲染选项的话,还有
featureCollection.draw()
,其中pointRadius
和strokeWidth
参数来控制点的显示半径和线宽
# 从gee获取要素数据集 ecoregions = ee.FeatureCollection('RESOLVE/ECOREGIONS/2017') pointG = ee.Geometry.Point(-76.2486, 44.8988) # 设置形状点 pointF = ee.Feature(pointG) # 将点转化为要素 pointFC = ee.FeatureCollection(pointF) # 将要素转化为要素数据集 # 设置可视化颜色 m = geemap.Map() m.set_center(-76.2486, 44.8988, 8) m.add_layer(ecoregions.draw(color='green', strokeWidth=5), {}, 'drawn') # 设置面要素数据集的颜色和线宽 m.add_layer(pointFC.draw(color='red', pointRadius=20), {}, 'point') # 设置点要素数据集的显示半径 m
*注意:*在形状或者要素对象使用draw()函数会报错,即这两种对象不支持通过该函数设置显示效果
*注意:*在该段代码构建几何形状、要素和要素数据集时,尤其是后两者时,并没有提供属性表,但仍然可以成功。- 2.3. 要对要素数据集的可视化进行更多的控制,可以使用
image.paint()
函数,该函数将要素数据集作为一个输入参数使用
# 创建一个空图像,在其中绘制特征,投影到字节(这句话我没看懂)。 empty = ee.Image().byte() # m = geemap.Map() ecoregions = ee.FeatureCollection('RESOLVE/ECOREGIONS/2017') # 可视化 outline = empty.paint(featureCollection=ecoregions, color=1) # 不设置宽度 outline = empty.paint(featureCollection=ecoregions, color=1, width=10) # 设置宽度 m.add_layer(outline, {'palette': 'FF0000'}, 'paint') # 可视化 m
通过查阅gee中
paint(featureCollection, color, width)
的API说明:在图像上绘制几何图形集合的几何图形,使用给定的 "颜色 "值替换任何几何图形覆盖图像的区域(如果指定了线宽,则替换周长覆盖图像的区域)中每个波段的值。这种算法最适合将特征属性中的分类数据转换为图像中的像素;如果您希望将集合可视化,可以考虑使用 FeatureCollection.style,它支持 RGB 颜色,而这种算法严格来说是 "单色 "的(使用单个数值)。
可以看出来,该函数似乎是把要素数据集的每个要素的几何形状转为了栅格形式进行渲染,通过display()
函数可以看到确实是一个栅格影像格式的对象
- 该方法也可以根据字段属性(字段属性必须是ee.Number类型)进行渲染
outlines = empty.paint(featureCollection=ecoregions, color='BIOME_NUM', width="NNH") # 设置RESOLVE/ECOREGIONS/2017的BIOME_NUM字段为颜色设置基础,线宽也一样 palette = ['FF0000', '00FF00', '0000FF'] # 设置调色板 m.add_layer(outlines, {'palette': palette, 'max': 14}, 'different color edges') # 设置可视化,调色板为palette拉伸显示,最大显示到BIOME_NUM字段的属性14
最终可以看到不一样的颜色和不一样粗的线宽
- 如果想填充和线宽同时显示
filled_outlines = empty.paint(ecoregions, 'BIOME_NUM').paint(ecoregions, 0, "NNH") # 在设置完填充对象后再次设置填充线宽显示 m.add_layer(filled_outlines, {'palette': ['000000'] + palette, 'max': 14}, 'edges and fills') m
- 2.1. 通过前面的例子我们也可以知道,在将栅格影像或者几何形状等可视化时,都使用了
2024/07/06 end
- 要素数据集的信息和元数据
该部分与栅格和栅格数据集的索引方式相同,但是我又是从要素和要素数据集先开始介绍的,因此当前要素和要素数据集部分先暂停,下面从栅格和栅格数据集开始介绍
Image
添加gee数据到地图并可视化
SR2a = ee.ImageCollection("CloudDataReserveID") # 获取gee数据,需要填写该数据在gee上的ID
# 以下为详细举例
# 这里选择了哨兵2号的遥感影像数据集,取其中的第一幅,将其栅格值缩小1w倍,得到真正的反射率值,再选择其中的4、3、2真彩色波段
# 当使用第一个函数.first()后,该SR2a实质上已变成了Image了,因为只取了整个栅格数据集的第一个栅格。
SR2a = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED").first()\
.divide(10000)\
.select("B4", "B3", "B2", )
# 设置可视化参数
visParams = {
"min": 0.0 # 影像显示的最小值
"max": 0.5 # 影像显示的最大值
"bands":["B4", "B3", "B2"] # 三个波段组成真彩色
}
# 进行可视化显示
Map.addLayer(SR2a, visParams, "Sentinel-2A") # 这三个参数位置分别为显示对象、可视化参数设置集、在地图上显示的图层名称
图左为哨兵2数据集在gee中的说明;图右为哨兵2添加到地图后的样子