Google Earth Engine : Remove value from S2 NDVI image collection (5 and 95 percentile)

1.6k views Asked by At

I'm calculating statistics over image collection of NDVI on Sentinel2.

I get an image collection of S2_SR over of defined period of time and over a specific area, and then removing clouds.

        var S2 = ee.ImageCollection('COPERNICUS/S2_SR')
    
    //filter start and end date
    .filterDate('2019-03-01', '2020-03-31')
    
    //filter according to drawn boundary
    .filterBounds(ROI);
    
    var palettes = require('users/gena/packages:palettes');
    var palette = palettes.colorbrewer.Spectral[8];
    
    // Function to mask cloud from built-in quality band
    // information on cloud
    var computeQAbits = function(image, start, end, newName) {
        var pattern = 0;
    
        for (var i=start; i<=end; i++) {
            pattern += Math.pow(2, i);
        }
    
        return image.select([0], [newName]).bitwiseAnd(pattern).rightShift(start);
    };
    
    var sentinel2 = function(image) {
    
      var cloud_mask = image.select("QA60");
      var opaque = computeQAbits(cloud_mask, 10, 10, "opaque");
      var cirrus = computeQAbits(cloud_mask, 11, 11, "cirrus");
      var mask = opaque.or(cirrus);
    
      return image.updateMask(mask.not());
    }

Then I've calculated NDVI and NDWI for each date;

       var addNDVI = function(image) {
          var ndvi = image.normalizedDifference(['B5', 'B4']).multiply(10000).rename('NDVI');
        
          return image.addBands(ndvi);
        };
        
        var addNDWI = function(image) {
          var ndwi = image.normalizedDifference(['B3', 'B8']).multiply(10000).rename('NDWI');
          return image.addBands(ndwi);
        };
        // Add NDVI band to image collection
        var S2 = S2.map(addNDVI);
        var S2 = S2.map(addNDWI);
        var NDVI = S2.select(['NDVI']);
        var NDWI = S2.select(['NDWI']);
var S2 = S2.map(addNDVI);
var S2 = S2.map(addNDWI);
var NDVI = S2.select(['NDVI']);
var NDWI = S2.select(['NDWI']);

var P_95_NDVI = NDVI.reduce(ee.Reducer.percentile([95]));
var P_05_NDVI = NDVI.reduce(ee.Reducer.percentile([5]));

NDVI_P = NDVI.updateMask(NDVI.gt(P_05_NDVI).and(NDVI.lt(P_95_NDVI)));


var P_95_NDWI = NDWI.reduce(ee.Reducer.percentile([95]));
var P_05_NDWI = NDWI.reduce(ee.Reducer.percentile([5]));

NDWI_P = NDWI.updateMask(NDWI.gt(P_05_NDWI).and(NDWI.lt(P_95_NDWI)));
    

Then, I've computed my statistics, min, max, mean, median, sd. So from my ouput, I get, the min, max, mean, median, sd, of my NDVI and NDWI indices for eavry single pixel over my period of time.

 // Add indices bands to image collection
    
    var reducer1 = ee.Reducer.mean();
    
    var reducers = reducer1.combine({reducer2: ee.Reducer.median(), sharedInputs: true})
                           .combine({reducer2: ee.Reducer.max(), sharedInputs: true})
                           .combine({reducer2: ee.Reducer.min(), sharedInputs: true})
                           .combine({reducer2: ee.Reducer.stdDev(), sharedInputs: true});
    
    
    var results_NDVI = NDVI.reduce(reducers);
    var results_NDWI = NDWI.reduce(reducers);
    
    var results = results_NDVI.addBands(results_NDWI);
    
    var results_integer = results.int16();

However, I've noticed some remaining outliers values due to clouds. I would like to, before calculatemy statistics, removing values of NDVI and NDWI lower than the 5th percentile and upper than the 95th. To make sure that my stats are not biaised by outliers values.

Thank you

1

There are 1 answers

5
MadeleineN On BEST ANSWER

I would suggest calculating the 95th and 5th percentile using a reducer (i.e. ee.Reducer.percentile([95])) and then masking the image:

results = results.updateMask(results.gt(bottomPercentile).and(results.lt(topPercentile)));