EZ | Get Started with Earth Engine | GEE - 02

\
Get\ Started\ with\ Earth\ Engine


开始使用GEE

这篇引导旨在为大家使用JavaScript语言的API提供一个快速路径,如果想要JavaScript的详细介绍或是得到API更加深入的使用,可以看这里,如果想要关于JavaScript代码风格的建议,则可以看谷歌对于JS编码的指导
GEE允许用户对储存在Google基础框架上的地理配准图(Georeferrenced Imagery)和矢量(Vector)运行一些算法,API提供了很多的功能,可以在图像上有所运用,既可以做显示,又可以做分析。这里有一份GEE的公开数据清单,它包含了大量开源可用的图像和矢量数据集,大家也可以在个人文件夹里放一些自己的数据。

Fig.1 :GEE代码编辑器界面

代码编辑器(Code Editor)是一个用于开发GEE程序的交互式环境,界面就如Fig.1所示,中间的部分是一个JavaScript的代码编辑页面,编辑器上面有一些按钮,可以用来执行保存脚本、运行代码、清空页面等操作。还有一个Get Link按钮,可以在地址框(Address Bar)里生成一个唯一性的URL。底部的展示面板展示了正在运行的脚本所加入的所有图像层(Layer),顶部还有一个搜索栏(Search Box),可以搜索数据集,也可以搜索某个地点,随人所愿。左边有一个实例代码的展示区,可以用来存放脚本或是在里面找API或是在资产库(Asset)里检索自己的私人文件。右部有一个对检查器(Inspector)、一个输出面板(Output Console),还有一个对于任务管理器(Manager),帮助按钮在右上方,里面有指向指导文档的链接还有其他文件。可以从代码编辑器指导帮助文档中得到更多信息。


打开,并在代码编辑器中Run起来

我们演示一下如何打开GEE的并执行一下显示图像的脚步,如果想得到最好的效果,推荐安装最新的Chrome

  • 打开GEE代码编辑器如果你还没注册,那就用Google账户注册一个。
  • 代码编辑器最左边有一个脚本(Scripts)选项卡,可以在那里找到一组脚本实例,你可以访问、展示并且在GEE中运行它们。
  • 在图像集(Image Collection)下,选择过滤复合(Filtered Composite),你就能在中控台(Center Console)上看到一个脚本,点一下运行(Run)按钮,就会选择科罗拉多州和犹他州相交位置一定范围内Landsat-7卫星的图像,它的显示使用真彩色合成的,这个例子会展示一下filter()clip()Map.addLayer()等基本的功能。
    \
    \
    Earth\ Engine\ data\ Structures

GEE数据结构

GEE中两个最基本的数据结构是ImageImageCollection(这两个东西会经常用,也很好理解,不译),二者分别代表了光栅图像(Raster)和矢量图(Vector)。Image容纳里波段(Band)信息和一个特性(Properties)组成的字典,Feature则是由几何信息和特征字典组成。一个图像的堆栈可以被整合为一个ImageCollection,特征的集合则可以被整合为FeatureCollection,GEE中还有一些基本的数据结构,有DictionaryDataNumberString等,重要的是记住这些数据结构都是面向服务器端的,这就意味着,除非你特意要求,你的浏览器不会知道你的脚本的任何信息。而你的特意要求会从Google传递到代码编辑器,如果信息Size比较大,速度就会稍微慢一点。
\
\
Earth Engine Algorithms


GEE的计算方法

有好几种调用API的方法,包括:

  • 调用对象自己的方法;
  • 调用算法;
  • 使用代码编辑器中特有的的函数;
  • 定义一些新函数;

代码编辑器列表中的文档(Docs)里有各个API类的使用方法(Method),举个例子,在Image类里,有一个方法是这样用的:
var image3 = image1.add(image2);
这个方法把image2的波段添加到image1里,ee.Algorithms类包括一个特定算法的列表,想从输入的DEM中创建一个图层,可以这样做:
var terrainImage = ee.Algorithms.Terrain(dem);
代码编辑器还有一些特殊的函数,包括Map还有其他的导出方法,能够把选中的图道导出到Google Drive中。在代码编辑器里,可以这样创建函数:

var myFunction = function(args) { 
  // do something
  return something;
};

想要使用定义好的函数去创造一个Collection,可以这样做:

var collection2 = collection1.map(aFunction);

在GEE中,静态的方法叫做Class(像是ee.Image),被写作Image.staticMethod()而在类的实例中被调用的放大被写作image.instanceMethod(),小写的image意思是这是一个名叫image的变量,是ee.Image的一个实例。

\
\
‘Hello\ world!’\ JavaScript


使用JavaScript打印‘Hello World!’

把特定的信息打印到输出面板上,是得到一个东西的信息的基本方法,展示一些数据性的结果,或是展示一个元数据(Metadata),或是一些Debug用的帮助信息,都可以这样做。在代码编辑器打印'Hello World!'是这样实现的:
print('Hello World!')
把这行代码Copy到代码编辑中,运行一下,就能在输出面板中看到我们想要的东西。对于一个遥感实例,下面的操作可以看一些Landsat 8卫星图像的一些元数据:
print(ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318'));
展示面板上就能看到这颗卫星的一些图像了。
\
\
Adding\ Data\ to\ the\ Map


往Map里增加一些数据

想要在展示面板上显示一些信息,尤其是一些可视化的信息,就要用到Adding操作,使用Map.addLayer()函数达成这一目的。下面的例子里,我们先用ee.Image()加载了一张Image,然后使用Map.addLayer()函数增加了一些东西,然后,地图就被居中显示。

// Load an image.
var image = ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318');
// Center the map on the image. 
Map.centerObject(image, 9);
// Display the image. 
Map.addLayer(image);

Map.centerObject()函数的第二个参数代表了缩放等级,越大的数字代表了越大的区域。如果对图像的显示效果不满意,可以对函数的一些参数做一些修改:

var image = ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318');
// Define visualization parameters in an object literal.
var vizParams = {bands: ['B5', 'B4', 'B3'], min: 5000, max: 15000, gamma: 1.3
// Center the map on the image and display. 
Map.centerObject(image, 9);
Map.addLayer(image, vizParams, 'Landsat 8 false color');

我们还可以使用这个函数增加一些feature或者featureCollection,代码如下:

var counties = ee.FeatureCollection('TIGER/2016/Counties'); 
Map.addLayer(counties, {}, 'counties');

\
\
Finding\ images,\ image\ collections\ and\ feature\ collections


找到你想要的数据

images、 image collections 和 feature collections都可以在GEE的数据清单里找到,在搜索栏中输入Landsat 8就可以找到这颗卫星,其他的也类似。完整的数据集的清单,可以在这里找到,点击数据集的名字,可以查看一些基本信息,包括数据来源、ID等等。点击导入(Import)按钮,可以把这个数据集加入进来,自动地,代码的头部就会出现对应的一行import代码。
也可以把数据集的ID复制到代码中来使用这个数据集:

var collection = ee ImageCollection(LANDSAT/LC08/C01/T1 )

一个Collection是来自地表的多层图像组成的,找到一个Collection里单张的图像要用到过滤器(Filter),也可以使用复合(Composite)和镶嵌(Mosaick)把一个图像的Collection削减到单张图像。对于过滤器、复合之类的详细信息,可以看对应部分的文档。

\
\
Filtering\ and\ Sorting


过滤和分类

我们经常需要根据空间和(或)时间对图像集进行过滤,主要目的是限制结果的数量,举个例子,想知道旧金山的Landsat 8数据中没有云雾遮挡的部分,就需要这样做。首先,我们需要定义一个ROI,一个点通常就足够了,点一下代码编辑器右边的检查(Inspector)按钮,就会看到你的ROI的信息,复制下来,然后就可以使用这个点了:

var point = ee.Geometry.Point(-122.262, 37.8719);

开始日期和结束日期应该这样设置:

var start = ee.Date('2014-06-01');
var finish = ee.Date('2014-10-01');

使用这个点和起止时间,就可以对图像进行过滤了。
当然,也可以把一些元数据进行修改,做到更好的过滤:

var filteredCollection = ee.ImageCollection('LANDSAT/LC08/C01/T1') 
    .filterBounds(point)
    .filterDate(start, finish)
    .sort('CLOUD_COVER', true);

这个Collection可以很安全地被展示并检查,当然,如果Collection中图像数量太多,可能会很慢,可能会时间超限,甚至可能返回一个error。可以把Collection视为一个列表,使用下面的方法观察第一张图:

var first = filteredCollection.first();

自己可以创建一些过滤器,操作如下:

// Load a feature collection.
var featureCollection = ee.FeatureCollection('TIGER/2016/States');
// Filter the collection.
var filteredFC = featureCollection.filter(ee.Filter.eq('NAME', 'California'))
// Display the collection. 
Map.addLayer(filteredFC, {}, 'California');

可以在编辑器上的Get Link按钮获得运行代码的一个唯一URL,方便分享或再次使用。
\
\
Band\ Math


在Band上执行一些数学操作

使用Image里的方法做一些数学性的操作,包括波段重组、图像区分或是其他数学的运算,举个例子,计算一下NDVI在20年间的变化:

// This function gets NDVI from Landsat 5 imagery. 
var getNDVI = function(image) {
  return image.normalizedDifference(['B4', 'B3']); 
};
// Load two Landsat 5 images, 20 years apart.
var image1 = ee.Image('LANDSAT/LT05/C01/T1_TOA/LT05_044034_19900604'); 
var image2 = ee.Image('LANDSAT/LT05/C01/T1_TOA/LT05_044034_20100611');
// Compute NDVI from the scenes. 
var ndvi1 = getNDVI(image1);
var ndvi2 = getNDVI(image2);
// Compute the difference in NDVI.
var ndviDifference = ndvi2.subtract(ndvi1);

这里使用了用户自己定义的函数,其他的函数在下一部分介绍。
\
\
Mapping\left(What\ to\ do\ instead\ of\ a\ for-loop\right)


重复测绘工作(拒绝循环程序)

使用map()函数做重复测绘,不要用循环。这个函数可以用在ImageCollectionFeatureCollection或是一个list里。示例代码把NDVI增加到ImageCollection里的每一张图像上:

// This function gets NDVI from Landsat 8 imagery. 
var addNDVI = function(image) {
  return image.addBands(image.normalizedDifference(['B5', 'B4'])); 
};
// Load the Landsat 8 raw data, filter by location and date. 
var collection = ee.ImageCollection('LANDSAT/LC08/C01/T1')
    .filterBounds(ee.Geometry.Point(-122.262, 37.8719))
    .filterDate('2014-06-01', '2014-10-01');
// Map the function over the collection.
var ndviCollection = collection.map(addNDVI);

另一个共同的任务是把一些东西增加到特征中,下面的实例就这样做了:

var sum = ee.Number(feature.get('property1')).add(feature.get('property2'))
return feature.set({'sum': sum}); };
// Create a FeatureCollection from a list of Features. 
var features = ee.FeatureCollection([
  ee.Feature(ee.Geometry.Point(-122.4536, 37.7403),
    {property1: 100, property2: 100}),
    ee.Feature(ee.Geometry.Point(-118.2294, 34.039),
    {property1: 200, property2: 300}),
]);

可以像下面这样吧Collection的类型修改掉:

// This function returns the image centroid as a new Feature.
var getGeom = function(image) {
  return ee.Feature(image.geometry().centroid(), {foo: 1}); };
// Load a Landsat 8 collection.
var collection = ee.ImageCollection('LANDSAT/LC08/C01/T1')
    .filterBounds(ee.Geometry.Point(-122.262, 37.8719))
    .filterDate('2014-06-01', '2014-10-01');
// Map the function over the ImageCollection.
var featureCollection = ee.FeatureCollection(collection.map(getGeom));
// Print the collection. 
print(featureCollection);

注意下那个foo,对每一个图像的中心它都被创建了。最后一行里我们把结果变成了一个FeatureCollection
\
\
Reducing


缩合

在GEE中,缩合是一种通过时间、空间、波段、数组或者其他数据结构将数据聚合在一起的一种方式,在API中,实现这一目的有多种方式。举个例子,如果想聚合成一个ImageCollection,可以使用reduce()函数将一个collection中的图像聚合成一张。这里有一个代码示例,把早就载入的Landsat-8卫星数据进行聚合,聚合的内容是至少五张无云的图像:

// Load a Landsat 8 collection.
var collection = ee.ImageCollection('LANDSAT/LC08/C01/T1')
    // Filter by date and location.
    .filterBounds(ee.Geometry.Point(-122.262, 37.8719)) 
    .filterDate('2014-01-01', '2014-12-31')
    // Sort by increasing cloudiness. 
    .sort('CLOUD_COVER');

// Compute the median of each pixel for each band of the 5 least cloudy scene 
var median = collection.limit(5).reduce(ee.Reducer.median());

缩合也是一种得到区域内图像统计信息的操作,这个任务是把感兴趣的区域内的像素点逐个进行处理,使用reducRegion()函数完成这一操作:

// Load and display a Landsat TOA image.
var image = ee.Image('LANDSAT/LC08/C01/T1_TOA/LC08_044034_20140318'); 
Map.addLayer(image, {bands: ['B4', 'B3', 'B2'], max: 0.3});

// Create an arbitrary rectangle as a region and display it.
var region = ee.Geometry.Rectangle(-122.2806, 37.1209, -122.0554, 37.2413); 
Map.addLayer(region);

// Get a dictionary of means in the region. Keys are bandnames. 
var mean = image.reduceRegion({
    reducer: ee.Reducer.mean(),
    geometry: region,
    scale: 30
});

关于缩合的具体信息,请看它的文档
\
\
Masking


蒙版

ee.Image中的每一个像素,都是既包含了值,有包含了一个范围从0到1取值的蒙版的实体,如果蒙版为0,那么就代表这个点完全被挡住了,GEE直接当做没有数据来处理,当蒙版取0到1之间其他值时,就把它当作参与数值计算的一个权值。
用户可以使用蒙版操作做像素转换或者排除它们,如上文所述,蒙版设置为0时意味着这个像素点被挡住了,继续看使用蒙版操作的代码实例:

// This function gets NDVI from Landsat 5 imagery. 
var getNDVI = function(image) {
    eturn image.normalizedDifference(['B4', 'B3']); 
};
// Load two Landsat 5 images, 20 years apart.
var image1 = ee.Image('LANDSAT/LT05/C01/T1_TOA/LT05_044034_19900604'); 
var image2 = ee.Image('LANDSAT/LT05/C01/T1_TOA/LT05_044034_20100611');

// Compute NDVI from the scenes. var ndvi1 = getNDVI(image1);
var ndvi2 = getNDVI(image2);
// Compute the difference in NDVI.
var ndviDifference = ndvi2.subtract(ndvi1);
// Load the land mask from the SRTM DEM.
var landMask = ee.Image('CGIAR/SRTM90_V4').mask();

// Update the NDVI difference mask with the land mask.
var maskedDifference = ndviDifference.updateMask(landMask);
// Display the masked result.
var vizParams = {min: -0.5, max: 0.5, palette: ['FF0000', 'FFFFFF', '0000FF'] 
Map.setCenter(-122.2531, 37.6295, 9);
Map.addLayer(maskedDifference, vizParams, 'NDVI difference');

这个例子里,注意一下NDVI中的蒙版,它用updataMask()函数做过一次更新。
蒙版操作对于把一些数据从分析范围排除出去也是很重要的操作,在它的文档可以看到更多实例。
下面的例子做了多种操作:过滤、重复测绘、缩合还有云层蒙版之类的:

// This function gets NDVI from a Landsat 8 image. 
var addNDVI = function(image) {
    return image.addBands(image.normalizedDifference(['B5', 'B4'])); 
};

// This function masks cloudy pixels. 
var cloudMask = function(image) {
    var clouds = ee.Algorithms.Landsat.simpleCloudScore(image).select(['cloud'])
    return image.updateMask(clouds.lt(10)); };

// Load a Landsat collection, map the NDVI and cloud masking functions over i 
var collection = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
    .filterBounds(ee.Geometry.Point([-122.262, 37.8719]))
    .filterDate('2014-03-01', '2014-05-31')
    .map(addNDVI)
    .map(cloudMask);

// Reduce the collection to the mean of each pixel and display.
var meanImage = collection.reduce(ee.Reducer.mean());
var vizParams = {bands: ['B5_mean', 'B4_mean', 'B3_mean'], min: 0, max: 0.5}; 
Map.addLayer(meanImage, vizParams, 'mean');

// Load a region in which to compute the mean and display it.
var counties = ee.FeatureCollection('TIGER/2016/Counties');
var santaClara = ee.Feature(counties.filter(ee.Filter.eq('NAME', 'Santa Clara'),
Map.addLayer(santaClara);

// Get the mean of NDVI in the region.
var mean = meanImage.select(['nd_mean']).reduceRegion({
    reducer: ee.Reducer.mean(), 
    geometry: santaClara.geometry(), 
    scale: 30
});

// Print mean NDVI for the region. mean.get('nd_mean').evaluate(function(val){
    print('Santa Clara spring mean NDVI:', val); 
});

\tag{该页面最后更新于2019年6月14日}

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