1

I'm trying to filter clouds in Sentinel-2 through GEE in a ROI but I get the same number of images clipping or not clipping the geometry.

How can I calculate the cloud coverage in a ROI and filter an ImageCollection depending on the cloud coverage?

This is the code I was working on:

var s2Sr = ee.ImageCollection('COPERNICUS/S2_SR');
var s2Clouds = ee.ImageCollection('COPERNICUS/S2_CLOUD_PROBABILITY');

var START_DATE = ee.Date('2018-03-30');
var END_DATE = ee.Date('2018-06-10');
var MAX_CLOUD_PROBABILITY = 20;
var region = AOI
Map.centerObject(region, 12);

function maskClouds(img) {
  var clouds = ee.Image(img.get('cloud_mask')).select('probability');
  var isNotCloud = clouds.lt(MAX_CLOUD_PROBABILITY);
  return img.updateMask(isNotCloud);
}


// The masks for the 10m bands sometimes do not exclude bad data at
// scene edges, so we apply masks from the 20m and 60m bands as well.
// Example asset that needs this operation:
// COPERNICUS/S2_CLOUD_PROBABILITY/20190301T000239_20190301T000238_T55GDP
function maskEdges(s2_img) {
  return s2_img.updateMask(
      s2_img.select('B8A').mask().updateMask(s2_img.select('B9').mask()));
}

// Filter input collections by desired data range and region.
var criteria = ee.Filter.and(
    ee.Filter.bounds(region), ee.Filter.date(START_DATE, END_DATE));
s2Sr = s2Sr.filter(criteria).map(maskEdges);
s2Clouds = s2Clouds.filter(criteria);

// Join S2 SR with cloud probability dataset to add cloud mask.
var s2SrWithCloudMask = ee.Join.saveFirst('cloud_mask').apply({
  primary: s2Sr,
  secondary: s2Clouds,
  condition:
      ee.Filter.equals({leftField: 'system:index', rightField: 'system:index'})
});

var s2CloudMasked = ee.ImageCollection(
  s2SrWithCloudMask).map(maskClouds).median();
var rgbVis = {min: 0, max: 3000, bands: ['B4', 'B3', 'B2']};

Map.addLayer(s2CloudMasked,
  rgbVis,
  'S2 SR masked at ' + MAX_CLOUD_PROBABILITY + '%', true);

print(s2SrWithCloudMask);

1 Answer 1

1

I've been struggling with this too. What worked for me was doing the filtering on the s2SrWithCloudMask before you turn it into an imageCollection. I also made a filter function to map to the collection, so you can then filter by that. Code below. Keep everything you have, just add these bits in.

This was converted from Python to JavaScript, there may be syntax errors.

function filterClouds(img) {
    var clouds = ee.Image(img.get('cloud_mask')).select('probability');

    var cloudiness = clouds.reduceRegion({
        reducer: 'mean',
        geometry: AOI,
        scale: 10,
    }).get('probability'); //get keeps the property server-sided, instead of doing getInfo() like you would in other cases.

    return img.set({'CLOUD_COVERAGE_AOI': cloudiness});
}

// Join S2 SR with cloud probability dataset to add cloud mask.
var s2SrWithCloudMask = ee.Join.saveFirst('cloud_mask').apply({
    primary: s2Sr,
    secondary: s2Clouds,
    condition:
        ee.Filter.equals({leftField: 'system:index', rightField: 'system:index'})
});

s2SrWithCloudMask = s2SrWithCloudMask.map(filterClouds);
s2SrWithCloudMask = s2SrWithCloudMask.filterMetadata('CLOUD_COVERAGE_AOI', 'less_than', MAX_CLOUD_PROBABILITY)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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