20231011更新:从很常用的SPEI网站(时间分辨率1月、3月……,0.5°)
https://spei.csic.es/spei_database/#map_name=spei01#map_position=1459
用GEE简单做了一张anomaly动图。发现以下几个点:
(1)ImageCollection做动图,用 getVideoThumbURL 可以实现。
// Define arguments for animation function parameters.
var videoArgs = {
dimensions: 2268, //根据研究区大小确定;区域越大这个值应当越大
region: geometry,
framesPerSecond: 0.5, //帧率,每秒0.5张image即每张图停留2秒
crs: 'EPSG:4326',
min: -3,
max: 3,
//palette: ["d53e4f","fc8d59","fee08b","ffffbf","e6f598","99d594","3288bd"]
palette: ['red', 'orange', 'yellow', 'green', 'cyan', 'blue']
};
// Print the animation to the console as a ui.Thumbnail using the above defined
// arguments. Note that ui.Thumbnail produces an animation when the first input
// is an ee.ImageCollection instead of an ee.Image.
print(ui.Thumbnail(A, videoArgs));
// Alternatively, print a URL that will produce the animation when accessed.
print(A.getVideoThumbURL(videoArgs));
(2)统计某张image在区域上的均值(mean)、最大值(max)、最小值(min):
// anomaly4 是 image
var mean4 = anomaly4.select("b1").reduceRegion({
reducer: ee.Reducer.mean(),
//scale: 5550, //分辨率
geometry: MLYR,
maxPixels: 1e13,
//tileScale:16 //这个参数没懂是啥,所以注释掉了,应该不影响
})
print("4",mean4) //mean4 是 dictionary类型的object,打印出来的数字即是区域均值
// 或者
print(image.reduceRegion({reducer: ee.Reducer.mean(), geometry: MLYR_China}))
注意,上面函数中的 tileScale (Float, default: 1):
reduceRegions(collection, reducer, scale, crs, crsTransform, tileScale)
// https://zhuanlan.zhihu.com/p/466552413
这个参数一般是在计算大区域统计的时候,会出现超限的情况下使用的参数,一般是2的n次方。默认状况下是1,所以如果当我们研究全球区域,分辨率又很高的话,建议瓦片设置小一些,这样可以避免超限计算,出现无法计算的情况。 “一个介于0.1和16之间的比例系数,用于调整聚合瓦片的大小。一个用于减少聚合瓦片大小的缩放系数;使用更大的tileScale(例如2或4)可能会使计算在默认情况下耗尽内存。”
另外,reduceRegions 在服务端进行区域统计计算,不返回图像。如果需要图像,直接用 .reduce(ee.Reducer.mean());
如果批量计算collection 中每张image的mean,则:
// take ERA5 SM as an example
// 转换为月份image列表
var months = collection.toList(collection.size());
// 迭代计算均值并打印
for (var i = 0; i < months.size().getInfo(); i++) {
var img = ee.Image(months.get(i));
var mean = img.reduceRegion({
reducer: ee.Reducer.mean(),
geometry: ROI,
scale: 5550
}).get('soil_temperature_level_1_mean');
print(mean); //从reduceRegion返回的dictionary中提取出均值结果
}
(3)GEE在线地图中添加图例:
https://code.earthengine.google.com/451b3fe0ee81e99d7c347fdc4c5bb745
(4)按时间先后顺序排列imagecollection:
.sort('system:time_start')
PS:简单的代码(自己写自己看):
multiyear的SPEI值:https://code.earthengine.google.com/700d5e7bdd87b9ab934be1312c34d892
2022年的SPEI值:https://code.earthengine.google.com/85ac123db3eb8448f389908469746a4d
(5)获取 imagecollection 中的第n张image:
// 获取imagecollection中属性month为5的image
var img1 = collection.filter(ee.Filter.eq('month', 5)).first()
// 同上,如果只有 system:index 属性:一定要记得数字那里加单/双引号
var img1 = collection.filter(ee.Filter.eq("system:index", "4")).first()
// 或者(toList()后获取的是Dictionary对象,后续进行运算需要验证是否能直接用。)
// img2 和 img1的结果相同,probably
var img2 = collection.toList(collection.size()).get(4)
// 或者(这个必须有时间戳,否则会报错)
// (Can't apply calendarRange filter to objects without a timestamp)
var img3 = Collection.filter(ee.Filter.calendarRange(5,5,'month')).first()
(6)imagecollection运算、map等操作后,保留原有所有属性/保留某个属性(时间戳、月份):
.copyProperties(image)
.set('system:time_start', ee.Date(image.get("system:time_start")))
.set('month', monthInteger) //获取system:time_start中的月份?
// 或者
.set('month', ee.Date(filtered.get('system:time_start')).get('month'))
(7)重命名波段
.select(['old'], ['new'])
(8)两个imagecollection 对应时间的 image 加减乘除四则运算 / 求均值,可以用 combine / merge / ee.Join.inner
Google Earth Engine(GEE)——ee.Join.inner的使用方法(以两个MODIS影像集合为例组成一个MODIS多波段影像集合)_此星光明的博客-优快云博客
虽然还是分不清这三个,但是浅浅写一下自己的理解:
- merge 是 imagecollection 的原始信息都不变,只不过把所有 image 按一定顺序(可能是时间)排列起来,即 image 的数量变多、原始信息保留。
- ee.Join.inner 就很少用了,不了解。看指南上,似乎无法对 imagecollection 和 image 操作?
- combine是对于 image 的数量、属性相同(有matching ID)的两个imagecollection(即它们中 image 的默认的system:index 一致) 的处理,合并的结果是对应ID的 image 作差,得到一个新的imagecollection,image数量不变,combine了 band。例如:
var A = esTd.combine(esT) //esTd esT是两个imagecollection,image数量一致,波段不同
var newIc = A.map(function(img){
// Get band1 and band2
var band1 = img.select('dewpoint_temperature_2m');
var band2 = img.select('temperature_2m');
// 目的:处理得到新波段;大家自行按需更改/跳过。
var newImg = band1.divide(band2)
.set('system:time_start', img.get('system:time_start'))
.select(['dewpoint_temperature_2m'], ['newBand']) // 重命名波段;
// Return the new image
return newImg;
});
原始ic VS combine后:
要注意,必须有 matching system:index。否则,如果system:index的数字不一致,但有其他属性比如month一致,是无法 combine 的。那么这种情况怎么办呢?
var list = ee.List.sequence(1,12)
var VPD = ee.ImageCollection(list.map(function(m){
var img1 = VPD2022.filter(ee.Filter.eq('month', m)).first()
var img2 = multi.filter(ee.Filter.eq('month', m)).first()
return img1.subtract(img2).copyProperties(img1)
}))
拓展【filter的操作】:GEE(Google Earth Engine)学习——常用筛选器Filter操作 - 代码先锋网
(9)上面代码暗含的知识点:筛选Imagecollection的属性:
// For collection with timestamp
.filter(ee.Filter.calendarRange(7,7,'month'))
// For collection without timestamp; "month" is one of the properties
.filter(ee.Filter.eq('month',7))
注意,image的某个property,放在括号左边且加引号;它的值放在右边。
插值和填补(我用的第一个链接的代码处理 MOD09A1 )
GEE 时序插值实现MODIS 8天无云影像代码免费分享_modis下载无云影像gee_CDUT_HS_2021的博客-优快云博客
【精选】Google Earth Engine(GEE)——MODIS影像平滑函数的进行_gee引擎 有平滑吗_此星光明的博客-优快云博客
Google Earth Engine(GEE)填补缺失影像_wx62ae92a1373c3的技术博客_51CTO博客
GEE:线性插值方法填补去云空洞——以 MCD43A4 和 NDVI 时间序列为例-优快云博客
Google Earth Engine(GEE)——NDVI时序线性插值补缺和导出视频结果案例分析(北京奥森公园为例)_gee线性插值-优快云博客
还有一种简单的填补方法:
// Method: https://blog.51cto.com/u_15690141/5782547
var replacedVals = Collection2022.map(function(image){
var currentDate = ee.Date(image.get('system:time_start'));
var meanImage = Collection2022.filterDate(
currentDate.advance(-2,'month'), currentDate.advance(2, 'month')).mean();//33333333333333333333333max min median
// 替换所有被屏蔽的值
return meanImage.where(image, image);
});
print(replacedVals)
Map.addLayer(Collection2022.first());
Map.addLayer(replacedVals.first());
MCD43A4 平滑:
【精选】Google Earth Engine(GEE)——MODIS影像平滑函数的进行_gee引擎 有平滑吗_此星光明的博客-优快云博客
知乎某大佬:
SG滤波:遥感影像SG滤波(基于GEE) - 知乎
区域统计:Google Earth Engine(区域统计) - 知乎
趋势分析:Google Earth Engine(趋势分析) - 知乎
其他:
在 GEE 实现 Savitzky-Golay 平滑滤波 - 知乎
google earth engine随缘学习(十三)SG滤波_sg滤波算法-优快云博客
(https://code.earthengine.google.com/fe8f4b806bca83af87df17ace1ae13e4)
n = 2m+1,即通常为奇数.
窗口大小(window_size):窗口大小是用于局部拟合的数据点的数量。通常选择奇数,以便在中心点左右有相等数量的数据点。窗口大小越大,平滑效果越明显,但过大的窗口可能会导致信号失真。