2

I am trying to calculate EVI for a Sentinel 2 Level 2A image collection. I have applied the Sentinel cloud mask provided by GEE but am not sure I am applying EVI correctly because my range is not between -1 and 1 and when I try to visualize it is a single color.

This is what I see when I inspect the bands using the Console.

"EVI", double, EPSG:32616, 10980x10980 px

My question is if I am already dividing by the scale factor (10000) in the cloud mask do I still need to divide each band by 10000 in my EVI equation? Any insight into why the EVI I'm producing is not usable?

//Area of interest
  var roi = /* color: #d63000 */ee.Geometry.Polygon(
        [[[-89.88191416015627, 14.139636998051515],
          [-90.32686044921877, 13.737115730837438],
          [-89.87916757812502, 13.526248029454758],
          [-89.60176279296877, 13.982444096452182]]]);
/**
 * Function to mask clouds using the Sentinel-2 QA band
 * @param {ee.Image} image Sentinel-2 image
 * @return {ee.Image} cloud masked Sentinel-2 image
 */
function maskS2clouds(image) {
  var qa = image.select('QA60');

          
  // Bits 10 and 11 are clouds and cirrus, respectively.
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;
  // 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).divide(10000);
}

// Add EVI using an expression.
var addEVI=function(image){
var EVI = image.expression(
      '2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
      'NIR' : image.select('B8').divide(10000),
      'RED' : image.select('B4').divide(10000),
      'BLUE': image.select('B2').divide(10000)}).rename('EVI');
      return image.addBands(EVI);
};

var Nov19= ee.ImageCollection('COPERNICUS/S2_SR')
            .filterBounds(roi)
                  .filterDate('2019-11-01', '2019-11-30')
                  // Pre-filter to get less cloudy granules.
                  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',10))
                  .map(addEVI)
                  .map(maskS2clouds);
                  
                  
print(Nov19);

Map.addLayer(Nov19.select('EVI').median().clip(roi), {min:-1,max:1,palette:['red', 'green']}, 'EVI Nov19');
4
  • Your range is practically in the middle between -1 and 1 (zero) because you are dividing by 100,000,000. @korndog was right. Map with maskS2clouds onto your image collection before addEVI and don't divide into image.expression by 10000. With these recommendations your script will work perfectly.
    – xunilk
    Feb 20, 2021 at 3:52
  • Thank you! I will try that! Apr 1, 2021 at 19:10
  • Could I ask what you're putting this code into (i.e. python, Visual Studio, etc.)?
    – Beck
    Sep 3, 2021 at 15:13
  • I'm putting this code into Google Earth Engine. Sep 5, 2021 at 13:44

2 Answers 2

1

Because you map maskS2clouds onto your image collection after addEVI, you end up dividing your EVI band by 10000. Decide whether you want to re-scale your images earlier in your script or on a case-by-case basis (e.g. when calculating EVI).

0

Late to reply but I have blog post regarding this question and have described in details about EVI calculation in GEE. https://kaflekrishna.com.np/blog-detail/enhanced-vegetation-index-evi-sentinel-2-image-google-earth-engine/

In short, I have used function to compute EVI as:

def getEVI(image):
    # Compute the EVI using an expression.
    EVI = image.expression(
        '2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
            'NIR': image.select('B8').divide(10000),
            'RED': image.select('B4').divide(10000),
            'BLUE': image.select('B2').divide(10000)
        }).rename("EVI")

    image = image.addBands(EVI)

    return(image)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.