根据属性的中值从 ee.ImageCollection 中选择图像
Selecting an image from an ee.ImageCollection based on the median value of an attribute
我正在为图像集赋予一个值,我想select图像具有该图像集的中值。
目前,我通过创建一个客户端值为图像的列表,将列表填充为奇数,然后使用中值获取我想要的 ID 和值,然后按该 ID 过滤集合来执行此操作。这行得通,但我必须在客户端调用获取值来计算中值 ID,然后过滤集合。我觉得这应该是可能的,而无需制作客户端列表。
所以我的问题是我是否可以在没有客户端列表的情况下执行此操作,EE 中的所有服务器端,我该怎么做?
'''
# returns a list of image data scores
client_list = get_attribute_and_id_client_side_list(ts_collection, 'datascore')
# padding so we always get a value rather than an average of 2
if len(client_list) % 2 == 0:
client_list.append(['padding', 0])
median_datscore = np.median([item[1] for item in client_list])
median_score_coll = ts_collection.filterMetadata('data_score', 'equals', median_datscore)
'''
所以基本上对于在元数据中具有值的图像集合,我想 select 仅具有 medain 值的图像而不使用任何客户端 getInfo()
您可以使用 ImageCollection.reduceColumns
算法来获取集合的 属性 的中值。然后您可以使用过滤器 select 具有该值的元素。
我在JavaScript里准备了一个例子,不过完全是服务端操作,翻译起来应该不会太难:
var landsat = ee.ImageCollection("LANDSAT/LC08/C01/T1_TOA");
var pointOfInterest = ee.Geometry.Point([-115.10699177547879, 40.56521148064664]);
var images = landsat
.filterDate('2017-05-01', '2017-09-01')
.filterBounds(pointOfInterest)
.map(function(img) {
// Add a numeric property for the example: the value of B2 at a point.
return img.setMulti(img.select(['B2'], ['B2_at_point']).reduceRegion({
reducer: ee.Reducer.mean(),
geometry: pointOfInterest,
}));
});
// Display the list of values, just for the example (this is not used further).
print(images.reduceColumns(ee.Reducer.toList(), ['B2_at_point']).get('list'));
// Compute the median.
var median = ee.Number(
images.reduceColumns(ee.Reducer.median(), ['B2_at_point'])
.get('median'));
print(median);
// Find the image or images that had the median.
var exactlyEqualsMedian = images.filter(ee.Filter.equals('B2_at_point', median));
var equalsOrNextToMedian = ee.ImageCollection(ee.Algorithms.If(
exactlyEqualsMedian.first(), // Is exactlyEqualsMedian nonempty?
exactlyEqualsMedian, // Then return it.
images // Otherwise find the nearest 2 images.
.map(function (i) {
return i.set('median_distance', median.subtract(i.get('B2_at_point')).abs());
})
.limit(2, 'median_distance')));
print(equalsOrNextToMedian);
Map.setCenter(-115.08, 40.56, 9);
Map.addLayer(equalsOrNextToMedian, {bands: ['B4', 'B3', 'B2'], max: 0.4, gamma: 1.6});
https://code.earthengine.google.com/4e0d3d59535722f55425618e7defefff
(请注意,此处的计算没有科学价值;这只是在图像集合中寻找中位数的示例。)
请注意,我没有采用将输入填充到 median() 的方法。相反,我随后进行过滤以选择完全匹配的图像或两个最接近的匹配图像。这是因为我希望它比尝试预先设置填充更有效(因为它需要额外查询集合以找出它有多大)。您当然可以在生成的 2 图像集合中选择适合您需要的任何图像 — 如果您不关心哪个图像,只需使用 equalsOrNextToMedian.first()
.
我正在为图像集赋予一个值,我想select图像具有该图像集的中值。
目前,我通过创建一个客户端值为图像的列表,将列表填充为奇数,然后使用中值获取我想要的 ID 和值,然后按该 ID 过滤集合来执行此操作。这行得通,但我必须在客户端调用获取值来计算中值 ID,然后过滤集合。我觉得这应该是可能的,而无需制作客户端列表。
所以我的问题是我是否可以在没有客户端列表的情况下执行此操作,EE 中的所有服务器端,我该怎么做?
'''
# returns a list of image data scores
client_list = get_attribute_and_id_client_side_list(ts_collection, 'datascore')
# padding so we always get a value rather than an average of 2
if len(client_list) % 2 == 0:
client_list.append(['padding', 0])
median_datscore = np.median([item[1] for item in client_list])
median_score_coll = ts_collection.filterMetadata('data_score', 'equals', median_datscore)
'''
所以基本上对于在元数据中具有值的图像集合,我想 select 仅具有 medain 值的图像而不使用任何客户端 getInfo()
您可以使用 ImageCollection.reduceColumns
算法来获取集合的 属性 的中值。然后您可以使用过滤器 select 具有该值的元素。
我在JavaScript里准备了一个例子,不过完全是服务端操作,翻译起来应该不会太难:
var landsat = ee.ImageCollection("LANDSAT/LC08/C01/T1_TOA");
var pointOfInterest = ee.Geometry.Point([-115.10699177547879, 40.56521148064664]);
var images = landsat
.filterDate('2017-05-01', '2017-09-01')
.filterBounds(pointOfInterest)
.map(function(img) {
// Add a numeric property for the example: the value of B2 at a point.
return img.setMulti(img.select(['B2'], ['B2_at_point']).reduceRegion({
reducer: ee.Reducer.mean(),
geometry: pointOfInterest,
}));
});
// Display the list of values, just for the example (this is not used further).
print(images.reduceColumns(ee.Reducer.toList(), ['B2_at_point']).get('list'));
// Compute the median.
var median = ee.Number(
images.reduceColumns(ee.Reducer.median(), ['B2_at_point'])
.get('median'));
print(median);
// Find the image or images that had the median.
var exactlyEqualsMedian = images.filter(ee.Filter.equals('B2_at_point', median));
var equalsOrNextToMedian = ee.ImageCollection(ee.Algorithms.If(
exactlyEqualsMedian.first(), // Is exactlyEqualsMedian nonempty?
exactlyEqualsMedian, // Then return it.
images // Otherwise find the nearest 2 images.
.map(function (i) {
return i.set('median_distance', median.subtract(i.get('B2_at_point')).abs());
})
.limit(2, 'median_distance')));
print(equalsOrNextToMedian);
Map.setCenter(-115.08, 40.56, 9);
Map.addLayer(equalsOrNextToMedian, {bands: ['B4', 'B3', 'B2'], max: 0.4, gamma: 1.6});
https://code.earthengine.google.com/4e0d3d59535722f55425618e7defefff
(请注意,此处的计算没有科学价值;这只是在图像集合中寻找中位数的示例。)
请注意,我没有采用将输入填充到 median() 的方法。相反,我随后进行过滤以选择完全匹配的图像或两个最接近的匹配图像。这是因为我希望它比尝试预先设置填充更有效(因为它需要额外查询集合以找出它有多大)。您当然可以在生成的 2 图像集合中选择适合您需要的任何图像 — 如果您不关心哪个图像,只需使用 equalsOrNextToMedian.first()
.