TransWikia.com

How can filter low cloud coverange in a region with Sentinel-2 L2A in GEE?

Geographic Information Systems Asked by Mar Roca on March 1, 2021

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);

One Answer

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)

Correct answer by Blue101black on March 1, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP