① var median = collection.reduce(ee.Reducer.median());
② var median = collection.median();
这两个表达完全一致,只是写法不同,最后得到的都是一张image。reducing:在collection的所有数据中逐像元地进行统计并归纳到一张单图层的图像上。
注意:通过reduce imagecolletion产生的composite image可以根据指定投影产生各种pixel,所以它本身是没有投影的。相反composites的默认投影是WGS-84,分辨率1°
compositing and mosaicking:
Landsat8影像去云代码:建议直接用.
// Define a function that scales and masks Landsat 8 surface reflectance images.
function prepSrL8(image) {
// Develop masks for unwanted pixels (fill, cloud, cloud shadow).
var qaMask = image.select('QA_PIXEL').bitwiseAnd(parseInt('11111', 2)).eq(0);
var saturationMask = image.select('QA_RADSAT').eq(0);
// Apply the scaling factors to the appropriate bands.
var getFactorImg = function(factorNames) {
var factorList = image.toDictionary().select(factorNames).values();
return ee.Image.constant(factorList);
};
var scaleImg = getFactorImg([
'REFLECTANCE_MULT_BAND_.|TEMPERATURE_MULT_BAND_ST_B10']);
var offsetImg = getFactorImg([
'REFLECTANCE_ADD_BAND_.|TEMPERATURE_ADD_BAND_ST_B10']);
var scaled = image.select('SR_B.|ST_B10').multiply(scaleImg).add(offsetImg);
// Replace original bands with scaled bands and apply masks.
return image.addBands(scaled, null, true)
.updateMask(qaMask).updateMask(saturationMask);
}
qualityMosaic和max的区别:
GEE学习笔记 五十九:GEE中mosiac、qualityMosiac、max区别_qualitymosaic_无形的风(知乎)的博客-CSDN博客
二者都是对imagecollection操作,max后是变成image(每个pixel上看一遍 取最大值),是默认选第一个波段 / 指定一个波段的信息。qualityMosaic不是取最大值,它返回的是最大值对应的原始数据。
比如, 一个collection有7个波段,max是各波段都算了max;但后者按ndvi值排序的话,结果是最绿像元所对应时刻的地表反射率的值(只是用ndvi做一个索引)。如果是单波段数据 / colletion中只有一张影像,区别不大。
应用场景:计算全中国ndvi最大值出现的时间 (https://code.earthengine.google.com/a30f907a809a2e6abb2d631ad5ab2f60?noload=1)。collection要有时间戳,把时间放在波段上,再对NDVI进行qualityMosaic,就得到doy了。如果对时间排序则是最新的。官网的例子(https://developers.google.com/earth-engine/guides/ic_composite_mosaic)是NDVI最大值(最绿)像元的合成以及最新时间的合成。
【董老师 直观比较二者的区别】https://code.earthengine.google.com/bc3208123a98779e1326830fe8bc4aaf
比如在这个代码中,结果有显著差异,因为max后, 是在img的每个像元上三个波段都是最大。
iterate:累加(类似for循环)。
GEE 学习笔记 9:for,while,map,evaluate,iterate的异同 - 知乎
👆 利用 landsat8,用map / iterate的方法计算 2013-2020 年武汉市年平均 NDVI 值, 并导出 GIF.
其中, 这段代码也可以学习一下: 导入自己的数据(矢量), 筛选出某个geometry.
var roi = ee.FeatureCollection("users/comingboy1118/China/CH_shi");
var roi = roi.filter(ee.Filter.eq("市","武汉市")).geometry()
Map.addLayer(roi,{"color":'red',},"roi")
Map.centerObject(roi, 8)
① nanshan分区的代码
选了10个候选特征,缓冲区,设置时间、算指数、去云。得到原始数据集,是1564个elements。
中值合成:advances其实就是0、60、120的list,从0-60、60-120、120-180进行map对这三个间隔中值合成。结果seasonalS2就是合成后的,是包含3张images(doy分别是109、169、229)的List。
那么接着,seasonals是对seasonalS2(list)进行iterate操作。其中,mergeBands是个function,后面的image[]则是个空的初始值。结果是有30个波段的image(3×10)。
【总结:每加一个新数要把原来的和(赋初始值0)也加上,再迭代,出来一个新数就加一个。
上面代码中,element是新数,previous是前面的和,按照顺序处理每一个,直到下一个。】
② 官方代码: 计算EVI的累加值。
计算了EVI的2011-2014年每景影像 减去 十年EVI均值的结果,增加了时间戳属性,称之为“EVI anomaly”, 然后累加这个anomaly (即series).
“ 对 iterate ()的每次调用都会将anomaly添加到正在运行的sum中,并将结果添加到list中。最后的结果传递给 ImageCollection 构造函数,以获得一个新的image序列。”
// Load MODIS EVI imagery.
var collection = ee.ImageCollection('MODIS/006/MYD13A1').select('EVI');
// Define reference conditions from the first 10 years of data.
var reference = collection.filterDate('2001-01-01', '2010-12-31')
// Sort chronologically in descending order.
.sort('system:time_start', false);
// Compute the mean of the first 10 years.
var mean = reference.mean();
// Compute anomalies by subtracting the 2001-2010 mean from each image in a
// collection of 2011-2014 images. Copy the date metadata over to the
// computed anomaly images in the new collection.
var series = collection.filterDate('2011-01-01', '2014-12-31').map(function(image) {
return image.subtract(mean).set('system:time_start', image.get('system:time_start'));
});
// Display cumulative anomalies.
Map.setCenter(-100.811, 40.2, 5);
Map.addLayer(series.sum(),
{min: -60000, max: 60000, palette: ['FF0000', '000000', '00FF00']}, 'EVI anomaly');
累加函数是accumulate. 累加方式: 在原来list的基础上, 再加上当前image的值.
再下一段cumulative是应用iterate, 里面是accumulate函数, 以及first初始值(空的EVI).
具体来看, 主要是累加的函数: 当前的image加上previous的和. 从first开始迭代. 另外, 他是把list作为初始的迭代, 所以后面还要把list转为imagecollection.
// Get the timestamp from the most recent image in the reference collection.
var time0 = reference.first().get('system:time_start');
// Use imageCollection.iterate() to make a collection of cumulative anomaly over time.
// The initial value for iterate() is a list of anomaly images already processed.
// The first anomaly image in the list is just 0, with the time0 timestamp.
var first = ee.List([
// Rename the first band 'EVI'.
ee.Image(0).set('system:time_start', time0).select([0], ['EVI'])
]);
// This is a function to pass to Iterate().
// As anomaly images are computed, add them to the list.
var accumulate = function(image, list) {
// Get the latest cumulative anomaly image from the end of the list with
// get(-1). Since the type of the list argument to the function is unknown,
// it needs to be cast to a List. Since the return type of get() is unknown,
// cast it to Image.
var previous = ee.Image(ee.List(list).get(-1));
// Add the current anomaly to make a new cumulative anomaly image.
var added = image.add(previous)
// Propagate metadata to the new image.
.set('system:time_start', image.get('system:time_start'));
// Return the list with the cumulative anomaly inserted.
return ee.List(list).add(added);
};
// Create an ImageCollection of cumulative anomaly images by iterating.
// Since the return type of iterate is unknown, it needs to be cast to a List.
var cumulative = ee.ImageCollection(ee.List(series.iterate(accumulate, first)));
// Predefine the chart titles.
var title = {
title: 'Cumulative EVI anomaly over time',
hAxis: {title: 'Time'},
vAxis: {title: 'Cumulative EVI anomaly'},
};
// Chart some interesting locations.
var pt1 = ee.Geometry.Point(-65.544, -4.894);
print('Amazon rainforest:',
ui.Chart.image.series(
cumulative, pt1, ee.Reducer.first(), 500).setOptions(title));
var pt2 = ee.Geometry.Point(116.4647, 40.1054);
print('Beijing urbanization:',
ui.Chart.image.series(
cumulative, pt2, ee.Reducer.first(), 500).setOptions(title));
var pt3 = ee.Geometry.Point(-110.3412, 34.1982);
print('Arizona forest disturbance and recovery:',
ui.Chart.image.series(
cumulative, pt3, ee.Reducer.first(), 500).setOptions(title));
上图是anomaly的多年值,但我们常用累加的anomaly, 因此要用到iterate.
[师兄提问: 为什么要用list作为空的first]: first必须是个list. 因为series是个collection, 它迭代时输出的是list, 所以初始的必须也是list. 可以理解为只能在list或者collection上迭代.