0

I am trying to calculate the mean pixel values of three Sentinel-2 images, all of which I have cloud masked separately. They all have small areas of cloud but in different places. I assumed that when I calculated the mean, the cloud masked pixels having no-data values would simply be excluded from the analysis and in cloudy patches I would get a mean of the other two images instead. However this is not the case and my final image is masked wherever there was cloud in any of the three images.

My goal is therefore to combine all three of these images, masked for cloud, to produce a cloud-free image of average pixel values.

I considered that calculating the mean directly (instead of adding separately and dividing by 3) might solve this, however since my images are separate assets and not a filtered image collection I do not know how to do this.

function maskS2clouds(collection) {
  var qa = collection.select('QA60');
  var cloudBitMask = 1 <<10;
  var cirrusBitMask = 1 <<11;

  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
  .and(qa.bitwiseAnd(cirrusBitMask).eq(0));
  
  return collection.updateMask(mask).divide(10000);
}

//image collection is filtered
var dataset = ee.ImageCollection("COPERNICUS/S2")
  .filterBounds(geometry)
  .filterDate('2017-06-19', '2017-06-20')
  .map(maskS2clouds);
  
var dataset2 = ee.ImageCollection("COPERNICUS/S2")
  .filterBounds(geometry)
  .filterDate('2017-08-23', '2017-08-24')
  .map(maskS2clouds);
  
var dataset3 = ee.ImageCollection("COPERNICUS/S2")
  .filterBounds(geometry)
  .filterDate('2017-07-19', '2017-07-20')
  .map(maskS2clouds);

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

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

3

The problem with the approach you tried is that image1.add(image2), a math operation on exactly two images, is only defined/unmasked where both input images are unmasked. Also notice that even if it produced pixels wherever either image is unpacked, you'd end up with the sum of 1, 2, or 3 images, always divided by 3, which is not what you want because it's a sum scaled by a constant, instead of the mean of however many images there are at that pixel.

Instead, you should put your three images in a collection, then apply a mean reduction to the collection. Reductions understand that the number of inputs can vary per-pixel.

// You had this...
var june = image1.mosaic();
var aug = image2.mosaic();
var july = image3.mosaic();

// Now take the mean.
var avg = ee.ImageCollection([june, aug, july]).mean();

Map.addLayer(avg);

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.