1

I have the following code (utilizing a script by Rodrigo Principe that implements Hollstein et al's 2016 Sentinel 2 cloud mask), which overall works quite well.

    var mask_all = function(image) {
      var hollstein_mask = cld.hollstein_S2(['shadow', 'cloud', 'cirrus'])(image)
      return hollstein_mask
    };

However, it leaves some white borders around clouds and some black borders around shadows. I'd like to get rid of these with a buffer. But no matter how long I bang away at it, I can't manage to convert the existing mask to a binary image, buffer that, and then use that to update the mask. Here is the best I can do, which doesn't crash but also does not appear to do anything at all:

    var buffer = function(image){
        var buffer_bad = image.select('cloud').neq(1)
                          .and(image.select('shadow').neq(1))
                          .and(image.select('cirrus').neq(1))
                          .focal_max({radius: 100, units: 'meters'})
        return image.updateMask(buffer_bad)
    }

What I'm trying to make happen there is to take the existing mask, nibble way at the edges by 100 meters, and then update the mask.

Here's the full snippet of relevant code for context:

var cld = require('users/fitoprincipe/geetools:cloud_masks')

var mask_all = function(image) {
  var hollstein_mask = cld.hollstein_S2(['shadow', 'cloud', 'cirrus'])(image)
  return hollstein_mask
};

var buffer = function(image){
    var buffer_bad = image.select('cloud').neq(1)
                      .and(image.select('shadow').neq(1))
                      .and(image.select('cirrus').neq(1))
                      .focal_max({radius: 100, units: 'meters'})
    return image.updateMask(buffer_bad)
}

var allclear = ee.ImageCollection('COPERNICUS/S2')
  // Pre-filter to get less cloudy granules over the ROI.
                  .filter(ee.Filter.calendarRange(1, 2, 'month'))
                  .filterBounds(ROI)
                  .map(mask_all)
                  .map(buffer)
                  .median();
1

While mask_all() seems to add cloud, shadow, cirrus bands, these get masked together with the rest of the image. So, you don't know which pixels actually did contain cloud/shadow/cirrus, which you rely on when buffering. If you don't want to make any changes to how mask_all() works, the best you can do is probably to buffer your mask. This will of course buffer not only the bad pixels, but also decrease the image footprint, which is less than ideal.

var buffer = function (image) {
  var mask = image.mask().reduce(ee.Reducer.min())
  var buffer_bad = mask
    .focal_min({radius: 100, units: 'meters'})
  return image.updateMask(buffer_bad)
}

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.