Ga naar inhoud

Spectrale indices

Spectral indices zijn combinaties van twee of meerdere spectrale banden die gebruikt worden om bepaalde kenmerken extra in de verf te zetten of ze te herberekenen naar een relatieve schaal. Ze worden berekend aan de hand van bandbewerkingen, die op verschillende manieren in Google Earth Engine geïmplementeerd kunnen worden.

1. NDVI

De Normalized Difference Vegetation Index (NDVI) is wellicht de bekendste vegetatie-index en wordt berekend als:

\[NDVI = { NIR - RED \over NIR + RED}.\]

Waarbij:
NIR = reflectie in het nabij-infrarode gebied van het spectrum (oftewel Near-Infrared)
RED = reflectie in het rode gebied van het spectrum

De resulterende index krijgt waarden tussen -1 en 1.

De NDVI is een maat voor de dichtheid en gezondheid van vegetatie op basis van verschillen in lichtreflectie tussen het rode en nabij-infrarode spectrum. Vegetatie absorbeert veel zichtbaar licht voor fotosynthese (lage reflectie in het rode deel van het spectrum) en weerkaatst bijna al het nabij-infrarode licht (hoge NIR-reflectiewaarde), wat zorgt voor een hogere NDVI-waarde. Hoe dichter of gezonder de vegetatie, hoe hoger de NDVI.

Andere objecten, zoals water of stedelijke oppervlakken, absorberen NIR-licht juist goed, waardoor de NDVI-waarde lager of zelfs negatief uitvalt.

In Earth Engine kan de NDVI (en andere indices) op verschillende manieren berekend worden. We starten met de meest conventionele aanpak. Vooraleer we hiermee starten, dienen we een wolkenvrij Sentinel-2 beeld te bemachtigen

Stap 1 – Importeren en visualiseren van Sentinel-2 beeld
Maak een puntgeometrie aan ergens ter hoogte van de Gentse haven (Evergem).


Maak vervolgens een Sentinel-2 beeld aan, met volgende eigenschappen:

  • Gebruikmaken van de Sentinel-2 Surface Reflectance (Harmonized) collectie
  • Voeg de CloudScore+ laag toe (zie vorig practicum)
    • Filter op basis van:
      • Geometrie Haven Gent
      • Periode: Lente 2025
      • Maximale wolkbedekking van 20%
  • Cloudmask toegepast
  • Mediane reducer voor overblijvende collectie

Stap 2 – Clippen tot de grenzen van Gent
We beschikken over de grenzen van Gent als polygoon (vector). Voeg deze toe aan je script. De vector bevat alle Belgische gemeenten, waaruit we Gent op basis van de Name-eigenschap filteren.

var Gent = ee.FeatureCollection('projects/teledetectie-2025-474312/assets/P2-FeatureExtraction/Belgium_municipalities')
              .filter(ee.Filter.eq('Name', 'Gent'));

Gebruik vervolgens .clip(Gent) om het geselecteerde Sentinel-2-beeld te begrenzen tot het grondgebied van Gent. Visualiseer als een Valse KleurenComposiet (R= NIR, G = B4, B= B3)

Oplossing
// Inladen van 'shape'
var Gent = ee.FeatureCollection('projects/teledetectie-2025-474312/assets/P2-FeatureExtraction/Belgium_municipalities').filter(ee.Filter.eq('Name','Gent'))

//1. Importeren van de Sentinel-2 collectie.
var S2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED");

// Importeren CloudPlus Collectie
var csPlus = ee.ImageCollection('GOOGLE/CLOUD_SCORE_PLUS/V1/S2_HARMONIZED');

// Aanmaken van treshold + maskfunctie + Herschalingsfunctie
var CLEAR_THRESHOLD = 0.6
var applyCloudMask = function(img){
    return img.updateMask(img.select('cs').gte(CLEAR_THRESHOLD))  
            .multiply(0.0001) //   
            .copyProperties(img, ["system:time_start"]);  
}


//Filteren op basis van datum (lente 2025) + beeld met laagste wolkenpercentage selecteren
var S2_Gent_Lente25 = S2
    .linkCollection(csPlus, ['cs']) // Toevoegen CloudScore aan collectie
    .filterBounds(Gent) // Filteren obv Geometrie Gent (of punt)
    .filterDate('2025-03-20', '2025-06-30')
    .map(applyCloudMask)

print('Gent Lente 25: ',S2_Gent_Lente25)

//Clippen naar Grenzen Gent
var S2_Gent_Lente25 = S2_Gent_Lente25.clip(Gent)

//Visualisatieparameters (of handmatig instellen)
var S2_ValseKleuren = {
  min: 0,
  max: 0.5, 
  bands: ['B8', 'B4', 'B3'],
  };

//Toevoegen aan Map
Map.addLayer(S2_Gent_Lente25,S2_ValseKleuren,'Valse Kleuren lente 2025')
  • Stap 3 - Berekenen van de NDVI
    Een eerste methode om een NDVI aan te maken is via de ingebouwde .normalizedDifference() functie. Ga na welke Sentinel-2 banden je nodig hebt om de ndvi te berekenen. (Maak eventueel gebruik van de ‘Docs’-tab.)

    //2. Aanmaken NDVI via NormalDifference()-functie. Vul de '?' in
    var ndvi = S2_Gent_Lente25.normalizedDifference(['?', '?']).rename('NDVI');
    Map.addLayer(ndvi,{},'ndvi_lente_2025') //Zonder visualisatieparametes
    


  • Een ndvi wordt meestal afgebeeld met een kleurenpallet, zoals onderstaand voorbeeld:

    // Met visualisatie
    var ndviParams = {min: -1, max: 1, palette: ['red','yellow','darkgreen']};
    Map.addLayer(ndvi, ndviParams, 'ndvi_2025_vis');
    


Oefening: Connecteer de ndvi-waarden met de gepaste landbedekkingsklasse.
NDVI waarde Landbedekking (Lente)
Negatief (< 0) stenen, bodem, schaduw
Kleine waarden (0.1 or less) Grasland/lage vegetatie
Moderate values (0.2 to 0.3) Dense vegetatie
Large values (0.6 to 1) wolken, water, sneeuw
Antwoord
NDVI waarde Landbedekking (Lente)
Negative values (< 0) water / sneeuw / Wolken
Small values (0.1 or less) stenen, naakte grond, schaduw
Moderate values (0.2 to 0.5) Verspreide vegetatie, ongezond
Large values (0.6 to 1) Dense vegetatie

2. Bandbewerkingen

Bandbewerkingen kunnen gebruikt worden om een nieuw beeld af te leiden uit bestaande banden. Het berekenen van indices zoals de NDVI is daar een treffend voorbeeld van. Andere toepassingen zijn ratio’s of het verschil tussen twee beelden op verschillende tijdstippen om veranderingen visueel te benadrukken.

Er zijn twee manieren om in Earth Engine bandbewerkingen uit te voeren:

Optie 1 - Bewerkingen via operatoren

De basisoperators maken gebruik van 2 inputs: ofwel 2 beelden, ofwel 1 beeld en 1 constante. De bewerkingen worden steeds per pixel en per band uitgevoerd. Voorbeeld van operatoren zijn add(), subtract() en divide().

//NDVI berekenen aan de hand van bandwerkingen met operatoren
// Lange uitwerking: noodzakelijke banden eerst selecteren en onderbrengen in een nieuwe variabele
var nir = S2_Gent_Lente25.select('B8');
var red = S2_Gent_Lente25.select('B4');
var ndvi2 = nir.subtract(red).divide(nir.add(red)).rename('NDVI');
Map.addLayer(ndvi2, ndviParams, 'ndvi via operatoren');

Het resultaat is logischerwijs identiek als de voorgaande ndvi-berekening.

Optie 2 - Bewerkingen via expressies

Voor complexere wiskundige bewerkingen is de .expression()-functie handiger. Binnen deze expressie geef je de variabelen expliciet aan, waardoor de formule overzichtelijker en makkelijker te coderen is. De expressie aanvaardt ook constanten. Variabelen die binnen de expressie gebruikt worden, moeten steeds worden gedefinieerd.

//NDVI aan de hand van een expressie
  var ndvi3 = S2_Gent_Lente25.expression(
      '(NIR - RED)/(NIR + RED)', {
        'NIR': S2_Gent_Lente25.select('B8'),
        'RED': S2_Gent_Lente25.select('B4')
  });

Ook hier is het resultaat hetzelfde als de vorige ndvi-berekeningen.

Gebruikte operators binnen expressies

Onderstaande tabel geeft de binnen de expressies gehanteerde operators weer (bron: Earth Engine guide)


3. Andere indices

Naast de NDVI bestaan er nog een heleboel andere indices, elk met een eigen toepassing.

De Normalized Difference Water Index (NDWI)

De NDWI is een index ontwikkeld door McFeeters (1996), met als doel op oppervlaktewater te monitoren. Doorgaans kunnen de NDWI waarden als volgt worden gedefinieerd:
* 0.2 – 1: Wateroppervlakte,
* 0.0 – 0,2: overstroomde gebieden, zeer natte gronden,
* -0,3 – 0.0: drogere gronden,
* -1 – -0.3: Droge gronden, stedelijk gebied

De NDWI wordt berekend als:

\[NDWI = { GREEN - NIR \over GREEN + NIR}.\]

4. Opdrachten

Oef 1 - NDWI

Test de NDWI index uit op je Sentinel-beeld van de Gentse Haven en omstreken. Bekijk de verschillen. Kijk hiervoor zeker naar naburige natuurgebieden en waterplassen.

Oef 2 - NDVI per seizoen

In deze oefening maak je een visualisatie van de NDVI per seizoen ter hoogte van Durbuy.

  1. Maak een wolkenvrije beeldencollectie aan (gebruik een maximaal aan wolkbedekking van 30%) aan van de regio Durbuy. Maak gebruik van de Cloudmask-procedure, op basis van de S2_CloudProbability collectie, zoals hier beschreven: https://users.ugent.be/~jfeyen/P1/P1-Cloud_masking.html#2-cloud-mask-van-sentinel-2-data

  2. Maak een functie aan om de NDVI te berekenen. Laat de functie dan los op de Imagecollectie via .map().

  3. Maak aan de hand van de collectie 3 beelden aan met een median()-reducer, binnen volgende periodes:

    A. Jan- 15 maart (Winter)
    B. 15 maart - Mei (Lente)
    C. Juli-Augustus (Zomer)

  4. Visualiseer voor elk seizoen een Normale Kleurencomposiet en een NDVI-beeld. Gebruik onderstaande visualisatieparameters bij het plotten:

//Visualisatieparameters instellen
var NormaleKleuren = {
  min: 0,
  max: 0.3,
  bands: ['B4', 'B3', 'B2'],
};

var ndviParams = {
  min: 0,
  max: 1,
  bands: ['NDVI'],
  palette: ['red','yellow','darkgreen']
};
Oplossing NDVI per seizoen

Via deze link: https://code.earthengine.google.com/74d3638b42126d36323f7f4c5b4d48f8?noload=true