0

I need to filter the LANDSAT/LC8_SR image collection using an assessment of total cloud cover in the entire scene of each image. i.e. each image in the collection is "in" or "out" based on a threshold of cloud cover for the whole image. In the TOA collections I can easily do this using 'CLOUD_COVER' from the metadata, but the surface reflectance collection does not have this metadata attribute. I have tried using reduceRegion to find the sum of cfmask=4 over the 'cfmask' layer, but this returns a value and I don't know where to put that value so I can use it to filter the images.

// Load a Landsat 8 ImageCollection for a single path-row.
var collection = ee.ImageCollection('LANDSAT/LC8_SR')
    .filter(ee.Filter.eq('wrs_path', 23))
    .filter(ee.Filter.eq('wrs_row', 38));
// use wrs feature collection to establish region to assess cloud cover
var fc = ee.FeatureCollection('ft:1_RZgjlcqixp-L9hyS6NYGqLaKOlnhSC35AB5M5Ll')
    .filter(ee.Filter.and(
    ee.Filter.eq('PATH', 23),
    ee.Filter.eq('ROW', 38)));
0

This would be the way to go:

var fc = ee.FeatureCollection('ft:1_RZgjlcqixp-L9hyS6NYGqLaKOlnhSC35AB5M5Ll')
.filter(ee.Filter.and(
ee.Filter.eq('PATH', 23),
ee.Filter.eq('ROW', 38)));

var geom = ee.Feature(fc.first()).geometry()

// Load a Landsat 8 ImageCollection for a single path-row.
var collection = ee.ImageCollection('LANDSAT/LC8_SR')
    .filter(ee.Filter.eq('wrs_path', 23))
    .filter(ee.Filter.eq('wrs_row', 38));

// Compute CLOUD_COVER and add it as an image property
var mapper = function(img) {
  var cfmask = img.select("cfmask")
  var clouds = cfmask.eq(4)
  var per1 = clouds.reduceRegion({
             reducer: ee.Reducer.mean(), 
             geometry: geom, 
             scale: 30,
             maxPixels: 1e13}).get("cfmask")
  var per = ee.Number(per1).multiply(100)
  return img.set("CLOUD_COVER", per)
}

// Print size before filtering
print("before", collection.size())

// Apply function
var col = collection.map(mapper)

// Filter by 10% or less
var filtered = col.filterMetadata("CLOUD_COVER","less_than", 10)

// Print after filtering
print("after", filtered.size())

// Filter by 90% or more
var withclouds = col.filterMetadata("CLOUD_COVER","greater_than", 90)

// Add layer to see that it works
Map.addLayer(ee.Image(filtered.first()),{bands:["B5","B6","B4"],min:0, max:5000}, "less than 10")
Map.addLayer(ee.Image(withclouds.first()),{bands:["B5","B6","B4"],min:0, max:5000}, "greater than 90")

Map.centerObject(geom)

But, I think it'd be better if you use the image footprint instead:

// Compute CLOUD_COVER and add it as an image property
var mapper = function(img) {
  var cfmask = img.select("cfmask")
  var clouds = cfmask.eq(4)
  var per1 = clouds.reduceRegion({
             reducer: ee.Reducer.mean(), 
             geometry: img.geometry(), 
             scale: 30,
             maxPixels: 1e13}).get("cfmask")
  var per = ee.Number(per1).multiply(100)
  return img.set("CLOUD_COVER", per)
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.