第一篇:【Python-geemap教程(三)上】3D地形渲染与Landsat NDVI计算

引言

在前两篇内容中,我们完成了基于 Miniconda 搭建 geemap + Google Earth Engine (GEE) 的开发环境,并介绍了基础数据加载与可视化方法。从本文开始,我们将深入实战,分两篇讲解如何通过 Python+geemap 实现多维地理数据可视化:

  • 上篇:3D地形渲染与单景影像植被指数计算;
  • 下篇:时序植被指数动态可视化与综合应用。

通过这两篇内容,你将掌握从静态地形分析到动态植被监测的完整流程,理解地理空间数据的多维特征。

一、3D地形可视化:探索青藏高原的地貌特征

SRTM(航天飞机雷达地形测绘任务) 数据是全球应用最广泛的数字高程模型之一,分辨率达30米。我们将用它实现青藏高原东北部的3D地形渲染,并计算坡度、坡向等地形因子。

python 复制代码
import geemap
import ee

# 初始化 GEE
try:
    ee.Initialize(project='ee-hllutlu2024')  # 替换为自己的GEE项目ID
except Exception:
    ee.Authenticate()
    ee.Initialize(project='ee-hllutlu2024')

# 创建 3D 地图(mode='3D')
Map = geemap.Map(center=[36.5, 100.5], zoom=8, mode='3D')

# 加载 SRTM DEM 数据
dem = ee.Image('USGS/SRTMGL1_003')

# 计算坡度与坡向
slope = ee.Terrain.slope(dem)
aspect = ee.Terrain.aspect(dem)

# 高程可视化参数
dem_params = {
    'min': 0,
    'max': 5000,
    'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']
}

# 添加图层
Map.addLayer(dem, dem_params, 'Elevation')
Map.addLayer(slope, {'min': 0, 'max': 60}, 'Slope')
Map.addLayer(aspect, {'min': 0, 'max': 360}, 'Aspect')

# 添加颜色条
Map.add_colorbar(dem_params, label='Elevation (m)', layer_name='Elevation')

Map.addLayerControl()
Map

代码逐段解释

1. 环境初始化
python 复制代码
import geemap
import ee

# 初始化 GEE
try:
    ee.Initialize(project='ee-hllutlu2024')  # 替换为自己的GEE项目ID
except Exception:
    ee.Authenticate()
    ee.Initialize(project='ee-hllutlu2024')
  • geemap 是连接Python与GEE的核心库,提供地图交互和数据处理功能;
  • ee.Initialize() 通过项目ID连接GEE服务器,try-except 确保首次使用时自动触发身份验证。
2. 创建3D地图对象
python 复制代码
Map = geemap.Map(center=[36.5, 100.5], zoom=8, mode='3D')
  • center=[36.5, 100.5]:地图中心点设为青藏高原东北部(北纬36.5°,东经100.5°);
  • mode='3D':开启三维模式,支持地形立体渲染和视角旋转(鼠标拖拽可旋转,滚轮可缩放)。
3. 加载与处理地形数据
python 复制代码
# 加载 SRTM DEM 数据
dem = ee.Image('USGS/SRTMGL1_003')

# 计算坡度与坡向
slope = ee.Terrain.slope(dem)
aspect = ee.Terrain.aspect(dem)
  • USGS/SRTMGL1_003 是GEE内置的SRTM数据,覆盖全球且免费可用;
  • ee.Terrain.slope(dem):计算坡度(地表倾斜角度,0-90°);
  • ee.Terrain.aspect(dem):计算坡向(地表朝向,0-360°,正北为0°)。
4. 可视化设置与图层添加
python 复制代码
# 高程可视化参数
dem_params = {
    'min': 0,
    'max': 5000,
    'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']
}

# 添加图层
Map.addLayer(dem, dem_params, 'Elevation')
Map.addLayer(slope, {'min': 0, 'max': 60}, 'Slope')
Map.addLayer(aspect, {'min': 0, 'max': 360}, 'Aspect')
  • dem_params 定义高程的颜色映射:绿色(低海拔)→浅绿→棕色→灰色→白色(高海拔,如雪山);
  • Map.addLayer() 依次添加高程、坡度、坡向图层,便于对比分析。
5. 添加辅助元素
python 复制代码
Map.add_colorbar(dem_params, label='Elevation (m)', layer_name='Elevation')
Map.addLayerControl()
Map
  • 颜色条帮助解读高程数值与颜色的对应关系;
  • 图层控制面板可自由切换显示/隐藏不同图层。

运行效果

三维地图中可直观看到青藏高原的山脉、河谷等地形特征,坡度图显示陡峭程度,坡向图反映山体朝向,适合地质、水文等领域的初步分析。


二、Landsat 8 NDVI计算:长江中游植被状况

NDVI(归一化植被指数) 是反映植被覆盖度的重要指标,通过 Landsat 8 的近红外和红光波段计算得出。我们以长江中游为例,提取2023年生长季的植被信息。

python 复制代码
import geemap
import ee

# 初始化
try:
    ee.Initialize(project='ee-hllutlu2024')
except Exception:
    ee.Authenticate()
    ee.Initialize(project='ee-hllutlu2024')

# 创建地图
Map = geemap.Map(center=[30, 110], zoom=6)

# 加载 Landsat 8 Collection 2 影像
image = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') \
    .filterDate('2023-05-01', '2023-10-01') \
    .filterBounds(ee.Geometry.Point(110, 30)) \
    .sort('CLOUD_COVER') \
    .first()

# 应用缩放因子(按USGS文档)
def apply_scale_factors(img):
    optical = img.select('SR_B.*').multiply(0.0000275).add(-0.2)
    thermal = img.select('ST_B.*').multiply(0.00341802).add(149.0)
    return img.addBands(optical, None, True).addBands(thermal, None, True)

image = apply_scale_factors(image)

# 计算NDVI
ndvi = image.normalizedDifference(['SR_B5', 'SR_B4']).rename('NDVI')

# 可视化参数
ndvi_params = {'min': -0.2, 'max': 0.8, 'palette': ['blue', 'white', 'green']}

# 添加图层
Map.addLayer(image, {'bands': ['SR_B4', 'SR_B3', 'SR_B2'], 'min': 0, 'max': 0.3}, 'Landsat 8 RGB')
Map.addLayer(ndvi, ndvi_params, 'NDVI')

Map.addLayerControl()
Map

代码逐段解释

1. 数据筛选:获取最优影像
python 复制代码
image = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') \
    .filterDate('2023-05-01', '2023-10-01') \
    .filterBounds(ee.Geometry.Point(110, 30)) \
    .sort('CLOUD_COVER') \
    .first()
  • LANDSAT/LC08/C02/T1_L2 是Landsat 8的Level 2级数据(已做大气校正,可直接用);
  • filterDate 限定2023年5-10月(长江流域植被生长季);
  • sort('CLOUD_COVER').first() 选取云量最少的影像,减少云层对植被观测的干扰。
2. 辐射定标:转换为物理值
python 复制代码
def apply_scale_factors(img):
    optical = img.select('SR_B.*').multiply(0.0000275).add(-0.2)
    thermal = img.select('ST_B.*').multiply(0.00341802).add(149.0)
    return img.addBands(optical, None, True).addBands(thermal, None, True)

image = apply_scale_factors(image)
  • Landsat原始数据是整数(DN值),需转换为实际物理量:
    • 光学波段(SR_B.*)→ 地表反射率(范围0-1);
    • 热红外波段(ST_B.*)→ 亮度温度(单位:开尔文);
  • 转换公式来自USGS官方文档,确保数据准确性。
3. NDVI计算:提取植被信息
python 复制代码
ndvi = image.normalizedDifference(['SR_B5', 'SR_B4']).rename('NDVI')
  • 公式:NDVI = (近红外 - 红光) / (近红外 + 红光)
  • SR_B5 是近红外波段(植被强反射),SR_B4 是红光波段(植被吸收多);
  • NDVI值范围为-1到1:正值越大,植被越茂密;负值可能是水体、建筑等。
4. 可视化对比
python 复制代码
# 真彩色影像(RGB)
Map.addLayer(image, {'bands': ['SR_B4', 'SR_B3', 'SR_B2'], 'min': 0, 'max': 0.3}, 'Landsat 8 RGB')
# NDVI指数
Map.addLayer(ndvi, ndvi_params, 'NDVI')
  • 真彩色影像用红(B4)、绿(B3)、蓝(B2)波段组合,接近人眼所见;(注意未去云)
  • NDVI用蓝(低植被/水体)→白(中等)→绿(高植被)渐变显示,直观区分植被覆盖差异。

运行效果

地图中可对比查看长江中游的真实地表与植被分布,绿色区域(如林地、农田)NDVI值高,蓝色区域(如河流、湖泊)NDVI值低。


小结

本篇我们通过两个案例展示了 Python+geemap 的核心能力:

  • 3D地形可视化:将平面高程数据转为立体地貌,辅助地形分析;
  • 单景影像NDVI计算:从多光谱数据中提取植被信息,评估地表覆盖。
相关推荐
2202_7567496919 分钟前
01 基于sklearn的机械学习-机械学习的分类、sklearn的安装、sklearn数据集及数据集的划分、特征工程(特征提取与无量纲化、特征降维)
人工智能·python·机器学习·分类·sklearn
鹿野素材屋41 分钟前
C#中对于List的多种排序方式
开发语言·c#
whxnchy1 小时前
C++刷题 - 7.27
开发语言·c++
王者鳜錸1 小时前
PYTHON从入门到实践-18Django从零开始构建Web应用
前端·python·sqlite
冗量1 小时前
PPT自动化 python-pptx - 8: 文本(text)
python·自动化·powerpoint
白日梦想家-K1 小时前
题单【模拟与高精度】
开发语言·c++·算法
超级晒盐人2 小时前
用落霞归雁的思维框架推导少林寺用什么数据库?
java·python·系统架构·学习方法·教育电商
鹦鹉0072 小时前
IO流中的字节流
java·开发语言·后端
重生之我是Java开发战士2 小时前
【C语言】内存函数与数据在内存中的存储
c语言·开发语言·算法
haaaaaaarry2 小时前
Element Plus常见基础组件(二)
开发语言·前端·javascript