EDS 220 Fall 2022

NDVI Calculations with Landsat Data

Now that we've gotten somewhat familiar with using Google Earth Engine to do basic data visualizations, in this notebook we'll apply our tools to a new spectral index. As we did in class, we'll be working with the Landsat data catalog:

https://developers.google.com/earth-engine/datasets/catalog/landsat

The ultimate goal here is to read in Landsat multispectral data and use it to calculate a standard 'index' product used to indicate vegetation health: the Normalized Difference Vegetation Index (NDVI). Here are some example maps showing the surface reflectance sensed by Landsat (left) and the NDVI index calculated from those data (right):

image.png

The NDVI is calculated using the red (R) and near-infrared (NIR) bands, combined using the following formula:

$NDVI = \frac{(NIR - R)}{(NIR + R)}$

A more detailed description is available on the USGS Landsat website:

https://www.usgs.gov/core-science-systems/nli/landsat/landsat-normalized-difference-vegetation-index?qt-science_support_page_related_con=0#qt-science_support_page_related_con

Configure Your Environment

As we did in the class example (Landsat_colormaps_GEE), we'll need to set up our Jupyter environment and make sure that GEE is authenticated and initialized. The packages we need are ee, geemap, and pandas:

We'll work with Landsat 8 data from the Tier 1-Real Time dataset, to ensure high quality and long temporal coverage. As a reminder, the differences between the Landsat data 'tiers' is:

A full description of the Landsat data organizational structure in GEE can be found at: https://developers.google.com/earth-engine/guides/landsat

The below example reads in data from:

Note that the data we will be reading in here are top-of-atmosphere (TOA) reflectances, estimates of the radiation reflected at the top of Earth's atmosphere.

The first thing we'll do is to read in the Tier 1-Real Time dataset, using the ee.ImageCollection function:

Calculate NDVI

Technically, arithmetic operations in GEE must be performed on individual Image objects - so if you try to add or subtract ImageCollections directly, an error will result (you can try it if you want, and see what I mean!). There are two ways around this:

  1. Filter the ImageCollection down to a single Image, then perform calculations
  2. Use the map() function to perform calculations on each image within the collection

Below are examples using both these methods:

Option 1: Filter ImageCollection down to a single Image

We can follow the procedure used in class to create a temporal average of Landsat imagery over a given time period; this will be a single image, which we can use to compute NDVI.

For NDVI calculation, we want bands 4 (red) and 5 (NIR), which are called "B4" and "B5" respectively.

In order to perform the actual calculation, we need to use the subtract, add, and divide attributes:

Now we define new visualization parameters appropriate for NDVI. Since this index is based on a difference between bands, it now has a range between -1 and 1, rather than the values one uses when generating a true-color image.

One other neat thing you can do when specifying visualization parameters is assign different color palettes: here I'm specifying a color bar that ranges from blue (negative NDVI) to green (positive NDVI), with white in the middle.

Then all there is to do is to create a basemap and add the NDVI layer to it!

Option 2: Mapping NDVI across an ImageCollection

The next example uses map() so that we can get familiar with how it works. First, we define a function which takes an image as input: it then calculates NDVI and adds it to the image as a new band called "NDVI". Here is the function:

Now we can use this function in the call to "map" and apply it to the entire collection of Santa Barbara images:

We'll need to specify new visualization parameters, which tell GEE to plot the new NDVI band in the appropriate color range:

Finally, we use the same approach as above to plot the NDVI layer over the basemap:

If you look at the above map, you'll see that rather than the single (temporal average) image that Option 1 generates, Option 2 is actually plotting many images superimposed on one another!