0

I want to compute NDVI for all images in Sentinel2 (less than 20% cloud cover) in an image collection comprising 5 years. Thereafter, I want to batch export the output as a binary TIF file where NDVI <0.5 is ignored. Once I can do this, I will do the rest of the analysis in QGIS through a model that is ready to go.

Here's what I've done so far in bits and pieces to the best of my abilities.

//add study area
var studyarea = ee.FeatureCollection('users/XXX/XXXXX/studyarea');

Map.addLayer(studyarea, {color: 'red'}, 'study area');
Map.centerObject(studyarea);

//
/**
 * 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 the Sentinel-2 ImageCollection and bound to study area
var collectionSentinel2 = ee.ImageCollection('COPERNICUS/S2_SR')
                  .filterDate('2015-07-01', '2020-10-15')
                  // Pre-filter to get less cloudy granules.
                  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',20))
                  .filterBounds(studyarea)
                  .map(maskS2clouds)
                  .map(function(image){return image.clip(studyarea)});

//Mapping a Function over a Collection
var addNDVI = function(image) {
  var ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI');
  return image.addBands(ndvi);
};


//Applying NDVI to all images in the collection
var withNDVI = collectionSentinel2.map(addNDVI);

print (withNDVI);

So far so good apparently, but this is adding NDVI as a separate band, not sure if that's a good approach. Thereafter, here's the next bit of the code where I am thresholding NDVI images. I'm unable to use this as a function as with computing NDVI earlier.

//thresholding to extract healthy vegetation
//Identify all pixels below threshold and set them equal to 1. All other pixels set to 0
var ndvi_thrshld = ndvi.gt(0.50);  

//Remove all pixels equal to 0
ndvi_thrshld = ndvi_thrshld.updateMask(ndvi_thrshld); 

//Clip to study area        
var ndvi_thrshld_clipped = ndvi_thrshld.clip(studyarea);

To export to Drive, I am using the following code snippet which works great for a few images but not sure how to iterate it over the image collection.

// Export the image, specifying scale and region.
Export.image.toDrive({
  image: ndvi_thrshld_clipped ,
  description: 'NDVI',
  scale: 10,
  region: studyarea,
  maxPixels: 18095956539
});
0

I think I figured out the answer myself. This seems to do the trick, sharing the entire code with anyone interested.

var batch = require('users/fitoprincipe/geetools:batch');

//add study area
var studyarea = ee.FeatureCollection('users/XXX/XXXXX/studyarea');

Map.addLayer(studyarea, {color: 'red'}, 'study area');
Map.centerObject(studyarea);

//
/**
 * 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 the Sentinel-2 ImageCollection and bound to study area
var collectionSentinel2 = ee.ImageCollection('COPERNICUS/S2_SR')
                  .filterDate('2015-07-01', '2020-10-15')
                  // Pre-filter to get less cloudy granules.
                  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',20))
                  .filterBounds(studyarea)
                  .map(maskS2clouds)
                  .map(function(image){return image.clip(studyarea)});

//Mapping a Function NDVI over a Collection
var addNDVI = function(image) {
  var ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI');
  
  //Thresholding
  //If NDVI less or equal to 0.5 => 0 else 1
  var thres = ndvi.gte(0.5).rename('thres');
  
  return image.addBands(ndvi).addBands(thres);
};


//Applying NDVI to all images in the collection
var withNDVI = collectionSentinel2.map(addNDVI);

print (withNDVI);

//Export only the thres band
//SYNTAX - imageCollection.select([old bands], [new band names])
var bandSubset = withNDVI.select(['thres'], ['thres'])

batch.Download.ImageCollection.toDrive(bandSubset, 'NEWFOLDER', 
                {scale: 10, 
                 region: studyarea.getInfo()["coordinates"], 
                 type: 'float'}) 

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.