GEE绘制DEM全解析
关于
昨天阅读了一篇质量很高的python绘制地形图博客。有感而发,我便想到了GEE(Google earth engine)数据源众多、计算速度快、计算算子多的特点,使用GEE应该不会逊色于python。
制作流程
使用GEE绘制DEM一共有3步,其中最重要的是调色板的使用。
(1)DEM数据源
GEE的DEM数据众多,读者可以根据自己的需要选择合适的数据源。研究区范围大,可以选择分辨率较低的数据,如果研究区域较小,则尽量使用高分辨率DEM。
在GEE中的每一种数据源,都有详细的介绍与代码引用示例,比如荷兰的0.5m分辨率的DEM:
这里考虑到试验区是我老家四川省,这里使用覆盖全球的30m分辨率NASA DEM。
// 引入数据源 研究区选择我的老家四川省
var dataset = ee.Image('NASA/NASADEM_HGT/001');
var elevation = dataset.select('elevation').clip(ROI);
// 设置可视化参数
var elevationVis = {
min: 0,
max: 8000,
};
//可视化
Map.addLayer(elevation, elevationVis, 'Elevation');
Map.centerObject(ROI, 7);
(2)颜色配色表
待数据加载完成之后,数据的颜色不好看,这个时候就需要调色板。有几种办法,一种是在GEE中手动调整DEM显示:
还有一个就是可以参考别人的已经设置好的调色板,直接调用,这里我推荐一个GitHub仓库 ee-palettes(https://github.com/gee-community/ee-palettes):
该仓库汇集了近两百种配色方案,在GEE中直接调用即可:
调用这个仓库,只需要引入函数库,然后new一个调色板,并将该配色方案填入地图加载函数中,注意设置最大值与最小值。然后对照着颜色表逐个尝试,找到最适合自己的颜色方案。
//调用仓库已经配置好的调色板
var palettes = require('users/gena/packages:palettes');
var palette_bamako = palettes.crameri.bamako[10,25,50];
Map.addLayer(elevation, {min:0, max:8000, palette: palette_bamako}, 'crameri.bamako');
var palette_rainbow = palettes.kovesi.rainbow_bgyr_35_85_c72[7];
Map.addLayer(elevation, {min:0, max:8000, palette: palette_rainbow}, 'palette_rainbow');
var palette_misc = palettes.misc.jet[7];
Map.addLayer(elevation, {min:0, max:8000, palette: palette_misc}, 'palette_misc');
var palette_diverging = palettes.kovesi.diverging_linear_bjy_30_90_c45[7];
Map.addLayer(elevation, {min:0, max:8000, palette: palette_diverging}, 'palette_diverging');
在配色过程中,也可以注意调色板的最大值与最小值对于DEM显示的影响。四川省的最高海拔为7556米,最低海拔为188米。但是这并不代表我们的配色值域应该遵从最大最小值,因为在配色中如果像素值大于max值,则颜色为最右端,值会自动调整的,如果我们能找到最佳的值域范围,则内部的像素点因为高度差异引起的对比更明显,换句话说,使用大部分值域范围的显示效果更佳。
根据四川省的DEM值分布直方图,我做了以下几个对比:
//值域范围对比
//0-8000m
var palette_rainbow1 = palettes.kovesi.rainbow_bgyr_35_85_c72[7];
Map.addLayer(elevation, {min:0, max:8000, palette: palette_rainbow1}, 'palette_rainbow1');
//最大值与最小值
var palette_rainbow2 = palettes.kovesi.rainbow_bgyr_35_85_c72[7];
Map.addLayer(elevation, {min:188, max:7556, palette: palette_rainbow2}, 'palette_rainbow2');
//直方图的横轴最大值与最小值
var palette_rainbow3 = palettes.kovesi.rainbow_bgyr_35_85_c72[7];
Map.addLayer(elevation, {min:451, max:4525, palette: palette_rainbow3}, 'palette_rainbow3');
//直方图的横轴最小值与6000
var palette_rainbow4 = palettes.kovesi.rainbow_bgyr_35_85_c72[7];
Map.addLayer(elevation, {min:451, max:6000, palette: palette_rainbow4}, 'palette_rainbow4');
如何选取合适调色板的值域范围,也是优雅绘制DEM的重要因素。
(3)山体阴影;
选取了较好的DEM数据源、调色板、值域范围后,我们可以加入山体阴影来增强DEM的显示效果。函数 ee.Terrain.hillshade(input,azimuth, elevation)是生成山体阴影的算子,input为DEM,azimuth是方位角,elevation是高度角。
方向角指的是太阳的角度方向,是以北为基准方向在 0 到 360 度范围内按顺时针进行测量的,90º 的方位角为东。高度指的是照明源高出地平线的角度或坡度。高度的单位为度,范围为 0(位于地平线上)到 90(位于头上)之间。需要注意hillshade的值域为0-255.
//山体阴影
var palette_hillshade = palettes.crameri.bamako[10,25,50];
var exaggeration = 20;
var hillshade = ee.Terrain.hillshade(elevation.multiply(exaggeration),270,45);
Map.addLayer(hillshade, {min: 0, max: 255, palette: palette_hillshade}, 'palette_hillshade');
方位角
影响山体阴影显示效果的有方位角:
//不同的方位角
var palette_hillshade = palettes.crameri.bamako[10,25,50];
var exaggeration = 20;
var hillshade_45 = ee.Terrain.hillshade(elevation.multiply(exaggeration),45,15);
Map.addLayer(hillshade_45, {min: 0, max: 255, palette: palette_hillshade}, 'palette_hillshade_45');
var hillshade_135 = ee.Terrain.hillshade(elevation.multiply(exaggeration),135,15);
Map.addLayer(hillshade_135, {min: 0, max: 255, palette: palette_hillshade}, 'palette_hillshade_135');
var hillshade_225 = ee.Terrain.hillshade(elevation.multiply(exaggeration),225,15);
Map.addLayer(hillshade_225, {min: 0, max: 255, palette: palette_hillshade}, 'palette_hillshade_225');
var hillshade_315 = ee.Terrain.hillshade(elevation.multiply(exaggeration),315,15);
Map.addLayer(hillshade_315, {min: 0, max: 255, palette: palette_hillshade}, 'palette_hillshade_315');
GEE的默认方向角为270º ,作者可以根据自身需求选择合适的方位角。
高度角
不同的高度角也会影响山体阴影的显示效果:
//不同的高度角
var palette_hillshade = palettes.crameri.bamako[10,25,50];
var exaggeration = 20;
var hillshade_15 = ee.Terrain.hillshade(elevation.multiply(exaggeration),270,15);
Map.addLayer(hillshade_15, {min: 0, max: 255, palette: palette_hillshade}, 'palette_hillshade_15');
var hillshade_30 = ee.Terrain.hillshade(elevation.multiply(exaggeration),270,30);
Map.addLayer(hillshade_30, {min: 0, max: 255, palette: palette_hillshade}, 'palette_hillshade_30');
var hillshade_45 = ee.Terrain.hillshade(elevation.multiply(exaggeration),270,45);
Map.addLayer(hillshade_45, {min: 0, max: 255, palette: palette_hillshade}, 'palette_hillshade_45');
var hillshade_60 = ee.Terrain.hillshade(elevation.multiply(exaggeration),270,60);
Map.addLayer(hillshade_60, {min: 0, max: 255, palette: palette_hillshade}, 'palette_hillshade_60');
var hillshade_75 = ee.Terrain.hillshade(elevation.multiply(exaggeration),270,75);
Map.addLayer(hillshade_75, {min: 0, max: 255, palette: palette_hillshade}, 'palette_hillshade_75');
var hillshade_90 = ee.Terrain.hillshade(elevation.multiply(exaggeration),270,90);
Map.addLayer(hillshade_90, {min: 0, max: 255, palette: palette_hillshade}, 'palette_hillshade_90');
一般来说,高度角越小,山体阴影效果越强,高度角在gee中默认是45°。
代码链接
https://code.earthengine.google.com/2e947952a68cb01eb63a247ec4424936
写在最后
总结以下,要优雅地使用GEE绘制DEM:
首先得选好数据源,小研究区选择分辨率高的DEM,大研究区可以选择低分辨率DEM;
其次是选好调色板,这里推荐使用第三方库ee-palettes,然后就是注意调色板的最值范围;
其次是制作山体阴影,注意选择合适的太阳高度角与方位角。
该文只是提供一个制作思路,由于作者的审美水平有限,读者不必完全按照我的配色方案来制作地形图,怎么好看怎么来。
参考
Clarmy吱声.如何用Python绘制炫酷的立体地形图