1

I have a shapefile which contains many crop plots, around 2000. I need to calculate NDVI (normalized difference vegetation index) and then calculate statistics for each one of the 2000 plots separately.

Is there any short way to make Google Earth Engine calculate the statistics for each plot without saving each plot as a shapefile and uploading it to the system?

This is the code I have now:


my end goal is to create in the end one table which will have different statistics calculations (which I still haven't added) for each plot, ordered by the dates of the images from the Image Collection. 

/**
 * 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)
  .copyProperties(image, ['system:time_start']);
}

// Map the function over one year of data and take the median.
// Load Sentinel-2 TOA reflectance data.
var dataset = ee.ImageCollection('COPERNICUS/S2')
                  .filterDate('2015-06-23', '2019-07-02')
                  // Pre-filter to get less cloudy granules.
                  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
                  .select('B2','B3','B4','B8','QA60')
                  .filterBounds(geometry)
                  .map(maskS2clouds);

var rgbVis = {
  min: 0.0,
  max: 0.3,
  bands: ['B4', 'B3', 'B2'],
};

var clippedCol=dataset.map(function(im){ 
   return im.clip(geometry);
});

//test if clipping the image collection worked
Map.centerObject(geometry);
Map.addLayer(clippedCol.median(), rgbVis, 'RGB');

// Get the number of images.
var count = dataset.size();
print('Count: ',count);
// print(clippedCol);//here I get the error messege "collection query aborted after accumulation over 5000 elements
// print(dataset,'dataset');//the same error here


//function to calculate NDVI
var addNDVI = function(image) {
  var ndvi = image.normalizedDifference(['B8', 'B4'])
  .rename('NDVI')
  .copyProperties(image,['system:time_start']);
  return image.addBands(ndvi);

};

//NDVI to the clipped image collection
var withNDVI = clippedCol.map(addNDVI).select('NDVI');



// // Test the addNDVI function on a single image.
// var ndvi1 = withNDVI.select('NDVI').mean();


var colorizedVis = {
  min: 0.0,
  max: 1.0,
  palette: [
    'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
    '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
    '012E01', '011D01', '011301'
  ],
};

// // Test the addNDVI function on a single image.

// var listOfImages =(withNDVI.toList(withNDVI.size()));
// var firstImage = (listOfImages.get(0));
// var secondImage =(listOfImages.get(1));


Map.centerObject(geometry);
print('NDVI Images',withNDVI.select('NDVI'));
// Map.addLayer(firstImage,colorizedVis,'test1');
// Map.addLayer(secondImage,colorizedVis,'test2');


//Long-Term Time Series

print(ui.Chart.image.series(withNDVI, geometry, ee.Reducer.mean(), 30));


0

The function you are looking for is reduceRegions(). It is important to note that this function runs on image, not image collection. So you have to first reduce your S2 image collection to an image. Since you have a stack of images at every pixels, calling median() on the collection will give you an image where every pixel is the median value of all the images at that pixel.

Once you have an image, you can run reduceRegions() with the shapefile as the collection.

As you mentioned you want multiple stats, you can combine reducers as per your requirement.

Below is the relevant code snippet, assuming your uploaded shapefile is referred by table variable.

var meanNDVIImage = withNDVI.median();

var tableWithStats = meanNDVIImage.reduceRegions({
  collection: table,
  reducer: ee.Reducer.mean().combine({
  reducer2: ee.Reducer.minMax(),
  sharedInputs: true
  }),
  scale: 1000
});

If your region is large, the computation may timeout in interactive mode. Export the resulting tableWithStats to get the results.

  • Thank you, I tried this code but it was very heavy and I couldn't even export it. I'm also not sure that it function as I want, because I need the statistic for each plot while all the 2000 plots belong to one shapfile – Reut Jul 14 at 14:14

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.