google-earth-engine – How to Filter Out Values of a Property in a Feature Collection

google-earth-enginegoogle-earth-engine-javascript-api

I am writing a script to find where imagery from Landsat 7 and Landsat 8 overlaps within two days of each other within a certain aoi. The output for this is a feature collection with a property called 'overlap_pixel_count'. I would like to filter the output collection to only include 'overlap_pixel_count' values that are greater than 1,000,000.

I am having difficulty accomplishing this with the current data structure. Here is what I have thus far:

var pixel_overlap = l7.map(function(i){
  //get the L7 img 
  var l7_id = ee.String(i.id())
  // get the L7 image geometry to use for filtering
    var l7_geom = i.geometry()
    // get the L7 image date to use for filtering
    var l7_date = i.date()
  // pick a L7 band and get its mask
  var l7_mask = i.select(['SR_B4']).mask()
  // filter the L8 collection
  var l8collection = l8.filterBounds(l7_geom)
                       .filterDate(l7_date.advance(-2,'day'), l7_date.advance(2,'day'))
                       
  // Make a feature collection of intersecting geometries                    
  var count_feat = ee.FeatureCollection(l8collection.map(function(i){
                  //same steps as Landsat 7
                  var l8_id = ee.String(i.id())
                  var l8_geom = i.geometry()
                    var l8_date = i.date()
                  var l8_mask = i.select(['SR_B5']).mask()
                    
                  // Now find the geometric intersection of the two images
                  var intersect = l7_geom.intersection(l8_geom, 30)     
                  // multiply the l7 and l8 masks together (product > 0 means theres overlap)
                  var masks_added = l7_mask.multiply(l8_mask).gt(0)
                  // Count the number of overlapping pixels
                  var overlap_count = masks_added.reduceRegion({reducer: ee.Reducer.sum(), 
                                                                geometry: intersect, 
                                                                scale: 30, 
                                                                bestEffort: true, 
                                                                maxPixels: 1e9, 
                                                                tileScale: 4});                      
      
                  //set the feature propeties to output
                  return ee.Feature(intersect).set({'ID_L7': l7_id, 'DATE_L7': l7_date, 
                                                    'ID_L8': l8_id, 'DATE_L8': l8_date,
                                                    'overlap_pixel_count': overlap_count})                 
  }))

// Return the feature collections 
  return count_feat
}).flatten() // flatten feature collections into one collection

Here is the sharable GEE link: https://code.earthengine.google.com/fc99c39501b877f619e4231054bc998d

Best Answer

The problem is that the value over which you want to do the filter ('overlap_pixel_count') is contained inside an ee.Dictionary object (reduceRegion always returns a Dictionary). Thus, you cannot directly use a filter over a property that is a Dictionary (as you would normally do with numbers, dates or strings). The trick here is getting the desired value out of the Dictionary so it can be added as a numeric property. In addition, I am not completely sure if you need to rename both bands (coming from l7 and l8) with the same name ('band'), but if in some cases the property obtained by the reduceRegion comes out from the l7_mask and others from the l8_mask, it might be a good idea to homogeneize the band names. Later, you can use that name to extract that key out of the Dictionary.

Here's the only changes I made to your script:

var l7_mask = i.select(['SR_B4']).mask().rename('band')

var l8_mask = i.select(['SR_B5']).mask().rename('band')

// at the end of the function
  return ee.Feature(intersect).set({
    'ID_L7': l7_id, 
    'DATE_L7': l7_date,
    'ID_L8': l8_id, 
    'DATE_L8': l8_date,
    'overlap_pixel_count': overlap_count.getNumber('band') 
})

// Then you can filter normally
var filt = pixel_overlap.filter(ee.Filter.gte('overlap_pixel_count', 1000000))
print(filt.limit(50))
Related Question