I am filtering a Sentinel-2 collection with the goal of producing an average over a period of three months. I have selected three images within the collection with which to do this. They all have some cloud cover but in different parts of the image. So far, I have defined a cloud mask and mapped this over the three images before averaging them, but this produces an average like in the attached image which has all the cloud from all three images masked out where there is a cloud in just one image. Eventually, I will be running vegetation indices on them and making different layers with other years, so I don't want large areas of the average masked out due to cloud cover. As it will impact these differences.

current result from code

My question is this: How can I create an average of these three images whilst excluding cloudy patches from the resulting layer. I.e., if one patch of the cloud is present in one image, how can I exclude that so the average layer is just an average of the other two images where the cloud was not present?

Apologies if that sounds convoluted. I basically want to end up with a resulting layer which does not have any cloud masked out and instead takes the average from the two images which do not have a cloud in any particular area.

This is my code so far:

//define the cloud mask layer
function maskS2clouds(collection) {
  var qa = collection.select('QA60');
  var cloudBitMask = 1 <<10;
  var cirrusBitMask = 1 <<11;
//layer called mask = the cloudy bits
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
//'image' is a layer with the mask applied to it  
  return collection.updateMask(mask).divide(10000);

//image collection is filtered
var dataset = ee.ImageCollection("COPERNICUS/S2")
  .filterDate('2017-06-19', '2017-06-20')
var dataset2 = ee.ImageCollection("COPERNICUS/S2")
  .filterDate('2017-08-23', '2017-08-24')
var dataset3 = ee.ImageCollection("COPERNICUS/S2")
  .filterDate('2017-07-19', '2017-07-20')
//image with mask applied
var image1 = dataset.map(function(image) { return image.clip(geometry); });
var image2 = dataset2.map(function(image) { return image.clip(geometry); });
var image3 = dataset3.map(function(image) { return image.clip(geometry); });

Map.addLayer(image1, RGB, "June");
Map.addLayer(image2, RGB, "August");
Map.addLayer(image3,RGB, "July");

var june = image1.mosaic();
var aug = image2.mosaic();
var july = image3.mosaic();
var junaug = june.add(aug);
var augjuly = junaug.add(july);
var avg = augjuly.divide(3);

1 Answer 1


Im not sure for GEE , try this https://www.researchgate.net/post/atmospheric_correction_in_sentinel-2_images

From doing it off GEE: see https://labo.obs-mip.fr/multitemp/theias-sentinel-2-l3a-monthly-cloud-free-syntheses/

Maybe one can implement the L3A Weighted Averaging Method in GEE: For each pixel, and each band, WASP almost simply averages the cloud free surface reflectances gathered during a synthesis period of 45 days. For instance, to produce the synthesis of July 15th, it will average all the cloud free L2A observations gathered between June 26th and August 5th. And this is done every month.

In details (as already explained in this post):

  1. A directional correction is made to homogenise the surface reflectances as if they had been taken from the vertical, avoiding differences where the Sentinel-2 orbits overlap.

  2. Then weights are computed:

    • Pixels close to a detected cloud or shadow have a lower weight
    • Pixels with a lower aerosol optical thickness have a higher

A greater weight is given to dates close to the synthesis date.

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.