本文介绍在谷歌地球引擎(Google Earth Engine,GEE)中,计算长时间序列遥感影像数据在多年中,在每一个指定天数的时间范围内的平均值的方法。本文是谷歌地球引擎(Google Earth Engine,GEE)系列教学文章的第二十篇。
首先,我们来看一下本文需要实现的需求。现在我们希望,计算某个研究区域中,2022
年内每一个8
天的时间范围内,NDVI数据的平均值。换句话说,我们希望对于2022
年的001
天到008
天内的全部NDVI数据计算平均值,然后再对009
天到016
天内的全部NDVI数据计算平均值,然后再对017
天到024
天内的全部NDVI数据计算平均值,依此类推。最后,我们对每一个8
天范围内的平均值结果图像加以导出。这个需求和我们之前的Python自动计算Excel数据指定范围内的区间最大值有些类似,不过当时的文章中,我们是将遥感影像中某一个像元的多年数据提取到Excel中,且计算的是最大值;而在本文中,我们希望是对整个研究区域内的全部遥感影像加以指定间隔时期内数据的计算,且计算的是平均值。
明确了需求,我们即可开始代码的撰写。本文所用代码如下。
var year = ee.String("2022");
var ndvi = ee.ImageCollection("MODIS/MYD09GA_006_NDVI")
.filterDate('2022-01-01', '2023-01-01')
.select(["NDVI"]);
var chinaBoundary = ee.Geometry.Rectangle(70, 14, 137, 52);
var selectedDays = ee.List.sequence(1, 366, 8);
var filterAndClip = function(day) {
var start = ee.Number(day);
var end = start.add(7);
var filtered = ndvi.filter(ee.Filter.calendarRange(start, end, 'day_of_year'))
.map(function(image) {
// print(start);
// print(end);
// return image.clip(chinaBoundary).reproject('EPSG:4326', null, 500);
return image.clip(chinaBoundary)
});
// Map.addLayer(filtered, {}, 'NDVI');
var filtered_mean = filtered.reduce(ee.Reducer.mean());
// Map.addLayer(filtered_mean, {}, "NDVI_Mean");
// return filtered;
return filtered_mean;
// return filtered.reduce(ee.Reducer.mean());
};
var ndvi_china = ee.ImageCollection([]);
for (var i = 0; i < selectedDays.length().getInfo(); i++) {
var day = selectedDays.get(i);
var filtered = filterAndClip(day);
var exportParams = {
image: filtered,
description: year.cat(ee.Number(day).format('%03d')).getInfo(),
folder: "ndvi_8_days_new",
scale: 500,
region: chinaBoundary,
maxPixels: 10000000000000
};
Export.image.toDrive(exportParams);
ndvi_china = ndvi_china.merge(filtered);
}
首先,定义变量和数据源。其中,year
是一个包含字符串值2022
的Earth Engine字符串对象,后面我们导出遥感影像的时候,需要将其作为导出文件的文件名前缀。ndvi
是通过筛选日期和选择NDVI
波段来创建的MODIS NDVI影像集合。chinaBoundary
是本文中研究区域边界的矩形几何对象。selectedDays
是一个包含从1
到366
的数值列表,表示一年中每8
天的时间间隔。
随后,定义一个函数filterAndClip
,用于筛选指定时间范围内的NDVI影像集合,并对每个影像进行边界裁剪;最后,它返回裁剪后影像集合的平均值。对于这个函数,首先,函数接受一个参数day
,表示时间值。其次,将传入的时间值day
转换为Earth Engine数值对象,分别存储在start
和end
变量中;这里的day
是一个整数,表示一年中的某个时间。接下来,使用ee.Filter.calendarRange
函数对ndvi
影像集合进行筛选,根据day
、start
和end
的值,筛选出位于指定时间范围内的影像;这里使用'day_of_year'
参数表示筛选基于一年中的日期。随后,使用map
函数对筛选后的影像集合中的每个影像进行边界裁剪;image.clip(chinaBoundary)
将每个影像裁剪为中国边界范围内的部分。裁剪后的影像集合存储在filtered
变量中。其次,使用reduce
函数和ee.Reducer.mean()
对裁剪后的影像集合进行平均值计算;filtered.reduce(ee.Reducer.mean())
将每个像素位置的影像值取平均,生成一个表示平均值的影像。最后,函数返回裁剪和平均值计算后的影像集合filtered_mean
。
接下来,创建一个空的影像集合ndvi_china
,用于存储最后裁剪和筛选后的NDVI影像(但是我这里后面没有用上这个影像集合ndvi_china
,之所以有这个是之前别的需求会用到,后来更换需求了但是代码这里没有删除)。
其次,我们使用循环处理每个时间段。在循环中,我们遍历selectedDays
列表中的每个时间值。对于每个时间值,我们调用filterAndClip
函数来获取裁剪和筛选后的NDVI影像的平均值。
然后,我们定义了导出参数exportParams
,包括要导出的影像、描述、文件夹、比例尺、区域和最大像素数等。
最后,我们使用Export.image.toDrive
函数将筛选后的影像导出到Google Drive,并将其添加到ndvi_china
影像集合中。
执行上述代码,我们来看一下效果。这里需要注意,为了更好地展示代码的效果,运行时我将代码中如下所示位置的2
个Map.addLayer()
函数取消注释了。
首先,看一下“Inspector”。如下图所示,每一个NDVI_Mean
图像(下图中下方的紫色框内),都是其上方8
景图像(下图中上方的紫色框内)的平均值,也就是这8
天的NDVI的平均值。不难看出,下图中上方的紫色框内,8
景图像就是从当年第001
天到第008
天的NDVI,那么下图中下方的紫色框内就是从001
天到008
天的NDVI的平均值。
其次,看一下“Tasks”。如下图所示,这一年内每隔8
天的NDVI平均值结果图像都可以加以导出了。
至此,大功告成。