0

I am using the Earth Engine Python API and attempting to extract date and NDVI values from an image collection. I have added an NDVI band to each image in the collection but I am having trouble figuring out how to extract the actual NDVI value from each band in order to produce a dataframe of an NDVI time series.

I am creating an NDVI band with the code below

    nir = img.select('B5')
    red = img.select('B4')
    ndvi = nir.subtract(red).divide(nir.add(red)).rename('NDVI')
    print('NDVI value:', ndvi.select('NDVI').getInfo())

and I am receiving info from the NDVI band in the form of

NDVI value: {'type': 'Image', 'bands': [{'id': 'NDVI', 'data_type': {'type': 'PixelType', 'precision': 'float'}, 'dimensions': [492, 492], 'origin': [2368, 3104], 'crs': 'EPSG:32612', 'crs_transform': [30, 0, 175185, 0, -30, 5063115]}]}

The documentation on accessing computed NDVI values is limited and I have been scanning tutorials and other exchange posts for ee api related solutions but have found nothing. Any help would be greatly appreciated!

1

You currently have an image which has an NDVI value for each pixel in the original image. In order to get a single number, you need to reduce the image — to take the mean, median, maximum, minimum, or other such operation on pixels in the image, within a region of interest. Here is the documentation on reduceRegion, which is the way to do this.

Since you have an image collection and want a table, you also need to map over the image collection. Whenever you want a number or other value for each image in a collection, the way you do that is by adding a property to each image, using set(), or by producing new features that have only the data you want.

This example I wrote is in JavaScript since I wrote it in the Earth Engine Code Editor, but the differences with Python are fairly small so I hope you can follow along.

var meanNDVICollection = imgs.map(function (img) {
  // Your code.
  var nir = img.select('B5');
  var red = img.select('B4');
  var ndviImage = nir.subtract(red).divide(nir.add(red)).rename('NDVI');

  // Compute the mean of NDVI over the 'region'
  var ndviValue = ndviImage.reduceRegion({
    geometry: region,
    reducer: ee.Reducer.mean(),
  }).get('NDVI');  // result of reduceRegion is always a dictionary, so get the element we want

  // Add the value as a property to each image in the collection.
  // return img.set('NDVI', ndviValue);

  // Or, create a new feature with only the properties we want.
  return ee.Feature(null, {
    // Adding property we computed.
    'NDVI': ndviValue
  }).copyProperties(img, [
    // Picking properties from the original image.
    'system:time_start',
    'SUN_ELEVATION'
  ])
});

// Export, or you can use any other method for getting a table out of Earth Engine.
Export.table.toDrive({
  collection: meanNDVICollection
});

https://code.earthengine.google.com/580f2f06c9978caf43eac42b5dd0ff44

(Disclaimer: I do not have training in the scientific and statistical aspects of remote sensing. The choices of mean and scale: 20 in this script are for demonstration of Earth Engine only and should not be assumed to produce scientifically valid results.)

1
  • Thank you so much! This code was incredibly helpful – Ian Dershem May 5 '20 at 17:18
0

Kevin Reid provided a very helpful solution to my issue. Here is the python code that I ended up using

def meanNDVICollection (img):
  nir = img.select('B5');
  red = img.select('B4');
  ndviImage = nir.subtract(red).divide(nir.add(red)).rename('NDVI');

  # Compute the mean of NDVI over the 'region'
  ndviValue = ndviImage.reduceRegion(**{
    'geometry': hatCreekPolygon.getInfo(),
    'reducer': ee.Reducer.mean(),
  }).get('NDVI');  # result of reduceRegion is always a dictionary, so get the element we want

  newFeature = ee.Feature(None, {
      # Adding computed NDVI value
      'NDVI': ndviValue
  }).copyProperties(img, [
      # Picking properties from original image
      'system:time_start',
      'SUN_ELEVATION'
  ])

  return newFeature

This returned a Feature Collection which I was then able to loop through and access the date and ndvi values with get('NDVI') and get('system:time_start')

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.