作者: _养乐多_
本文记录了在Google Earth Engine (GEE) 平台上对影像去除异常值的方法和代码。
Google Earth Engine (GEE) 提供了多种方法来去除影像异常值,以下是一些可能有用的技巧:
-
普通异常值过滤:使用
ee.Image.clip()
或ee.Image.updateMask()
方法,将高于或低于阈值的像素值设为 null 或其他合适的值。例如,可以使用image.updateMask(image.lt(threshold))
将小于某个阈值的像素值设为 null。 -
基于多波段的异常值检测:使用
ee.Image.reduce()
或ee.Image.select()
方法选择多个波段,然后使用ee.Image.unmix()
方法将图像分解为不同的成分。这些成分中可能有一些是异常值,可以使用统计方法,如标准差和均值来检测和去除这些异常值。 -
基于空间和时间的异常值检测:使用空间和时间分析方法,如聚类、时间序列分析等,来检测和去除影像中的异常值。例如,可以使用时间序列分析方法,如基于季节模型的异常值检测,来检测异常的时间序列值。
-
基于机器学习的异常值检测:使用监督学习方法,如决策树、随机森林等,来建立模型并检测异常值。例如,可以使用随机森林分类器来检测异常像素。
这些技巧可以单独或结合使用,具体取决于您的数据和研究问题。在 GEE 中,您可以使用 JavaScript 代码来实现这些方法。
一、普通异常值过滤
普通异常值过滤通常是指在像素值方面存在异常值时,使用阈值将这些异常值从图像中移除或替换为其他值。在 GEE 中,可以使用 ee.Image.updateMask() 或 ee.Image.clip() 方法来实现这一过滤。
下面是一个使用 ee.Image.updateMask() 方法实现异常值过滤的示例代码:
// 选择要处理的图像
var image = ee.Image('LANDSAT/LC08/C01/T1_SR/LC08_044034_20140318');
// 设置异常值的阈值范围
var minValue = 0;
var maxValue = 5000;
// 将小于阈值的像素设为 null
var filteredImage = image.updateMask(image.gte(minValue).and(image.lte(maxValue)));
// 打印结果
print('Original image', image);
print('Filtered image', filteredImage);
另一种实现异常值过滤的方法是使用 ee.Image.clip() 方法。这种方法类似于 ee.Image.updateMask() 方法,但是使用了不同的语法。以下是使用 ee.Image.clip() 方法实现异常值过滤的示例代码:
// 选择要处理的图像
var image = ee.Image('LANDSAT/LC08/C01/T1_SR/LC08_044034_20140318');
// 设置异常值的阈值范围
var minValue = 0;
var maxValue = 5000;
// 将小于阈值的像素设为 null
var filteredImage = image.clip(image.geometry()).updateMask(image.gte(minValue).and(image.lte(maxValue)));
// 打印结果
print('Original image', image);
print('Filtered image', filteredImage);
二、按照百分位数来去除异常值
按照百分位运算来去除异常值,可以使用以下步骤:
-
选择要处理的图像或图像集合。
-
计算图像中每个像素的百分位数,例如,可以使用 ee.Image.reduce() 方法和 ee.Reducer.percentile() 函数来计算每个像素在整个时间序列中的百分位数值。
-
选择要去除的异常值的范围,例如,您可以选择去除小于第1个百分位数和大于第99个百分位数的像素。
-
将图像中位于异常值范围内的像素设为 null 或其他合适的值,例如,可以使用 ee.Image.updateMask() 方法将这些像素的值设为 null。
以下是一个使用 GEE JavaScript API 实现上述步骤的示例代码:
// 选择要处理的图像集合
var imageCollection = ee.ImageCollection('MODIS/006/MOD13A1').select('NDVI');
// 计算每个像素在整个时间序列中的百分位数值
var p1 = imageCollection.reduce(ee.Reducer.percentile([1])).rename('p1');
var p99 = imageCollection.reduce(ee.Reducer.percentile([99])).rename('p99');
// 选择要去除的异常值的范围,并将图像中的异常值设为 null
var filteredCollection = imageCollection.map(function(image) {
var mask = image.updateMask(image.gte(p1).and(image.lte(p99)));
return image.mask(mask);
});
// 打印结果
print('Original collection', imageCollection);
print('Filtered collection', filteredCollection);
在上述示例中,我们选择了 MODIS 的 NDVI 数据集,并计算了每个像素在整个时间序列中的第1和第99个百分位数值。然后,我们选择了去除小于第1个百分位数和大于第99个百分位数的像素,并将这些像素的值设为 null。最后,我们打印了原始集合和过滤后的集合,以进行比较。
三、基于多波段的异常值去除
基于多波段的异常值去除可以通过以下步骤实现:
-
选择要处理的多波段图像或图像集合。
-
计算每个像素在每个波段中的像素值,例如,可以使用 ee.Image.select() 方法和 ee.Image.addBands() 方法将每个波段的像素值合并到一个图像中。
-
选择要去除的异常值的范围,例如,您可以选择去除小于第1个百分位数和大于第99个百分位数的像素。
-
将图像中位于异常值范围内的像素设为 null 或其他合适的值,例如,可以使用 ee.Image.updateMask() 方法将这些像素的值设为 null。
以下是一个使用 GEE JavaScript API 实现上述步骤的示例代码:
// 选择要处理的多波段图像
var image = ee.Image('LANDSAT/LC08/C01/T1_SR/LC08_044034_20140318').select(['B2', 'B3', 'B4']);
// 计算每个像素在每个波段中的像素值
var combinedImage = image.addBands(image.select('B3')).addBands(image.select('B4'));
// 计算每个像素在所有波段中的百分位数值
var p1 = combinedImage.reduce(ee.Reducer.percentile([1])).rename('p1');
var p99 = combinedImage.reduce(ee.Reducer.percentile([99])).rename('p99');
// 选择要去除的异常值的范围,并将图像中的异常值设为 null
var filteredImage = combinedImage.mask(combinedImage.gte(p1).and(combinedImage.lte(p99)));
// 打印结果
print('Original image', image);
print('Filtered image', filteredImage);
在上述示例中,我们选择了 Landsat 8 的一幅多波段图像,并计算了每个像素在所有波段中的第1和第99个百分位数值。然后,我们选择了去除小于第1个百分位数和大于第99个百分位数的像素,并将这些像素的值设为 null。最后,我们打印了原始图像和过滤后的图像,以进行比较。
四、基于空间和时间的异常值去除
基于空间和时间的异常值去除可以通过以下步骤实现:
-
选择要处理的多时相多波段图像集合。
-
将图像集合按时间顺序排序,例如,可以使用 ee.ImageCollection.sort() 方法将图像集合按时间顺序排序。
-
计算每个像素在每个波段中的像素值,例如,可以使用 ee.Image.select() 方法和 ee.Image.addBands() 方法将每个波段的像素值合并到一个图像中。
-
计算每个像素在所有时间和波段中的百分位数值,例如,可以使用 ee.ImageCollection.reduce() 方法和 ee.Reducer.percentile() 方法计算每个像素在所有时间和波段中的百分位数值。
-
选择要去除的异常值的范围,例如,您可以选择去除小于第1个百分位数和大于第99个百分位数的像素。
-
将图像中位于异常值范围内的像素设为 null 或其他合适的值,例如,可以使用 ee.Image.updateMask() 方法将这些像素的值设为 null。
以下是一个使用 GEE JavaScript API 实现上述步骤的示例代码:
// 选择要处理的多时相多波段图像集合
var collection = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(ee.Geometry.Point(-122.2627, 37.8735))
.filterDate('2013-01-01', '2019-12-31')
.select(['B2', 'B3', 'B4']);
// 将图像集合按时间顺序排序
var sortedCollection = collection.sort('system:time_start');
// 计算每个像素在每个波段中的像素值
var combinedImage = sortedCollection.toBands();
// 计算每个像素在所有时间和波段中的百分位数值
var p1 = combinedImage.reduce(ee.Reducer.percentile([1])).rename('p1');
var p99 = combinedImage.reduce(ee.Reducer.percentile([99])).rename('p99');
// 选择要去除的异常值的范围,并将图像中的异常值设为 null
var filteredImage = combinedImage.updateMask(combinedImage.gte(p1).and(combinedImage.lte(p99)));
filteredImage = ee.ImageCollection([filteredImage]).toBands();
// 打印结果
print('Original collection', collection);
print('Filtered collection', filteredImage);
在上述示例中,我们选择了 Landsat 8 的一个多时相多波段图像集合,并按时间顺序排序。然后,我们计算了每个像素在所有时间和波段中的第1和第99个百分位数值。接着,我们选择了去除小于第1个百分位数和大于第99个百分位数的像素,并将这些像素的值设为 null。最后,我们打印了原始图像集合和过滤后的图像集合,以进行比较。
五、基于机器学习的异常值去除
基于机器学习的异常值去除有很多方法,这里介绍几种常用的方法:
-
孤立森林算法(Isolation Forest):这个算法基于决策树,可以有效地隔离数据中的异常点。这个算法的工作原理是:首先随机选择一个特征,然后在该特征的最大值和最小值之间随机选择一个分裂值。这个过程重复进行直到决策树被完全构建,然后通过测量隔离点所需的分裂次数来评估它的异常性。
-
局部离群因子算法(Local Outlier Factor,LOF):这个算法通过比较点的局部密度来识别异常值。它计算周围点的密度,并将目标点的密度与周围点的密度进行比较。如果目标点的密度比周围点的密度低,那么它就被认为是异常值。
-
孪生网络算法(Siamese Networks):这个算法将数据点映射到一个低维空间中,并利用距离度量来衡量数据点之间的相似性。异常值的度量距离通常比正常值的度量距离更大,因此可以使用距离度量来识别和去除异常值。
这些算法都需要一定的编程知识和数据处理技能,但可以通过Python等编程语言的机器学习库来实现。