3

I am trying to create and map an image collection (not image or mosaic if that is even possible), where QA60 defines the Cloud-mask. I have written the code below - however, it seems the Jan2016 images do not correspond the cloud mask, even though the pixel inspector shows the same image time stamp for all layers. Hence, "NoCLouds" layer contains many pixels with clouds and has many other without masked. Maybe my mask is wrong?

var Jan2016 = ee.ImageCollection('COPERNICUS/S2')
      .filterBounds(NSW)
      .filterDate('2016-01-01', '2016-01-30');

var trueColor = {bands: ['B4', 'B3', 'B2'], min: 0, max: 3000};
var falseColor= {bands: ['B8', 'B3', 'B4'], min: 0, max: 3000};
//Define the CLoud layer (here: QA60 is MSI2's quality mask)
var Clouds = {bands: ['QA60']};

//Add the cloud mask as layer; PROBLEM: SEEMS QA60 is taken from different images every time..
//Clouds is just a band, do i need to specify the threshold?
Map.addLayer(Jan2016, Clouds, "CloudsJan16");

// Mask clouds
var noclouds = Jan2016.map(function(img) {
              var mask = 
img.select(['QA60']).neq(11); 
//.neq(xx) doesn't seem to make a difference
                   return img.updateMask(mask);

});

//Add the layer/imagery to the map with variable, display type, and name  
Map.addLayer(noclouds, trueColor, "NoClouds");
Map.addLayer(Jan2016, falseColor, "Jan2016false");
  • You should define NSW to make this example reproducible – aldo_tapia Dec 27 '17 at 11:16
3

Here is an example of cloud masking for Sentinel-2:

var s2 = ee.ImageCollection("COPERNICUS/S2");
var pt = ee.Geometry.Point([-122.41653442382812, 37.77180027337861]);

var cloudyImage = ee.Image('COPERNICUS/S2/20151207T190417_20151207T221905_T10SEG');
Map.centerObject(cloudyImage, 10);
Map.addLayer(cloudyImage, {bands: ['B4', 'B3', 'B2'], max: 2000}, 'cloudy image');

// Bits 10 and 11 are clouds and cirrus, respectively.
var cloudBitMask = ee.Number(2).pow(10).int();
var cirrusBitMask = ee.Number(2).pow(11).int();

var qa = cloudyImage.select('QA60');

Map.addLayer(qa.bitwiseAnd(cloudBitMask).neq(0), {}, 'clouds');
Map.addLayer(qa.bitwiseAnd(cirrusBitMask).neq(0), {}, 'cirrus');

function maskS2clouds(image) {
  var qa = image.select('QA60');
  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(
             qa.bitwiseAnd(cirrusBitMask).eq(0));
  return image.updateMask(mask);
}

var cloudMasked = s2.filterBounds(pt).map(maskS2clouds);

var median = cloudMasked.median();
Map.addLayer(median, {bands: ['B4', 'B3', 'B2'], max: 2000}, 'median');
  • 1
    Nick, there are some accuracy problems when using QA60 band to mask clouds. Do you suggest some alternative when computing cloud and shadows actually on S2 data? Maybe the Gennadii shadow code, or something like it? – Etore Marcari Jr. Dec 4 '18 at 12:12

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.