问题描述:“在GEE中想对图像窗口进行一些计算,比如3x3像元窗口,计算整个图像的某个公式,比如计算这个窗口像元的总平均值的来作为每个像元的新值”
解决方法:在GEE中使用移动窗口的方法来对影像进行计算主要用到了ee.Kernel.square/ee.Kernel.rectangle
和neighborhoodToArray
函数
Kernel用来确定核,即移动窗口的大小,单位可以是像素,也可以是米,使用方法如下:
var kernel = ee.Kernel.square({
radius:3, //移动窗口半径
units:"pixels", //单位
normalize:false,
})
定义完移动窗口大小以后,使用neighborhoodToArray函数来对移动窗口范围内的值进行计算,比如要使用3x3像元窗口内的平均值来作为新的值代替原像元值,可以使用如下方法:
var img_neiborhood_mean2 = img.reduceNeighborhood({
reducer:ee.Reducer.mean(), // 平均值
kernel:kernel, // 前面定义的kernel
}).rename('mean2');
返回的就是使用移动窗口对整个影像计算后的新影像。
这里以SRTM DEM为例计算,完整计算代码如下:
//定义roi范围
var roi = ee.Geometry.Polygon(
[[[110.51894680483909, 36.61075542452372],
[110.51894680483909, 33.98398879058431],
[113.97964016421409, 33.98398879058431],
[113.97964016421409, 36.61075542452372]]], null, false);
// 读取 DEM
var DEM = ee.Image("CGIAR/SRTM90_V4");
var img = DEM.clip(roi);
// 定义kernel
var kernel = ee.Kernel.square({
radius:3,
units:"pixels",
normalize:false,
});
// 移动窗口计算
var img_neiborhood_mean2 = img.reduceNeighborhood({
reducer:ee.Reducer.mean(),
kernel:kernel,
}).rename('mean2');
Map.addLayer(img_neiborhood_mean2,{min:0,max:1000},'mean2');
原始DEM:
移动窗口计算后:
这里只是使用简单的移动窗口内的平均值来代替,如果想要其他的也可以。比如计算这个窗口每个像元与窗口像元的总平均值的差,作为每个像元的新值,就可以先通过上述方法计算每个像元窗口内的平均值,然后使用原始影像减去平均值影像,就得到了需要的影像。ee.Reducer里面还有很多其他的函数,基本能够满足需要。
在网上看见也有其他方法,是使用Array的相关操作来实现,贴上使用Array的相关代码以供学习:
//定义roi范围
var roi = ee.Geometry.Polygon(
[[[110.51894680483909, 36.61075542452372],
[110.51894680483909, 33.98398879058431],
[113.97964016421409, 33.98398879058431],
[113.97964016421409, 36.61075542452372]]], null, false);
// 读取 DEM
var DEM = ee.Image("CGIAR/SRTM90_V4");
var img = DEM.clip(roi);
// 邻域转为Array,包括x和y两个轴
var img_neiborhood = img.neighborhoodToArray({
kernel:kernel,
});
// 计算移动窗口x和y轴的平均值
var img_neiborhood_mean = img_neiborhood.arrayReduce({
reducer:ee.Reducer.mean(),
axes:[0],
}).arrayReduce({
reducer:ee.Reducer.mean(),
axes:[1],
}).arrayProject([0]).arrayFlatten({
coordinateLabels:[['mean']],
// separator:"_",
})
Map.centerObject(roi);
Map.addLayer(img,{min:0,max:1000},'img');
Map.addLayer(img_neiborhood,{min:0,max:1000},'img_neiborhood');
Map.addLayer(img_neiborhood_mean,{min:0,max:1000},'img_neiborhood_mean');