EZ | Image Visualization | GEE - 08

Image\ Visualization


图像可视化

前面的文档中已经介绍了如何使用map.addLayer()函数对image做可视化,如果你不加任何参数使用这一函数,默认地,GEE会按照红-绿-蓝的次序依次加入。默认的归一值基于数据终端波段信息实现,例如,floats被限制在[0,1]的范围内,16-bit的数据则可以投射到可能值的全域,但是,这样的默认值可能不是特别合适。为了实现最好的可视化效果,你可以使用我们给这个函数所提供的一些参数,特别地,这些参数可以列在这里:

Visualization Parameters for Map.addLayer()
Parameter Description Type
bands 三个波段的列表,映射在RGB上 列表
min 最低值 数值或是数值列表
max 最大值 数值或是数值列表
gain 每个像素值的权重 数值或是数值列表
bias 每个DN上添加的值 数值或是数值列表
gamma 伽玛校正因子 数值或是数值列表
palette CSS风格的字符串的列表* 十六进制字符串列表
opacity 图层的不透明度** 数值
format jpg或是png 字符串

\tag{*单波段image独有}

RGB\ Composites


RGB拼合

下面展示了把Landsat-8卫星图像当作伪色图像显示的参数详细信息:

var image = ee.Image('LANDSAT/LC08/C01/T1_TOA/LC08_044034_20140318');

// Define the visualization parameters.
var vizParams = {
  bands: ['B5', 'B4', 'B3'],
  min: 0,
  max: 0.5,
  gamma: [0.95, 1.1, 1]
};

// Center the map and display the image.
Map.setCenter(-122.1899, 37.5010, 10); // San Francisco Bay
Map.addLayer(image, vizParams, 'false color composite');

在这个例子中,B5波段被指定为红色,B4波段被指定为绿色,B3波段则为蓝色,结果如下:


Fig.1 三藩市Landsat-8伪色图像

Color\ Palettes


palettes参数

想要展示一个image其中包含的一个波段,可以把palette参数用CSS风格的颜色字符串列表进行设置,下面就是用cyan和blue渲染图像的实例代码:

// Load an image.
var image = ee.Image('LANDSAT/LC08/C01/T1_TOA/LC08_044034_20140318');

// Create an NDWI image, define visualization parameters and display.
var ndwi = image.normalizedDifference(['B3', 'B5']);
var ndwiViz = {min: 0.5, max: 1, palette: ['00FFFF', '0000FF']};
Map.addLayer(ndwi, ndwiViz, 'NDWI', false);

在此例中,注意minmax两个参数,二者被指示到像素值范围内,这也正是palettes参数应该设置的范围,代码中对中值进行线性拉伸,同时应该注意到opt_show参数被设置为false,结果就是图层被添加到地图上时实际上不可见。参数可以在图层管理器中进行调整。该代码显示结果如下:

Fig.2 Landsat-8 NDWI 三藩市

Masking


蒙版

可以使用image.updateMask()函数设置每个像素的透明度。每一个蒙版等于0的像素都不被计算,完全透明。下面的例子更新了NDWI图层的蒙版:

// Mask the non-watery parts of the image, where NDWI < 0.4.
var ndwiMasked = ndwi.updateMask(ndwi.gte(0.4));
Map.addLayer(ndwiMasked, ndwiViz, 'NDWI masked');

Visualization\ Images


image可视化

使用image.visualize()方法来吧image转化成一个8位的RGB图像,用来显示或导出。例子如下:

// Create visualization layers.
var imageRGB = image.visualize({bands: ['B5', 'B4', 'B3'], max: 0.5});
var ndwiRGB = ndwiMasked.visualize({
  min: 0.5,
  max: 1,
  palette: ['00FFFF', '0000FF']
});

Mosaicking


马赛克

可以使用imageCollection.mosaic()函数对图像做马赛克操作,这一方法根据输入集合中的顺序呈现输出图像中的图层。下面的例子使用mosaic()函数组合蒙版的NDWI和伪彩色图进行合成并获得新的可视化效果:

// Mosaic the visualization layers and display (or export).
var mosaic = ee.ImageCollection([imageRGB, ndwiRGB]).mosaic();
Map.addLayer(mosaic, {}, 'mosaic');

在这个例子中,观察两个可视化图像的List被送入了ImageCollection的构造函数。,列表中的顺序就决定了图层显示的顺序,显示结果如下:

Fig.3 三藩市的Landsat-8伪彩色图像和NDWI的马赛克可视化

Clipping


裁剪

image.clip()参数被用来做裁剪,瞎main的例子对Fig.3中的图像做了裁剪:

// Create a circle by drawing a 20000 meter buffer around a point.
var roi = ee.Geometry.Point([-122.4481, 37.7599]).buffer(20000);

// Display a clipped version of the mosaic.
Map.addLayer(mosaic.clip(roi));

显示结果如下:


Fig.4 裁剪方式

Rendering\ Categorical\ Maps


渲染特定地图

palettes对于渲染离散值地图非常重要,在有多个类的时候,就要使用这个palettes对每个类提供不同的颜色。image.remap()函数在这里可能派得上用场,它可以将标签转化为连续整数。下面使用了palettes对土地覆盖情况做了渲染:

// Load 2012 MODIS land cover and select the IGBP classification.
var cover = ee.Image('MODIS/051/MCD12Q1/2012_01_01')
  .select('Land_Cover_Type_1');

// Define a palette for the 18 distinct land cover classes.
var igbpPalette = [
  'aec3d4', // water
  '152106', '225129', '369b47', '30eb5b', '387242', // forest
  '6a2325', 'c3aa69', 'b76031', 'd9903d', '91af40',  // shrub, grass
  '111149', // wetlands
  'cdb33b', // croplands
  'cc0013', // urban
  '33280d', // crop mosaic
  'd7cdcc', // snow and ice
  'f7e084', // barren
  '6f6f6f'  // tundra
];

// Specify the min and max labels and the color palette matching the labels.
Map.setCenter(-99.229, 40.413, 5);
Map.addLayer(cover,
             {min: 0, max: 17, palette: igbpPalette},
             'IGBP classification');

执行结果如下:

IGBP渲染的MODIS2012

Staled\ Layer\ Descriptors


样式化图层描述符(SLD)

可以使用SLD对于显示的图像进行渲染,我们提供了image.sldStyle()函数,还有一个对于特征和着色信息的XML文件,尤其是RasterSymbolizer这一项。实例代码如下:

var cover = ee.Image('MODIS/051/MCD12Q1/2012_01_01').select('Land_Cover_Type_1');

// Define an SLD style of discrete intervals to apply to the image.
var sld_intervals =
'<RasterSymbolizer>' +
 ' <ColorMap  type="intervals" extended="false" >' +
    '<ColorMapEntry color="#aec3d4" quantity="0" label="Water"/>' +
    '<ColorMapEntry color="#152106" quantity="1" label="Evergreen Needleleaf Forest"/>' +
    '<ColorMapEntry color="#225129" quantity="2" label="Evergreen Broadleaf Forest"/>' +
    '<ColorMapEntry color="#369b47" quantity="3" label="Deciduous Needleleaf Forest"/>' +
    '<ColorMapEntry color="#30eb5b" quantity="4" label="Deciduous Broadleaf Forest"/>' +
    '<ColorMapEntry color="#387242" quantity="5" label="Mixed Deciduous Forest"/>' +
    '<ColorMapEntry color="#6a2325" quantity="6" label="Closed Shrubland"/>' +
    '<ColorMapEntry color="#c3aa69" quantity="7" label="Open Shrubland"/>' +
    '<ColorMapEntry color="#b76031" quantity="8" label="Woody Savanna"/>' +
    '<ColorMapEntry color="#d9903d" quantity="9" label="Savanna"/>' +
    '<ColorMapEntry color="#91af40" quantity="10" label="Grassland"/>' +
    '<ColorMapEntry color="#111149" quantity="11" label="Permanent Wetland"/>' +
    '<ColorMapEntry color="#cdb33b" quantity="12" label="Cropland"/>' +
    '<ColorMapEntry color="#cc0013" quantity="13" label="Urban"/>' +
    '<ColorMapEntry color="#33280d" quantity="14" label="Crop, Natural Veg. Mosaic"/>' +
    '<ColorMapEntry color="#d7cdcc" quantity="15" label="Permanent Snow, Ice"/>' +
    '<ColorMapEntry color="#f7e084" quantity="16" label="Barren, Desert"/>' +
    '<ColorMapEntry color="#6f6f6f" quantity="17" label="Tundra"/>' +
  '</ColorMap>' +
'</RasterSymbolizer>';
Map.addLayer(cover.sldStyle(sld_intervals), {}, 'IGBP classification styled');

想用渐变色渲染图像,就把ColorMap参数设置为'ramp',下面的例子比较了'interval'和'ramp'的区别:

// Load SRTM Digital Elevation Model data.
var image = ee.Image('CGIAR/SRTM90_V4');

// Define an SLD style of discrete intervals to apply to the image.
var sld_intervals =
  '<RasterSymbolizer>' +
    '<ColorMap  type="intervals" extended="false" >' +
      '<ColorMapEntry color="#0000ff" quantity="0" label="0"/>' +
      '<ColorMapEntry color="#00ff00" quantity="100" label="1-100" />' +
      '<ColorMapEntry color="#007f30" quantity="200" label="110-200" />' +
      '<ColorMapEntry color="#30b855" quantity="300" label="210-300" />' +
      '<ColorMapEntry color="#ff0000" quantity="400" label="310-400" />' +
      '<ColorMapEntry color="#ffff00" quantity="1000" label="410-1000" />' +
    '</ColorMap>' +
  '</RasterSymbolizer>';

// Define an sld style color ramp to apply to the image.
var sld_ramp =
  '<RasterSymbolizer>' +
    '<ColorMap type="ramp" extended="false" >' +
      '<ColorMapEntry color="#0000ff" quantity="0" label="0"/>' +
      '<ColorMapEntry color="#00ff00" quantity="100" label="100" />' +
      '<ColorMapEntry color="#007f30" quantity="200" label="200" />' +
      '<ColorMapEntry color="#30b855" quantity="300" label="300" />' +
      '<ColorMapEntry color="#ff0000" quantity="400" label="400" />' +
      '<ColorMapEntry color="#ffff00" quantity="500" label="500" />' +
    '</ColorMap>' +
  '</RasterSymbolizer>';

// Add the image to the map using both the color ramp and interval schemes.
Map.setCenter(-76.8054, 42.0289, 8);
Map.addLayer(image.sldStyle(sld_intervals), {}, 'SLD intervals');
Map.addLayer(image.sldStyle(sld_ramp), {}, 'SLD ramp');

SLD也被用来拉伸像素取值以便提高连续数据的显示效果,下面的代码展示了线性拉伸与min-max Normalization以及Histogram进行比较的结果:

// Load a Landsat 8 raw image.
var image = ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318');

// Define a RasterSymbolizer element with '_enhance_' for a placeholder.
var template_sld =
  '<RasterSymbolizer>' +
    '<ContrastEnhancement><_enhance_/></ContrastEnhancement>' +
    '<ChannelSelection>' +
      '<RedChannel>' +
        '<SourceChannelName>B5</SourceChannelName>' +
      '</RedChannel>' +
      '<GreenChannel>' +
        '<SourceChannelName>B4</SourceChannelName>' +
      '</GreenChannel>' +
      '<BlueChannel>' +
        '<SourceChannelName>B3</SourceChannelName>' +
      '</BlueChannel>' +
    '</ChannelSelection>' +
  '</RasterSymbolizer>';

// Get SLDs with different enhancements.
var equalize_sld = template_sld.replace('_enhance_', 'Histogram');
var normalize_sld = template_sld.replace('_enhance_', 'Normalize');

// Display the results.
Map.centerObject(image, 10);
Map.addLayer(image, {bands: ['B5', 'B4', 'B3'], min: 0, max: 15000}, 'Linear');
Map.addLayer(image.sldStyle(equalize_sld), {}, 'Equalized');
Map.addLayer(image.sldStyle(normalize_sld), {}, 'Normalized');

在GEE中使用LSD还需要注意以下几点:

  • 同时支持OGC SLD1.0和OGC SLD1.1;
  • 传输的XML可以是完整的,也可以只有R a s te r Symbolizer及以下的部分;
  • 波段可以取GEE中的名字,或者是自然数,不能是其他东西;
  • 仅在透明时才会考虑不透明度值,非零时都被视为完全不透明;
  • OverlapBehavior定义都将被忽略;
  • 不支持ShadedRelief机制;
  • 不支持ImageOutline机制;
  • Geometry不被纳入运行范围;
  • 如果使用Normalization或者Histogram,输出图像将会带有histogram_bandname格式的元数据;

Thumbnail\ images


缩略图

使用ee.Image.getThumbURL()函数得到一个ee.Image的PNG或者JPEG缩略图。图像会显示在浏览器中,通过选择图像右边菜单中适当的选项,可以下载图片。

浏览器中显示SRTM的PNG略缩图

getThumbURL()Map.addLayer()共享参数,但它还多了一些选项,比方说dimensionregioncrs等,分别用来控制空间范围、尺寸还有缩略图显示部分。

Additional Parameters for ee.Image.getThumbURL() with Note on Format
parameter Description Type
dimension 以像素为单位的缩略图尺寸,如果提供一个整数,则它定义了图像比较大的边并按比例缩放出较小的边,如果尺寸很大,默认为512像素 WIDTHxHEIGHT形式的字符串或是一个整形数
region 需要渲染的地理空间区域,默认是整个图像或是提供的几何图像的边界 GeoJSON格式或是二维列表,提供至少三个点
crs 目标投影,默认是WGS84 字符串
format 定义略缩图是PNG还是JPEG,默认PNG格式为RGBA,alpha通道表示图像蒙版的有效和无效像素,无效像素是透明的,JPEG格式为RGB,无效像素使用零填充 字符串,‘png’或‘jpg’其中之一

单波段图像默认是灰度的,除非使用palette。多波段图像默认是RGB格式,除非使用bands参数。如果只有两个波段,第一个被设置为红色,第二个则是蓝色,绿色全部置零。

下面是一系列结合了getThumbURL()的实例代码,当你Run这些代码的时候,可以多看看打印到面板多URL。

// Fetch a digital elevation model.
var image = ee.Image('CGIAR/SRTM90_V4');

// Request a default thumbnail of the DEM with defined linear stretch.
// Set masked pixels (ocean) to 1000 so they map as gray.
var thumbnail1 = image.unmask(1000).getThumbURL({
  'min': 0,
  'max': 3000
});
print('Default extent and size:', thumbnail1);

// Specify region by GeoJSON, define palette, set size of the larger aspect dimension.
var thumbnail2 = image.getThumbURL({
  'min': 0,
  'max': 3000,
  'palette': ['00A600','63C600','E6E600','E9BD3A','ECB176','EFC2B3','F2F2F2'],
  'dimensions': 500,
  'region': ee.Geometry.Rectangle([-84.6, -55.9, -32.9, 15.7]).toGeoJSON(),
});
print('GeoJSON region, palette, and max dimension:', thumbnail2);

// Specify region by list of points and set display CRS as Web Mercator.
var thumbnail3 = image.getThumbURL({
  'min': 0,
  'max': 3000,
  'palette': ['00A600','63C600','E6E600','E9BD3A','ECB176','EFC2B3','F2F2F2'],
  'region': [[-84.6, 15.7], [-84.6, -55.9], [-32.9, -55.9]],
  'crs': 'EPSG:3857'
});
print('Linear ring region and specified crs', thumbnail3);

getThumbURL旨在产生一个预览图像,所以尺寸被限制在100,000,000像素大小,浏览器可能时间超限,如果想要更大的图,可以参考这里


\tag{此页面最后更新于2019年7月11日}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容