百里屠苏top  

Overview 

This chapter should help users of Earth Engine to better understand raster data by
applying visualization algorithms such as hillshading, hill shadows, and custom
colormaps. We will also learn how image collection datasets can be explored by
animating them as well as by annotating with text labels, using, e.g., attributes of
images or values queried from images.

主要内容:

  • 理解为什么感知上一致的颜色映射更好地呈现数据,并有效地使用它们进行栅格可视化;
  • 在重新映射值之前和之后使用图像调色板;
  • 在可视化图像或特征时添加文本注释;
  • 以多种方式动画图像集合(动画gif,导出视频剪辑,带有UI控件的交互式动画);
  • 添加山丘阴影和阴影来帮助可视化栅格数据集。

Section 1:

1、调色板 Palettes

有多种类型的颜色映射,每一种用于不同的目的。其中包括:

1)连续的:这些可能是最常用的颜色映射,对于序数、间隔和比率数据非常有用。也称为线性色图。

 2)发散的:这种类型的颜色图用于可视化具有正负值和具有意义的零的数据。

 3)循环的:有些变量是周期性的,在一段时间后恢复到相同的值。例如,季节、角度和时间通常表示为圆形变量。

4)语义的:有些颜色映射不映射到任意颜色,而是选择提供意义的颜色。我们把这些称为语义色图。

 

2、颜色图的流行来源

2.1 海洋专用cmocean颜色

2.2 colorcet颜色包

2.3 cpt-city

2.4 colorbrewer 

 2.5 Crameri 

 3、示例

 

// 调取 ERA5 数据. 
var era5 = ee.ImageCollection('ECMWF/ERA5_LAND/MONTHLY'); 
// 定义调色板. 
var palettes = require('users/gena/packages:palettes'); 
// 选择温度波段. 
era5 = era5.select('temperature_2m');

// 选择调色板.
var balancePalette = palettes.cmocean.Balance[7];
var threeColorPalette = ['blue', 'white', 'red'];


// 在右边的Inspector 窗口显示调色盘.
palettes.showPalette('temperature anomaly', balancePalette);
palettes.showPalette('temperature anomaly', threeColorPalette);


// 帅选获取两个时段的温度均值.
var era5_1980 = era5.filterDate('1981-01-01', '1991-01-01').mean();
var era5_2010 = era5.filterDate('2011-01-01', '2020-01-01').mean();


// 计算温度变化.
var era5_diff = era5_2010.subtract(era5_1980);


// Show it on the map.
Map.addLayer(era5_diff, {
    palette: threeColorPalette,
    min: -2,
    max: 2
}, 'Blue White Red palette');


Map.addLayer(era5_diff, {
    palette: balancePalette,
    min: -2,
    max: 2
}, 'Balance palette');

 

 

 

 4、第二个例子

 可视化南极冰川。南极冬天几个月是处于黑暗状态,所以用可见光影像无法看到流入海洋的冰。因此,我们使用雷达影像。

使用哨兵1的数据。

// An image of the Thwaites glacier. 
var imageId = 'COPERNICUS/S1_GRD/S1B_EW_GRDM_1SSH_20211216T041925_20211216T042029_030045_03965B_AF0A'; 
print("imageId", imageId);
// Look it up and select the HH band. 
var img = ee.Image(imageId).select('HH'); 
print("img", img);

// Use the palette library. 
var palettes = require('users/gena/packages:palettes'); 
// Access the ice palette. 
var icePalette = palettes.cmocean.Ice[7]; 

// Show it in the console. 
palettes.showPalette('Ice', icePalette); 
// Use  it to visualize the radar data. 
Map.addLayer(img, { 
    palette: icePalette, 
    min: -15, 
    max: 1 
}, 'Sentinel-1 radar'); 

// Zoom to the grounding line of the Thwaites Glacier. 
Map.centerObject(ee.Geometry.Point([-105.45882094907664, -74.90419580705336 ]), 8); 

 

 

 

 

Section 2:重新映射和调色板

1、分类后的栅格数据

美国地质调查局国家土地覆盖数据库(NLCD)--The USGS National Land Cover Database (NLCD)

// Advanced remapping using NLCD. 
// Import NLCD. 
var nlcd = ee.ImageCollection('USGS/NLCD_RELEASES/2016_REL'); 
// Use Filter to select the 2016 dataset. 
var nlcd2016 = nlcd.filter(ee.Filter.eq('system:index', '2016')) .first(); 
// Select the land cover band. 
var landcover = nlcd2016.select('landcover'); 
// Map the NLCD land cover. 
Map.addLayer(landcover, null, 'NLCD Landcover'); 

 

把三个城镇图层都显示为深红色('ab0000')

 

//把三个城镇图层都显示为深红色('ab0000'// Now suppose we want to change the color palette. 
var newPalette = ['466b9f', 'd1def8', 'dec5c5', 
    'ab0000', 'ab0000', 'ab0000', 
    'b3ac9f', '68ab5f', '1c5f2c', 
    'b5c58f', 'af963c', 'ccb879', 
    'dfdfc2', 'd1d182', 'a3cc51', 
    '82ba9e', 'dcd939', 'ab6c28', 
    'b8d9eb', '6c9fb8' 
]; 

// Try mapping with the new color palette. 
Map.addLayer(landcover, { 
    palette: newPalette 
}, 'NLCD New Palette'); 

结果:

 !!!发现结果不是我们想要的。这是因为the numeric codes for the different classes are not sequential. 

为了解决这个问题,我们将为类值创建一个新的索引,以便它们是连续的。

原来的索引:                                                            新的索引:

                   

 

// Extract the class values and save them as a list. 
var values = ee.List(landcover.get('landcover_class_values')); 
// Print the class values to console. 
print('raw class values', values); 
// Determine the maximum index value 
var maxIndex = values.size().subtract(1); 
// Create a new index for the remap 
var indexes = ee.List.sequence(0, maxIndex); 
// Print the updated class values to console. 
print('updated class values', indexes); 
// Remap NLCD and display it in the map. 
var colorized = landcover.remap(values, indexes) 
    .visualize({ 
        min: 0, 
        max: maxIndex, 
        palette: newPalette 
    }); 
Map.addLayer(colorized, {}, 'NLCD Remapped Colors'); 

结果:

 

 

Section 3:Annotations  注释

  • 注释是在地图上可视化数据的一种方式,可以提供关于栅格值或与上下文相关的任何其他数据的附加信息。
  • 在这种情况下,这些附加信息通常显示为几何图形、文本标签、图表或其他可视元素。
  • GEE中的一些注释可以通过使用API的ui部分来添加,从而在地图的顶部添加图形用户界面元素,如标签或图表。
  • 将注释作为图像的一部分呈现通常是有用的,例如通过可视化各种图像属性或突出显示特定区域。

在许多情况下,这些注释可以与在Earth Engine之外生成的输出图像混合,例如,通过使用Python库对导出的图像进行后期处理,或者通过使用GIS应用程序(如QGIS或ArcGIS)进行注释。然而,注释对于在代码编辑器中直接突出显示和/或标记特定区域也非常有用。Earth Engine提供了一个足够丰富的API,可以将矢量特征和几何图形转换为可以作为注释的光栅图像。我们建议查看Earth Engine文档中的ee.FeatureCollection.style函数,了解如何渲染几何图形。

对于文本注释,我们将使用一个外部包“users/gena/packages:text”,它提供了一种使用Earth Engine光栅API直接将字符串渲染为光栅图像的方法。解释这个包的实现超出了当前教程的范围,但是在内部,这个包使用了位图字体,这些字体作为栅格资产被摄取到地球引擎中,并用于将提供的字符串的每个字符转换为图像符号,然后将其转换为所需的坐标。

文本包的API包括以下强制和可选参数:

为了演示如何使用这个API,让我们呈现一个简单的“Hello World!”使用默认文本参数放置在地图中心的文本字符串。它的代码是:\

 

// Include the text package. 
var text = require('users/gena/packages:text'); 

// Configure map (change center and map type). 
Map.setCenter(0, 0, 10); 
Map.setOptions('HYBRID'); 

// Draw text string and add to map. 
var pt = Map.getCenter(); 
var scale = Map.getScale(); 
var image = text.draw('Hello World!', pt, scale); 
Map.addLayer(image); 

var image = text.draw('Hello World!', pt, scale, { 
    fontSize: 32, 
    fontType: 'Consolas', 
    textColor: 'black', 
    outlineColor: 'white', 
    outlineWidth: 1, 
    outlineOpacity: 0.8 
}); 
// Add the text image to the map. 
Map.addLayer(image); 

 

3.1 示例:  用文本标签注释云量。

var text = require('users/gena/packages:text'); 

var geometry = ee.Geometry.Polygon( 
    [ 
        [ 
            [-109.248, 43.3913], 
            [-109.248, 33.2689], 
            [-86.5283, 33.2689], 
            [-86.5283, 43.3913] 
        ] 
    ], null, false); 
    
Map.centerObject(geometry, 6); 

function annotate(image) { 
    // Annotates an image by adding outline border and cloudiness 
    // Cloudiness is shown as a text string rendered at the image center. 
    // Add an edge around the image. 
    var edge = ee.FeatureCollection([image]) 
        .style({ 
            color: 'cccc00cc', 
            fillColor: '00000000' 
        }); 
        
    // Draw cloudiness as text. 
    var props = { 
        textColor: '0000aa', 
        outlineColor: 'ffffff', 
        outlineWidth: 2, 
        outlineOpacity: 0.6, 
        fontSize: 24, 
        fontType: 'Consolas' 
    };
    
    var center = image.geometry().centroid(1); 
    var str = ee.Number(image.get('CLOUD_COVER')).format('%.2f'); 
    var scale = Map.getScale(); 
        var textCloudiness = text.draw(str, center, scale, props);
        // Shift left 25 pixels.
        textCloudiness = textCloudiness .translate(-scale * 25, 0, 'meters', 'EPSG:3857'); 
        
    // Merge results. 
    return ee.ImageCollection([edge, textCloudiness]).mosaic(); 
} 


// Select images. 
var images = ee.ImageCollection('LANDSAT/LC08/C02/T1_RT_TOA') 
    .select([5, 4, 2]) 
    .filterBounds(geometry) 
    .filterDate('2018-01-01', '2018-01-7'); 
    
// dim background. 
Map.addLayer(ee.Image(1), { 
    palette: ['black'] 
}, 'black', true, 0.5); 


// Show images. 
Map.addLayer(images, { 
    min: 0.05, 
    max: 1, 
    gamma: 1.4 
}, 'images'); 


// Show annotations. 
var labels = images.map(annotate); 
var labelsLayer = ui.Map.Layer(labels, {}, 'annotations'); 
Map.layers().add(labelsLayer);

 

// re-render (rescale) annotations when map zoom changes. 
Map.onChangeZoom(function(zoom) { 
    labelsLayer.setEeObject(images.map(annotate)); 
});

 

 

 

Section 4:Animations   动画

  • 将光栅图像可视化为动画是一种有用的技术,可以探索时间相关数据集的变化,而且还可以呈现简短的动画,以传达改变各种参数如何影响最终图像,例如,改变光谱指数的阈值导致不同的二值图或矢量特征的几何形状变化。
  • 动画在探索卫星图像时非常有用,因为它们允许观众快速理解地球表面或大气特性变化的动态。动画还可以帮助决定下一步应该采取什么步骤,设计一个强大的算法,从卫星图像时间序列中提取有用的信息。Earth Engine提供了两种标准的方式来生成动画:作为gif动画,以及作为VI视频剪辑。动画也可以从从地球引擎导出的一系列图像中渲染,使用许多工具,如ffmpeg或moviepy。然而,在许多情况下,有一种方法来快速探索图像集合作为动画,而不需要额外的步骤是有用的。
  • 三种方式:
    • 生成GIF动画
    • 将视频导出为一个VI文件到Google Drive
    • 动画图像收集交互使用UI控件和地图层。

 

示例1:GIF动画

 

// Include packages. 
var palettes = require('users/gena/packages:palettes'); 
var text = require('users/gena/packages:text'); 

var point = /* color: #98ff00 */ ee.Geometry.Point([-
    106.15944300895228, -74.58262940096245 
]); 

var rect = /* color: #d63000 */ 
    ee.Geometry.Polygon( 
        [ 
            [ 
                [-106.19789515738981, -74.56509549360152], 
                [-106.19789515738981, -74.78071448733921], 
                [-104.98115931754606, -74.78071448733921], 
                [-104.98115931754606, -74.56509549360152] 
            ] 
        ], null, false); 
        
// Lookup the ice palette. 
var palette = palettes.cmocean.Ice[7]; 

// Show it in the console. 
palettes.showPalette('Ice', palette); 

// Center map on geometry. 
Map.centerObject(point, 9); 

// Select S1 images for the Thwaites glacier. 
var images = ee.ImageCollection('COPERNICUS/S1_GRD') 
    .filterBounds(rect) 
    .filterDate('2021-01-01', '2021-03-01') 
    .select('HH') 
// Make sure we include only images which fully contain the region geometry. 
    .filter(ee.Filter.isContained({ 
        leftValue: rect, 
    rightField: '.geo' 
    })) 
    .sort('system:time_start'); 
    
// Print number of images. 
print(images.size());

//=====================================================================================
// Render images. 
var vis = { 
    palette: palette, 
    min: -15, 
    max: 1 
}; 

var scale = Map.getScale(); 

var textProperties = { 
    outlineColor: '000000', 
    outlineWidth: 3, 
    outlineOpacity: 0.6 
};

var imagesRgb = images.map(function(i) { 
// Use the date as the label. 
    var label = i.date().format('YYYY-MM-dd'); 
    var labelImage = text.draw(label, point, scale, textProperties); 
    return i.visualize(vis) 
        .blend(labelImage) // Blend label image on top. 
        .set({ 
            label: label 
        }); // Keep the text property. 
}); 

Map.addLayer(imagesRgb.first()); 
Map.addLayer(rect, {color:'blue'}, 'rect', 1, 0.5); 

//=====================================================================================
//Animation 1: Animated GIF with ui.Thumbnail 
//=====================================================================================

// Define GIF visualization parameters. 
var gifParams = { 
    region: rect, 
    dimensions: 600, 
    crs: 'EPSG:3857', 
    framesPerSecond: 10 
}; 

// Print the GIF URL to the console. 
print(imagesRgb.getVideoThumbURL(gifParams)); 

// Render the GIF animation in the console. 
print(ui.Thumbnail(imagesRgb, gifParams));

 

示例2:

//=====================================================================================
//Animation 2: Exporting an Animation with Export.video.toDrive 
//=====================================================================================

Export.video.toDrive({ 
    collection: imagesRgb, 
    description: 'ice-animation', 
    fileNamePrefix: 'ice-animation', 
    framesPerSecond: 10, 
    dimensions: 600, 
    region: rect, 
    crs: 'EPSG:3857' 
});

示例3:

//=====================================================================================
//Animation 3: The Custom Animation Package 
//=====================================================================================
// include the animation package 
var animation = require('users/gena/packages:animation'); 
// show animation controls 
animation.animate(imagesRgb, { 
    label: 'label', 
    maxFrames: 50 
}); 

 

实例:以landsat数据为例,查看某个区域的变化,以GIF显示

Section 5:地形可视化

var dem = ee.Image('AHN/AHN2_05M_RUW'); 
// Change map style to HYBRID and center map on the Netherlands 
Map.setOptions('HYBRID'); 
Map.setCenter(4.4082, 52.1775, 18); 

// Visualize DEM using black-white color palette 
var palette = ['black', 'white']; 
var demRGB = dem.visualize({ 
    min: -5, 
    max: 5, 
    palette: palette 
}); 
Map.addLayer(demRGB, {},'DEM'); 


var utils = require('users/gena/packages:utils'); 
var weight = 0.4; // Weight of Hillshade vs RGB (0 - flat, 1 -hillshaded). 
var exaggeration = 5; // Vertical exaggeration. 
var azimuth = 315; // Sun azimuth. 
var zenith = 20; // Sun elevation. 
var brightness = -0.05; // 0 - default. 
var contrast = 0.05; // 0 - default. 
var saturation = 0.8; // 1 - default. 
var castShadows = false; 

var rgb = utils.hillshadeRGB( 
    demRGB, dem, weight, exaggeration, azimuth, zenith, 
    contrast, brightness, saturation, castShadows); 
Map.addLayer(rgb, {}, 'DEM (no shadows)'); 


var castShadows = true; 
var rgb = utils.hillshadeRGB( 
    demRGB, dem, weight, exaggeration, azimuth, zenith, 
    contrast, brightness, saturation, castShadows); 
Map.addLayer(rgb, {}, 'DEM (with shadows)'); 

var palettes = require('users/gena/packages:palettes'); 
var palette = palettes.crameri.oleron[50]; 
var demRGB = dem.visualize({ 
    min: -5, 
    max: 5, 
    palette: palette 
}); 

var castShadows = true; 

var rgb = utils.hillshadeRGB( 
    demRGB, dem, weight, exaggeration, azimuth, zenith, 
    contrast, brightness, saturation, castShadows); 
Map.addLayer(rgb, {}, 'DEM colormap'); 

结果:

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2024-05-30 17:51  百里屠苏top  阅读(7)  评论(0编辑  收藏  举报