Springe direkt zu Inhalt

NDVI - Sentinel-2

As mentioned in the previous chapter, the NDVI is the normalized difference of the red and the infrared band, calculated as NDVI = (NIR-RED) / (NIR+RED).

Let us try to apply this to a Sentinel 2 Scene. As we want to learn how to deal with big data, we will have a look at the NDVI of July 2020 for the whole country of Lebanon.

Preparing the data

We already learned how to access any available data on the GEEs Data Catalog, so let us prepare the imagery. Keep in mind that in order to calculate the NDVI in the GEE, we will need to work with Images, not ImageCollections. In this example, we will access the whole Sentinel-2 Level-2A collection for July 2020 and aggregate its median to a single Rasterlayer.

// Compute Normalized Difference Vegetation Index over S2-L2 product.
// NDVI = (NIR - RED) / (NIR + RED), where
// RED is B4, 664.5 nm
// NIR is B8, 835.1 nm

//Step 1: Access your boundary-defining geometry
var extent_lebanon = ee.FeatureCollection("FAO/GAUL/2015/level0")
                  .filter(ee.Filter.eq('ADM0_NAME', 'Lebanon')); //filter for entry that equals the UN country name 'Lebanon'

//Step 2: Access the Sentinel-2 Level-2A data and filter it for all the the images of the year 2020 that lie within the geometries boundaries. Keep only the relevant bands and filter for cloud coverage.
var s2a = ee.ImageCollection('COPERNICUS/S2_SR')
                  .filterDate('2020-07-01', '2020-07-31')
                  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 10));

//Print your ImageCollection to your console tab to inspect it
print(s2a, 'Image Collection Lebanon July 2020');

//Step 3: Create a single Image by reducing by Median and clip it to the extent of the geometry
var s2a_median = s2a.median()

//Print your Image to your console tab to inspect it
print(s2a_median, 'Median reduced Image Lebanon July 2020');

//Add your Image as a map layer
var visParams = {'min': 400,'max': [4000,3000,3000],   'bands':'B8,B4,B3'};
Map.addLayer(s2a_median, visParams, 'S2 Lebanon July 2020 Median');

Calculating the NDVI

The GEE offers multiple ways to calculate the NDVI from your image.

Here, we will have a look at three different approaches, that will all lead to the same result.

The first approach uses simple band operations integrated in the GEE to calculate band maths, the second approach uses the function .expression to write a mathematical formula and the third approach uses the function .normalizedDifference, which calculates the Normalized Difference for two input variables

Depending on your interests and research, you might find specific approaches superior to others.

//Step 4: Calculate the NDVI manually: NDVI = (B8 - B4) / (B8 + B4)
//this can be achieved using either simple band operations, .expression or .normalizedDifference
//Variant 1: Simple band operations
var nir = s2a_median.select('B8');
var red = s2a_median.select('B4');
var ndvi = nir.subtract(red).divide(nir.add(red)).rename('NDVI');
print(ndvi, 'NDVI Lebanon July 2020 V1')

// Display the result.
var ndviParams = {min: -1, max: 1, palette: ['blue', 'white', 'green']};
Map.addLayer(ndvi, ndviParams, 'NDVI Lebanon July 2020 V1');

//Variant 2: .expression
var ndvi_2 = s2a_median.expression(
                      '(NIR-RED)/(NIR+RED)', {
                        'NIR' : s2a_median.select('B8'),
                        'RED' : s2a_median.select('B4')

print(ndvi_2, 'NDVI Lebanon July 2020 V2')

//Display the result
Map.addLayer(ndvi_2, ndviParams , 'NDVI Lebanon July 2020 V2');

//Variant 3: .normalizedDifference(NIR, RED)
//find out how .normalizedDifference works by checking Docs -> ee.Image -> normalizedDifference
var ndvi_3 = s2a_median.normalizedDifference(['B8', 'B4'])
print(ndvi_3, 'NDVI Lebanon July 2020 V3');

//You can also create more complex colour palettes via hex strings.
//this color combination is taken from the Examples script Image -> Normalized Difference:
var palette = ['FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718',
               '74A901', '66A000', '529400', '3E8601', '207401', '056201',
               '004C00', '023B01', '012E01', '011D01', '011301'];
//Please keep in mind that for this palette, you should set your minimum visible value to 0, as it s designed for this purpose.
//This is due to it being a gradient from brown to green tones, with a heavy focus on the green side. If we would set min: -1, NDVI = 0 would already be displayed in a dark green tone.
//You can recognize this by checking the palette-section of your layer information for ndvi_3.

// Display the input image and the NDVI derived from it.
Map.addLayer(ndvi_3, {min: 0, max: 1, palette: palette}, 'NDVI Lebanon July 2020 V3')

Now that we have calculated and displayed the NDVI in three different variants, we can use the Inspector and click on various places in the map panel to see that the pixel values are always identical!
Most of the time, the most convenient way to calculate the NDVI is by using the normalizedDifference as it is really easy and quick to execute.