In diesem Modul beschäftigst Du dich mit den Grundlagen der Fernerkundung. Dabei werden Satellitendaten genutzt, um zu verstehen, dass die Welt nicht immer so aussieht, wie Du sie kennst.
Autor:in
Zugehörigkeit
IZG
Ruhr-Universität Bochum
Veröffentlichungsdatum
14. September 2025
1 Pakete importieren
Hinweis
Bitte führe den Code mit den Importbefehlen in der folgenden Zelle aus, um die Pakete zu importieren. Dies muss jedes Mal als Erstes getan werden, nachdem der Kernel neugestartet wurde.
import ee # importieren der Google Earth Engine Schnittstelle (API) import geemap # importieren des geemap Paketes für die Analysetoolsimport os # importieren des Pakets für den Export von Daten auf die lokale Festplatte
/Users/soeren/PycharmProjects/cdec/wenv/lib/python3.12/site-packages/geemap/conversion.py:23: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
import pkg_resources
2 Interaktive Karten erstellen
Es wird wieder damit gestartet, eine interaktive Karte mit Koordinaten und Zoom-Faktor zu konfigurieren. Dieser Karte wird ein Name gegeben (hier: my_map), und anschließend wird die Karte über den Befehl my_map (also einfach ihren Namen) aufgerufen.
my_map = geemap.Map(center=(52.5525865,13.4535448), zoom=17) # neue Map konfigurieren mit Koordinate und Zoomstufemy_map # in der Zeile zuvor konfigurierte Map aufrufen
*** Earth Engine *** Share your feedback by taking our Annual Developer Satisfaction Survey: https://google.qualtrics.com/jfe/form/SV_7TDKVSyKvBdmMqW?ref=4i2o6
Hinweis
Wenn Du Google Maps besuchst, kannst Du mit der rechten Maustaste in der Karte auf einen Bereich Deiner Wahl klicken. Anschließend werden die Koordinaten in dem Kontextmenü ausgewählt, um die angezeigten Koordinaten des Ortes im Zwischenpeicher (Copy and Paste) abzulegen.
Aufgabe: Suche Dir einen Ort aus (Wohnort, Schule, Stadion, Park, etc.), ersetze die Koordinaten im Code oben aus dem Zwischenspeicher durch Deine eigenen (Strg+V), passe gegebenenfalls den Zoom-Faktor an, und starte den Code danach neu (Strg+Enter). Hat das funktioniert?
Es können auch mehrere unterschiedliche Karten erstellt werden, indem eine weitere Karte konfiguriert und zum Beispiel my_map2 genannt wird.
Der Befehl my_map in der obigen Zelle führt immer zur Darstellung der spezifisch in der ersten Zeile konfigurierten Karte mit dem gleichen Namen. Solltest Du im weiteren Verlauf dieses Notebooks nicht immer zu dieser einen Map hochscrollen wollen, kann diese einfach über den Befehl my_map in einer eigenen Zeile erneut dargestellt werden.
3 Basemaps hinzufügen
my_map # erneutes Aufrufen der oben bereits konfigurierten Karte 'Map'
In GEE verfügen Maps über Hintergrundkarten (Basemaps) mit meist globaler Ausdehnung. Standardmäßig wird die Karte der OpenStreetMap-Community genutzt. Es stehen jedoch viele weitere Optionen zur Verfügung.
Mit den folgenden Befehlen können zuerst alle verfügbaren Basemaps abgefragt und anschließend beliebig viele als weitere Layer der Karte hinzugefügt werden:
# Abfrage aller möglichen Basemapsbasemaps = geemap.basemaps # die Variable 'basemaps' beinhaltet nun eine Liste aller Basemaps aus dem geemap-Paket# mit dieser Funktionsschleife wird jede Basemap in einer eigenen Zeile ausgegeben, sonst könnte man das kaum lesen.for element in basemaps: # "Gehe die Liste 'basemaps' durch und mache mit jedem Listeneintrag (element) folgendes:print(element) # Gib den Namen des jeweiligen Listeneintrags aus."
Aufgabe: Wähle eine Basemap Deiner Wahl, z. B. ‘Esri.WorldImagery’, schreibe deren Name in Klammern und Anführungszeichen in die nächste Codezelle und führe sie aus.
Hinweis
Als Beispiel wird zusätzlich das topographische Kartenwerk der OpenStreetMap-Community hinzugefügt. Das Ergebnis dieses Codes kann entweder weiter oben in Deiner interaktiven Karte angeschaut werden, oder über den Befehl my_map wird eine erneute Instanz dieser Karte direkt unter der Code-Zelle angezeigt. Dies kann von Dir einfach in einer neuen Zeile ganz unten hinzugefügt werden.
my_map.add_basemap('OpenTopoMap')my_map.add_basemap('') # wenn die Klammer leer bleibt, wird eine Liste verfügbarer Basemaps angezeigt# Map.add_basemap('') # Backup
Über den Schraubenschlüssel oben rechts im Kartenfenster und einen Klick auf ‘Layers’ können die einzelnen Layer interaktiv ein- und ausgeschaltet sowie mit einer beliebigen Transparenz versehen werden.
4 Inspector-Tool benutzen
Zunächst wird ein digitales Geländemodell als weiterer Datensatz aus dem GEE Data Catalog in die Map geladen. Geländemodelle beschreiben die Oberfläche der Erde, wobei jedes Pixel die Höhe des entsprechenden Ortes angibt. Eine genauere Betrachtung der Geländemodelle erfolgt in Modul 3.
# Digitales Geländemodell SRTM (https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003)dgm = ee.Image('USGS/SRTMGL1_003')# Visualisierungsparameter für DEM definieren (min-max ist der Wertebereich der Höhe, Palette legt den Farbverlauf fest)vis_params = {'min': 0,'max': 250,'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],}# Beide neuen Layer der Map hinzufügen my_map.addLayer(dgm, # Angabe des Datensatzes, der hinzugefügt werden soll vis_params, # Visualisierungsparameter definieren (s.o.)'SRTM DEM', # Name, den der Layer in unserer Map haben sollTrue, # Layer ist aktiv und wird angezeigt (!= False)0.9) # Die 0.9 gibt dem DEM-Layer direkt eine 10%ige Transparenzmy_map
Über den Schraubenschlüssel oben rechts im Kartenfenster wird über das (i) der Inspektor erreicht. Wenn er aktiviert ist, kann durch einen Klick der Wert aller getroffenen Pixel innerhalb der Maske ausgegeben werden.
Aufgabe: Finde heraus, auf welcher Höhe sich der Rathausplatz Deiner Heimatstadt befindet. Und wie hoch ist laut Geländemodell der Teufelsberg? Schreibe Deine Antwort in die nächste, leere Zelle.
Basemaps werden in erster Linie zur Orientierung genutzt. Für Analysen werden jedoch „richtige“ Datensätze benötigt. Dafür steht in GEE ein großer Katalog zur Verfügung, der ähnlich wie bei den Basemaps über den Aufruf des Namens eines Datensatzes verwendet werden kann.
Oben links wird über das Welt-Symbol eine Suchmaske geöffnet, mit der Adressen, Koordinaten und auch GEE-Datensätze abgefragt werden können.
Aufgabe: Nun werden die ersten Daten eingelesen. Hierfür gibst Du im Tab ‘data’ beispielsweise ‘sentinel 2’ oder ‘sentinel 5’ ein und bestätigst mit Enter. Über das Dropdown-Menü wählst Du aus der Liste entweder das Harmonized Sentinel-2 MSI: MultiSpectral Instrument, Level-2A oder Sentinel-5P NRTI NO2: Near Real-Time Nitrogen Dioxide aus. Danach klickst Du auf ‘import’, um den Code anzuzeigen. Dieser wird markiert und in die Zwischenablage kopiert (Copy-Paste). Anschließend kann der Code in die folgende Zelle eingefügt und ausgeführt werden.
Hinweis
Sollte eine Fehlermeldung auftreten, wird der Variablenname der Karte in der letzten Zeile überprüft (my_map). Er muss mit dem Namen der oben definierten Variable (my_map) übereinstimmen.
Wenn Du Dich für Harmonized Sentinel-2 MSI: MultiSpectral Instrument, Level-2A entscheidest, erstellt der Code ein Mosaik aus Sentinel-2-Bildern, das möglichst wolkenfrei (max. 20% Wolkenbedeckung) ist.
Damit das funktioniert, musst Du den Zeitraum der Bilder über die Datumsangaben in filterDate anpassen (idealerweise wählst Du die Vegetationsperiode von März bis September innerhalb eines Jahres). Das Einladen des Sentinel-5-Bildmaterials funktioniert analog.
Beim Sentinel-2-Vorschlag wird durch den Code ein zusammengesetztes, wolkenfreies Mosaik aus Bildern mit maximal 20 % Wolkenbedeckung generiert – dies sollte im Code so gut wie möglich nachvollzogen werden. Dafür muss der Zeitraum, aus dem die Bilder stammen, über die Datumsangaben hinter filterDate( angepasst werden (idealerweise wird die Vegetationsperiode von März bis September eines Jahres gewählt). Das Einladen des Sentinel-5-Bildmaterials funktioniert auf ähnliche Weise.
Soll der Raumausschnitt in der Karte nicht verändert werden, kann die Zeile am Ende mit m.setCenter() durch eine vorangestellte Raute (#) auskommentiert werden. Zeilen mit einer Raute werden nicht ausgeführt und eignen sich daher gut zum Kommentieren von Skripten.
Ändere die Datumsangaben (das Format beachten und beibehalten!) und vergleiche die Ergebnisse miteinander.
Hinweis
Das Laden der Bilddaten kann etwas dauern.
# Zelle zum Einfügen und Ausführen des Codes aus der Zwischenablage (Strg+V)
6 Untersuchung der Vegetation
6.1 GEE Datensätze hinzufügen, visualisieren und vergleichen
Für die Untersuchung von Klima und Klimawandel kann die Vegetation herangezogen werden, da sie unmittelbar auf Temperaturunterschiede und Trockenheit reagiert. Diese Reaktionen lassen sich auch in Satellitenbildern messen. Wenn Vegetation beobachtet werden soll, muss zuerst festgestellt werden, wo sie sich befindet. Dies scheint offensichtlich, doch nicht alles, was wie Vegetation aussieht, ist tatsächlich Vegetation. Dies wird am Beispiel einiger Sportplätze genauer betrachtet.
Es sind etliche Sportplätze sichtbar, die kräftig grün erscheinen, genauso wie die offensichtlichen Wälder drumherum. Beide würden ohne zu zögern als Vegetation bezeichnet werden. Doch einige der Plätze sind Kunstrasenplätze und somit keine echte Vegetation. Für eine sichere Erkennung werden jedoch mehr Daten benötigt.
Deshalb wird in der nächsten Zelle Sentinel-2-Bildmaterial aus dem Catalog in die Karte eingefügt. Der Code wurde erneut in die Zelle kopiert.
def maskS2clouds(image): qa = image.select('QA60')# Bits 10 and 11 are clouds and cirrus, respectively. cloudBitMask =1<<10 cirrusBitMask =1<<11# Both flags should be set to zero, indicating clear conditions. mask = qa.bitwiseAnd(cloudBitMask).eq(0) \ .And(qa.bitwiseAnd(cirrusBitMask).eq(0))return image.updateMask(mask).divide(10000)sentinel2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED') \.filterDate('2020-05-01', '2020-08-30') \.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',20)) \.map(maskS2clouds)RGBvisualization = {"min": 0.0,"max": 0.3,"bands": ['B4', 'B3', 'B2'],# Bildschirm-Kanal: [ Rot, Grün, Blau]}my_map.addLayer(sentinel2.mean(), RGBvisualization, 'RGB')
Auf den ersten Blick erscheinen die Daten schlechter. Dies liegt daran, dass ein Pixel nur noch einem Quadrat von 10m x 10m entspricht und dadurch die räumliche Auflösung sinkt. Dabei gehen Details verloren, doch die Fußballplätze bleiben weiterhin sichtbar.
Die Farben bleiben grundsätzlich unverändert, da es sich immer noch um ein Echtfarbenbild handelt. Dies entsteht folgendermaßen: Der Bildschirm mischt alle Farben aus Rot, Grün und Blau (RGB). Dem roten Kanal des Bildschirms wird das rote reflektierte Licht zugeordnet, das vom Satelliten aufgezeichnet wurde. Dem grünen Kanal wird das grüne Licht und dem blauen Kanal das blaue Licht zugeordnet. R = Rotes Licht (B4) G = Grünes Licht (B3) B = Blaues Licht (B2)
Bei jedem Foto, das auf einem Smartphone angezeigt wird, passiert dasselbe. Filter verändern dann die Kanalkombination, um mehr Kontrast oder lustige Farbeffekte zu erzeugen.
Satelliten wie Sentinel-2 nehmen mehr Licht auf, als das menschliche Auge sehen kann, z. B. infrarotes Licht (bekannt von Fernbedienungen oder Wärmelampen). Dieses Licht kann auf einen der drei Farbkanäle des Bildschirms gelegt und so sichtbar gemacht werden.
In der nächsten Codezeile wird das Satellitenbild erneut hinzugefügt, allerdings werden andere Bereiche des reflektierten Lichts ausgewählt. Der rote Kanal des Bildschirms stellt Infrarotlicht dar, der grüne Kanal rotes Licht und der blaue Kanal grünes Licht. Blaues Licht wird nicht dargestellt. Dadurch entsteht ein sogenanntes Falschfarbenbild. R = Infrarotes Licht (B8) G = Rotes Licht (B4) B = Grünes Licht (B3)
Die Kanalkombination wird in der nächsten Code-Zelle in eine Variable geschrieben.
Um die beiden Visualisierungen besser vergleichen zu können, wird jetzt eine Split-Map verwendet. Zunächst werden der rechte und der linke Teil der Karte definiert. Anschließend wird eine neue Karte erstellt, die in zwei Hälften geteilt wird.
In der Falschfarbendarstellung beginnt das Bild plötzlich rot zu leuchten. Dies ist die Vegetation, deren Farbstoff Chlorophyll infrarotes Licht stark reflektiert. Versiegelte Flächen oder solche mit nacktem Erdboden, wie Straßen oder abgeerntete Felder, reflektieren dieses Licht nicht und erscheinen weiterhin dunkel.
Aufgabe: Nutze den Slider in der Kartenmitte, um zwischen Echt- und Falschfarbenbild hin- und herzublenden, und beobachte, wie die Vegetation anfängt rot zu leuchten. Wie viele Kunstrasenplätze entdeckst Du im angezeigten Bildausschnitt? Beschreibe kurz, wie Du die Kunstrasenplätze identifiziert hast.
Aufgabe: Vertausche oben in der Variable CIRvisualization die Kanalkombination in der eckigen Klammer (z. B. B8 mit B3) und probiere weitere Farbkombinationen aus. Versuche, die Vegetation beispielsweise in Blau oder Deiner Lieblingsfarbe leuchten zu lassen. Für die Expert*innen: Versuche mal Violett.
Hinweis
Nach Änderungen müssen sowohl die Codezelle mit CIRvisualization als auch die Codezelle für die Split-Map erneut ausgeführt werden.
Als Nächstes wird die Beurteilung kontrolliert, indem eine Landbedeckungsklassifikation der europäischen Raumfahrtbehörde ESA geladen wird. Um die Farben besser zu verstehen, wird auch direkt eine Legende hinzugefügt.
# ESA World Coveresa = ee.Image('ESA/WorldCover/v200/2021')my_map.addLayer(esa, {}, 'ESA Land Cover')my_map.add_legend(builtin_legend='ESA_WorldCover')my_map
Die Naturrasenplätze werden gelb dargestellt, was der Klasse Grassland entspricht. Die Kunstrasenplätze werden der Klasse Built-up zugeordnet. Diese steht zwar eigentlich für Bebauung, umfasst jedoch nicht nur Gebäude, sondern auch generell versiegelte bzw. künstliche Materialien wie Asphalt, Beton, Dachziegel sowie künstliche Oberflächen wie Tartan oder Kunstrasen. Die Analyse hat also erfolgreich funktioniert!
Aufgabe: Schau Dich in Berlin um und identifiziere mit Deiner Splitmap weitere Kunstrasenplätze.
6.2 Waldbrände - Vitalität der Vegetation berechnen und Veränderungen erkennen
In der vorherigen Übung hast Du gelernt, dass Materialien die verschiedenen Wellenlängenbereiche bzw. Farben des Lichts unterschiedlich stark reflektieren. Vegetation reflektiert im sichtbaren Bereich eine Mischung, die für das Auge grün erscheint, und zusätzlich auch Infrarotlicht. Andere grün erscheinende Materialien wie Kunstrasen reflektieren jedoch kein Infrarotlicht.
Dieses Verhalten wird genutzt, um gesunde von geschwächter Vegetation zu unterscheiden. Dies liegt daran, dass fehlendes Chlorophyll das Reflektionsverhalten der Pflanze verändert. Die folgende Abbildung verdeutlicht dies.
Um herauszufinden, wie gesund die Vegetation in den Satellitenbildern ist, wird der NDVI verwendet. Der NDVI ist ein Index, der die Reflektion des roten Lichts mit der des infraroten Lichts vergleicht bzw. verrechnet. Durch eine relativ einfache mathematische Formel entstehen Werte zwischen -1 und +1. Je höher der NDVI eines Pixels ist, desto vitaler (gesünder) ist die Vegetation, die abgebildet wird – wenn überhaupt. Der Wert 0 bedeutet keine oder tote Vegetation, und der Wert 1 steht für extrem grüne und vitale Vegetation (weitere Infos). Diese Werte können dann mithilfe beliebiger Farbskalen dargestellt werden.
Wenn der NDVI zu verschiedenen Zeitpunkten berechnet und verglichen wird, können Veränderungen der Vegetation ziemlich zuverlässig untersucht werden. Es gibt viele sinnvolle Anwendungsfälle, wie beispielsweise Waldbrände oder Rodungen.
Im Jahr 2018 hat in Treuenbrietzen ein großer Waldbrand stattgefunden. Dies wird nun genauer betrachtet.
Zuerst wird der NDVI auf Basis des Sentinel-2-Satelliten vor dem Ereignis berechnet. Dafür werden alle Aufnahmen zwischen dem 1. Juni 2018 und dem 22. August 2018 verwendet.
# Funktion um die Wolken auszumaskierendef maskS2clouds(image): qa = image.select('QA60')# Bits 10 and 11 are clouds and cirrus, respectively. cloudBitMask =1<<10 cirrusBitMask =1<<11# Both flags should be set to zero, indicating clear conditions. mask = qa.bitwiseAnd(cloudBitMask).eq(0) \ .And(qa.bitwiseAnd(cirrusBitMask).eq(0))return image.updateMask(mask).divide(10000)# Sentinel-2 ImageCollection filtern und NDVI berechnensentinel2_vorher = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED') \ .filterDate('2018-06-01', '2018-08-22') \ .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20)) \ .map(maskS2clouds) \ .mean() \ .normalizedDifference(['B8', 'B4']) \ .rename('ndvi')# .filterDate('2019-01-01', '2019-05-01') \ # Für Brandrodungen im Amazonas-Regenwald# .filterDate('2018-06-01', '2018-08-22') \ # Für Waldbrände in Treuenbrietzen# Visualisierungsparameter festlegenvisualization_ndvi = {'min': 0,'max': 1,'palette': ['8bc4f9', 'c9995c', 'c7d270', '8add60', '097210'],'bands': ['ndvi']}# Layer der Karte hinzufügenNDVIvorher = geemap.ee_tile_layer(sentinel2_vorher, visualization_ndvi, 'Sentinel-2 NDVI vorher')
Anschließend wird auf der gleichen Datenbasis der NDVI nach dem Ereignis berechnet. Dabei werden alle Bilder aus dem September 2018 verwendet, also direkt nach dem Brand.
sentinel2_nachher = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED') \ .filterDate('2018-09-01', '2018-09-30') \ .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20)) \ .map(maskS2clouds) \ .mean() \ .normalizedDifference(['B8', 'B4']) \ .rename('ndvi')# .filterDate('2019-10-15', '2020-02-01') \ # Für Brandrodungen im Amazonas-Regenwald# .filterDate('2018-09-01', '2018-09-30') \ # FÜR Waldbrände in TreuenbrietzenNDVInachher = geemap.ee_tile_layer(sentinel2_nachher, visualization_ndvi, 'Sentinel-2 NDVI nachher')
Nun werden die beiden NDVI-Bilder in einer Split-Map gegenübergestellt. Zum Vergleich mit der heutigen Situation wird zusätzlich eine Luftbild-Basemap hinzugefügt.
# neue interaktive Karte erstellen, beide NDVI-Layer hinzufügen und anzeigenNDVIMap = geemap.Map(center=(52.04246028999631, 12.922582408028168), zoom=14)#NDVIMap = geemap.Map(center=(-21.67113558863388, -60.816409695725085), zoom=8) # Für Brandrodungen im Amazonas-Regenwald#NDVIMap = geemap.Map(center=(52.04246028999631, 12.922582408028168), zoom=14) # Für Waldbrände in TreuenbrietzenNDVIMap.split_map(NDVIvorher, NDVInachher)NDVIMap.add_basemap('Esri.WorldImagery')NDVIMap
Mit einem Differenzbild wird die Veränderung der Vegetation in einem einzigen Datensatz dargestellt. Dazu werden die Werte des Vorher-Bildes Pixel für Pixel von denen des Nachher-Bildes subtrahiert. Dadurch erhalten abnehmende Werte ein negatives Vorzeichen.
# NDVI-Differenz berechnen, visualisieren, neue interaktive Karte erstellen, den entstehenden Layer hinzufügen und Karte anzeigenndvi_diff = sentinel2_nachher.subtract(sentinel2_vorher)visualization_diff = {'min': -1,'max': 1,'palette': ['red', 'white', 'green'],'bands': ['ndvi']}DiffMap = geemap.Map(center=(52.04246028999631, 12.922582408028168), zoom=14)#DiffMap = geemap.Map(center=(-21.67113558863388, -60.816409695725085), zoom=8) # Für Brandrodungen im Amazonas-Regenwald#DiffMap = geemap.Map(center=(52.04246028999631, 12.922582408028168), zoom=14) # Für Waldbrände in TreuenbrietzenDiffMap.add_basemap('Esri.WorldImagery')DiffMap.addLayer(ndvi_diff, visualization_diff, 'NDVI Brandrodungen Sommer')DiffMap
Aufgabe: Mit dem Pixel Inspector (vgl. Absatz 4: “Inspector-Tool benutzen”) wird die Abnahme des NDVI untersucht. Versuche, die roten und grünen Flächen abseits der Brandfläche zu erklären. Tipp: Nicht alle Flächen sind tatsächlich auf eine Veränderung der Vegetation zurückzuführen.
Aufgabe: Diese Untersuchung kann ebenso im Amazonas-Regenwald durchgeführt werden, um Brandrodung zu identifizieren. In den Codezellen zur NDVI-Berechnung (vgl. Absatz 6.2: “Waldbrände”) befinden sich mit Rauten (#) auskommentiere, alternative Datumsfilter. Füge diese an die entsprechende Stelle ein und führe die Zellen erneut aus. Passe außerdem den Ausschnitt an, den die Karte anzeigt, und erstelle die Karte neu.
Wiederverwendung
Dieses Material steht unter der Lizenz CC BY-SA 4.0.
(Lizenz Anzeigen)
Zitat
Mit BibTeX zitieren:
@online{2025,
author = {, IZG},
title = {Grundlagen der Fernerkundung},
date = {2025-09-14},
url = {https://material.cdec.io/modul_1/notebooks/01c_Fernerkundung.html},
langid = {de}
}