Google Earth Engine – Extracting the Highest 100 Pixel Values from a Single-Band Image

google-earth-engine

I'm trying to extract the brightest 100 pixels of a single band image. More specifically,

  1. sort the pixel values of a single band image,

  2. extract the top 100 pixel values,

  3. put them into a list for further use.

Below is my solution based on a for-loop, but it's too slow and even failed when i > 100. Code link:
https://code.earthengine.google.com/?scriptPath=users%2Fghongwei0309%2FGEE_ACO%3ABrightest_1000_Test

var dataset = ee.ImageCollection('COPERNICUS/S2')
                  .filterDate('2018-04-05', '2018-06-30')
                  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 10));

var img = dataset.first().select('B3');
var ftpt = img.geometry();  //image footprint

var lst = ee.List([]);
for (var i=0; i<30; i++){
  var maxVal = img.reduceRegion({
    reducer: ee.Reducer.max(),
    geometry: ftpt,
    scale: 10,
    crs: 'EPSG: 4326',
    bestEffort: true
  }).getNumber('B3');
  img = img.updateMask(img.lt(maxVal));
  maxVal = img.reduceRegion({
    reducer: ee.Reducer.max(),
    geometry: ftpt,
    scale: 10,
    crs: 'EPSG: 4326',
    bestEffort: true
  }).getNumber('B3')
  lst = lst.add(maxVal);
};
print(lst.length());

How can I do this?

Best Answer

I didn't get your example to work because you didn't share your assets/scripts.

But here is something that might work for you. Although there might be a better solution, you could apply a reduceregion(), get the pixel values and return the +/- 100 highest values:

var reduce = image.select('B3').reduceRegion({
    reducer: ee.Reducer.frequencyHistogram(),
    geometry: geometry2,
    scale: 30,
    crs: 'EPSG: 4326',
    bestEffort: true
  })
  
print(reduce, 'reduce')

// # accumulate values
var values = ee.Dictionary(reduce.values().get(0)).toArray().accum(0)
print(values, 'values')


var max = ee.Number(values.project([0]).get([-1])).subtract(100).round()
print(max, 'max')

var valuesToMask = values.project([0]).round().gt(max);
print(valuesToMask, 'valuesToMask')

// Pixel values - returned as string
var filterList = ee.List(ee.Dictionary(reduce.get('B3')).keys())
print(filterList)//.multiply(valuesToMask))

// make it a number
var toNumbers =  filterList.map(function(q){
  var number = ee.Number.parse(q)
  
  return ee.Number(number)
})

// Now mask the original pixel values
var filteredValues = ee.Array(toNumbers).mask(valuesToMask)
print(filteredValues, 'filteredValues')

https://code.earthengine.google.com/008badec53cad63afd62dd859614b02d

Related Question