Hello,
I like documenting some of code in my blog. Today I would like to share a simple classification using the python API of Google Earth Egnine. The results are not great but the approach is working.
I divided the code into two parts. In the first part, I define three polygons for deriving testing data for three classes: Urban, Green and Water and then classify a Landsat image. For the 2nd part, the visualisation, I modified the folium example provided here: https://colab.research.google.com/github/giswqs/qgis-earthengine-examples/blob/master/Folium/ee-api-folium-setup.ipynb#scrollTo=VP33EU7hJBq8 (Accessed Feb 2023).
First part:
import sys import csv import ee ee.Authenticate() ee.Initialize() # Get the polygon defining Washington countyData = ee.FeatureCollection('TIGER/2018/Counties') countyConnect = countyData.filter(ee.Filter.eq('STATEEF','11')) countyCpmmectDiss = countyConnect.union(100) # Load US county dataset. countyData = ee.FeatureCollection('TIGER/2018/Counties') # Filter the counties that are in Connecticut (more on filters later). washington = countyData.filter(ee.Filter.eq('STATEFP', '11')) Urban = ee.FeatureCollection( [ee.Feature( ee.Geometry.Polygon( [[[-77.0535926206179, 38.89903486157564], [-77.0535926206179, 38.895561277858654], [-77.04672616553978, 38.895427675091845], [-77.04655450416283, 38.899569243990044]]]), { "class": 0, "system:index": "0" })]) Water = ee.FeatureCollection( [ee.Feature( ee.Geometry.Polygon( [[[-77.05302814295763, 38.886078313198695], [-77.05611804774279, 38.88340585335565], [-77.04890826991075, 38.880198768850136]]]), { "class": 1, "system:index": "0" })]) Green = ee.FeatureCollection( [ee.Feature( #pGreenPoint, ee.Geometry.Polygon( [[[-77.03282, 38.87528], [-77.02759, 38.87545], [-77.0296 , 38.87254]]]), { "class": 2, "system:index": "0" })]) alltdata = Green.merge(Water) alltdata = alltdata.merge(Urban) bands = ['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7', 'ST_B10'] # Get a Landsat image and select Washington to avoid processing too many images image = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') \ .filterBounds(washington) \ .filterDate('2021-03-01', '2021-07-01')\ .median() label = "class" training = image.select(bands).sampleRegions( collection = alltdata, properties = [label], scale = 10 ) # Train classifier with 20 trees classifier = ee.Classifier.smileCart(20).train(training, label,bands) #print(classifier.confusionMatrix().accuracy()) # Classify the landsat images classified = image.select(bands).classify(classifier) print("TestFeatureVector: Processing Complete")
Second part:
#visualisation import folium import pandas as pd import numpy as np from folium import plugins # Add custom basemaps to folium basemaps = { 'Google Maps': folium.TileLayer( tiles = 'https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}', attr = 'Google', name = 'Google Maps', overlay = True, control = True ), 'Google Satellite': folium.TileLayer( tiles = 'https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', attr = 'Google', name = 'Google Satellite', overlay = True, control = True ), 'Google Terrain': folium.TileLayer( tiles = 'https://mt1.google.com/vt/lyrs=p&x={x}&y={y}&z={z}', attr = 'Google', name = 'Google Terrain', overlay = True, control = True ), 'Google Satellite Hybrid': folium.TileLayer( tiles = 'https://mt1.google.com/vt/lyrs=y&x={x}&y={y}&z={z}', attr = 'Google', name = 'Google Satellite', overlay = True, control = True ), 'Esri Satellite': folium.TileLayer( tiles = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', attr = 'Esri', name = 'Esri Satellite', overlay = True, control = True ) } # Define a method for displaying Earth Engine image tiles on a folium map. def add_ee_layer(self, ee_object, vis_params, name): try: # display ee.Image() if isinstance(ee_object, ee.image.Image): map_id_dict = ee.Image(ee_object).getMapId(vis_params) folium.raster_layers.TileLayer( tiles = map_id_dict['tile_fetcher'].url_format, attr = 'Google Earth Engine', name = name, overlay = True, control = True ).add_to(self) # display ee.ImageCollection() elif isinstance(ee_object, ee.imagecollection.ImageCollection): ee_object_new = ee_object.mosaic() map_id_dict = ee.Image(ee_object_new).getMapId(vis_params) folium.raster_layers.TileLayer( tiles = map_id_dict['tile_fetcher'].url_format, attr = 'Google Earth Engine', name = name, overlay = True, control = True ).add_to(self) # display ee.Geometry() elif isinstance(ee_object, ee.geometry.Geometry): folium.GeoJson( data = ee_object.getInfo(), name = name, overlay = True, control = True ).add_to(self) # display ee.FeatureCollection() elif isinstance(ee_object, ee.featurecollection.FeatureCollection): ee_object_new = ee.Image().paint(ee_object, 0, 2) map_id_dict = ee.Image(ee_object_new).getMapId(vis_params) folium.raster_layers.TileLayer( tiles = map_id_dict['tile_fetcher'].url_format, attr = 'Google Earth Engine', name = name, overlay = True, control = True ).add_to(self) except: print("Could not display {}".format(name)) # Add EE drawing method to folium. folium.Map.add_ee_layer = add_ee_layer my_map = folium.Map(location=[-8571600, 4579425], zoom_start=5, height=400) # Add custom basemaps basemaps['Google Maps'].add_to(my_map) basemaps['Google Satellite Hybrid'].add_to(my_map) # Add Land Mask to the map # Set visualization parameters. classVis = { 'min': 0, 'max': 10, 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']} #my_map.add_ee_layer(s2median , {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 2500, 'gamma': 1.1}, 'median' ) #my_map.add_ee_layer(ppBuffer, {}, 'ppBuffer' ) my_map.add_ee_layer(Urban , {}, 'Urban' ) my_map.add_ee_layer(Water , {}, 'Water' ) my_map.add_ee_layer(Green , {}, 'Green' ) my_map.add_ee_layer(classified,classVis,'classified') # Add a layer control panel to the map. my_map.add_child(folium.LayerControl()) plugins.Fullscreen().add_to(my_map) # Add a layer control panel to the map. my_map.add_child(folium.LayerControl()) # Add fullscreen button plugins.Fullscreen().add_to(my_map) # Display the map. display(my_map)
Here is an example of the output:
For the first part, I used this javascript tutorial to start with (https://www.youtube.com/watch?v=Md5_qkT-vC8&ab_channel=NoelGorelick), which was very useful but the final code is actually very differnt. I predominanly kept the study area, which is Washington.
I hope you find this tutorial useful to help you start working with your own data. :)
Acknowledgements: This work is done as part of my postdoctdoctoral research at University of Cambridge, funded by UKRI Future Leader's fellowship of Dr Emily Lines (FLF LCAG/439).