【问题标题】:Selecting an image from an ee.ImageCollection based on the median value of an attribute根据属性的中值从 ee.ImageCollection 中选择图像
【发布时间】:2020-03-18 13:27:24
【问题描述】:

我正在为一个图像集合赋予一个值,我想选择具有该图像集合中值的图像。

目前,我正在通过创建具有值客户端的图像列表来执行此操作,将列表填充为奇数,然后使用中值获取我想要的 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)

'''

所以本质上对于元数据中具有值的图像集合,我只想选择具有 medain 值的图像,而不使用任何客户端 getInfo()

【问题讨论】:

    标签: python median google-earth-engine


    【解决方案1】:

    您可以使用ImageCollection.reduceColumns 算法来获取集合属性的中值。然后您可以使用过滤器来选择具有该值的元素。

    我已经准备了一个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

    (请注意,此处进行的计算没有科学价值;这只是在图像集中找到中值的一个示例。)

    请注意,我没有采用将输入填充到中值()的方法。相反,我随后过滤以选择完全匹配的图像或两个最接近的匹配。这是因为我希望它比尝试预先设置填充更有效(因为它需要额外的时间查询集合以找出它有多大)。您当然可以在生成的 2 张图像集合中选择适合您需要的任何图像 - 如果您不在乎,请选择 equalsOrNextToMedian.first()

    【讨论】:

    • 很好的答案谢谢,很好的例子,我有另一个查询,在检查我使用的集合大小时if collection.size().getInfo() != 0 我试过if collection.size() != ee.Number(0) 似乎缺少一些东西。
    • AAah 刚刚意识到我可以从你的例子中解决这个问题,我认为,'ee.Algorithms.If
    • 这就是我最终实现if的方式if ts_collection.size().neq(ee.Number(0)):
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    相关资源
    最近更新 更多