遥感

EZ | Get Started with Earth Engi

2019-07-18  本文已影响0人  杜若飞er

\
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数据结构

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日}

上一篇下一篇

猜你喜欢

热点阅读