1

I am trying to calculate the red-edgeNDVI ((NIR – red edge)/(NIR + red edge)) of an Image.Collection in Google Earth Engine. There is a built in function for NDVI but not for red-edge NDVI. The code I have is below but I get the error message "image.NIR is undefined". I'm sure this is a simple syntax issue related to the function but I've tried everything I could think of and I just can't get it to work.

Can you tell me what I'm missing?

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

  // Load Sentinel-2 TOA reflectance data.
  var S2 = ee.ImageCollection('COPERNICUS/S2')
                  .filterDate('2017-06-01', '2017-09-30')
                  // Pre-filter to get less cloudy granules.
                  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
                  //Select required bands only
                  .select('B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B8A', 'QA60')
                  //Apply cloud mask
                  .map(maskS2clouds);

//Create band variables
var redEdge = S2.select('B5');
var NIR = S2.select('B8');

//Function to calculate redEdgeNDVI
var add_reNDVI = function(image){
  var redEdgeNDVI = image.NIR.subtract(redEdge).divide(NIR.add(redEdge)).rename('reNDVI');
    return image.addBands(reNDVI);
};
5

In your code, S2 is an ImageCollection, so when you "create band variables" you're just getting ImageCollections in which every image inside has only the selected band, which is useful. As you well commented, add_reNDVI is a function that will take every image in the collection and calculate reNDVI. So you have to map that function over the collection to get what you want.

// Load Sentinel-2 TOA reflectance data.
var S2 = ee.ImageCollection('COPERNICUS/S2')
                .filterDate('2017-06-01', '2017-09-30')
                // Pre-filter to get less cloudy granules.
                .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
                //Select required bands only
                .select('B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B8A', 'QA60')
                //Apply cloud mask
                .map(maskS2clouds);

//Function to calculate redEdgeNDVI
var add_reNDVI = function(image){
  //Create band variables
  var redEdge = image.select('B5');
  var NIR = image.select('B8');
  var redEdgeNDVI = NIR.subtract(redEdge).divide(NIR.add(redEdge)).rename('reNDVI');
    return image.addBands(redEdgeNDVI);
};
var s2_reNDVI = S2.map(add_reNDVI)
Map.centerObject(s2_reNDVI.first())
Map.addLayer(s2_reNDVI.first())

I guess you'll need to filter by bounds at some point, that is why I just took the first image out of the collection to check if it's working

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.