Google Satellite Embedding Dataset is a global dataset of pre-computed, analysis-ready geospatial embeddings for each year from 2017 onwards. This dataset was produced by Google DeepMind’s AlphaEarth Foundations model and presents a big leap in making remote sensing and climate datasets useful. Along with making existing remote sensing workflows more efficient, this dataset unlocks a range of new use cases. This workshop is designed to help you get started with the dataset in GEE and use it for a variety of applications.
If you already have a Google Earth Engine account, you can skip this step.
Visit our GEE Sign-Up Guide for step-by-step instructions.
The workshop material and exercises are in the form of Earth Engine scripts shared via a code repository.
users/ujavalgandhi/GEE-Satellite-Embedding
in the
Scripts tab in the Reader section.If you do not see the repository in the Reader section, click Refresh repository cache button in your Scripts tab and it will show up.
Workshop Repository
The course is accompanied by a video covering the all the sections This video is recorded from our live webinar class and is edited to make them easier to consume for self-study. We have 2 versions of the videos:
The video on YouTube is ideal for online learning and sharing. You may also turn on Subtitles/closed-captions and adjust the playback speed to suit your preference. Access the YouTube Video ↗
We have also made full-length video available on Vimeo. This video can be downloaded for offline learning. Access the Vimeo Video ↗
// Visualizing the Satellite Embedding Dataset
// ****************************************************
// Select a region
// ****************************************************
var geometry = ee.Geometry.Polygon([[
[76.39785, 12.5521],
[76.39785, 12.3550],
[76.65191, 12.3550],
[76.65191, 12.5521]
]]);
// Use the satellite basemap
Map.setOptions('SATELLITE');
// Draw a polygon to define the region
// Save it as the variable 'geometry'
Map.centerObject(geometry, 12);
// Prepare the Satellite Embedding dataset
// ****************************************************
var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
var year = 2024;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');
var filteredEmbeddings = embeddings
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
var embeddingsImage = filteredEmbeddings.mosaic();
print('Satellite Embeddings Image', embeddingsImage);
// Visualize the Satellite Embedding Dataset
// *********************************************************
// Visualize three axes of the embedding space as an RGB.
var visParams = {min: -0.3, max: 0.3, bands: ['A01', 'A16', 'A09']};
Map.addLayer(embeddingsImage.clip(geometry), visParams, 'Embeddings Image');
// Make the training dataset for unsupervised clustering
var nSamples = 1000;
var training = embeddingsImage.sample({
region: geometry,
scale: 10,
numPixels: nSamples,
seed: 100
});
print(training.first());
// Function to train a model for desired number of clusters
var getClusters = function(nClusters) {
var clusterer = ee.Clusterer.wekaKMeans({nClusters: nClusters})
.train(training);
// Cluster the image
var clustered = embeddingsImage.cluster(clusterer);
return clustered;
};
var cluster3 = getClusters(3);
Map.addLayer(cluster3.randomVisualizer().clip(geometry), {}, ' 3 clusters');
var cluster5 = getClusters(5);
Map.addLayer(cluster5.randomVisualizer().clip(geometry), {}, ' 5 clusters');
var cluster10 = getClusters(10);
Map.addLayer(cluster10.randomVisualizer().clip(geometry), {}, ' 10 clusters');
// Exercise
// Delete the geometry
// Draw a geometry for your region of interest
// Try visualizing the embeddings with different bands (A01, A02, A03...)
// Try changing the number of clusters to see different levels of detail
// Unsupervised Clustering with Satellite Embeddings
// Crop Type Mapping
// ****************************************************
// Select the region
// ****************************************************
// Cerro Gordo County, Iowa
var counties = ee.FeatureCollection('TIGER/2018/Counties');
var selected = counties
.filter(ee.Filter.eq('GEOID', '19033'));
var geometry = selected.geometry();
Map.centerObject(geometry, 12);
Map.setOptions('SATELLITE');
Map.addLayer(geometry, {color: 'red'}, 'Selected Region', false);
// Prepare the Satellite Embedding dataset
// ****************************************************
var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
var year = 2022;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');
var filteredembeddings = embeddings
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
var embeddingsImage = filteredembeddings.mosaic();
// Visualize three axes of the embedding space as an RGB.
var visParams = {min: -0.3, max: 0.3, bands: ['A01', 'A16', 'A09']};
Map.addLayer(embeddingsImage.clip(geometry), visParams, 'Embeddings Image');
// Create a Cropland Mask
// ****************************************************
// Use Cropland Data Layers (CDL) to obtain cultivated cropland
var cdl = ee.ImageCollection('USDA/NASS/CDL')
.filter(ee.Filter.date(startDate, endDate))
.first();
var cropLandcover = cdl.select('cropland');
var croplandMask = cdl.select('cultivated').eq(2).rename('cropmask');
// Visualize the crop mask
var croplandMaskVis = {min:0, max:1, palette: ['white', 'green']};
Map.addLayer(croplandMask.clip(geometry), croplandMaskVis, 'Crop Mask', false);
// Extract Training Samples
// ****************************************************
// Mask all non-cropland pixels
var clusterImage = embeddingsImage.updateMask(croplandMask);
Map.addLayer(clusterImage.clip(geometry), visParams,
'Embeddings Image (with Crop Mask)', false);
// We need to extract well distributed training samples
// for all target crops in the county
// Stratified random sampling to ensure we get desired
// number of samples exluding the masked pixels
var training = clusterImage.addBands(croplandMask).stratifiedSample({
numPoints: 1000,
classBand: 'cropmask',
region: geometry,
scale: 10,
tileScale: 16,
seed: 100,
dropNulls: true,
geometries: true
});
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Export samples to an asset (optional)
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Replace this with your asset folder
// The folder must exist before exporting
var exportFolder = 'projects/spatialthoughts/assets/satellite_embedding/';
var samplesExportFc = 'cluster_training_samples';
var samplesExportFcPath = exportFolder + samplesExportFc;
Export.table.toAsset({
collection: training,
description: 'Cluster_Training_Samples',
assetId: samplesExportFcPath
});
// Wait for the export to complete and continue with
// the exported asset from here onwards.
// Use the exported asset
var training = ee.FeatureCollection(samplesExportFcPath);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// End optional export section
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Visualize the samples
// ****************************************************
print('Extracted sample', training.first());
Map.addLayer(training, {color: 'blue'}, 'Extracted Samples', false);
// Perform Unsupervised Clustering
// ****************************************************
var minClusters = 4;
var maxClusters = 5;
var clusterer = ee.Clusterer.wekaCascadeKMeans({
minClusters:minClusters, maxClusters: maxClusters}).train({
features: training,
inputProperties: clusterImage.bandNames()
});
var clustered = clusterImage.cluster(clusterer);
Map.addLayer(clustered.randomVisualizer().clip(geometry), {}, 'Clusters', false);
// Assign Labels to Clusters
// ****************************************************
// Calculate Cluster Areas
// 1 Acre = 4046.86 Sq. Meters
var areaImage = ee.Image.pixelArea().divide(4046.86).addBands(clustered);
var areas = areaImage.reduceRegion({
reducer: ee.Reducer.sum().group({
groupField: 1,
groupName: 'cluster',
}),
geometry: geometry,
scale: 10,
maxPixels: 1e10
});
var clusterAreas = ee.List(areas.get('groups'));
// Process results to extract the areas and create a FeatureCollection
var clusterAreas = clusterAreas.map(function(item) {
var areaDict = ee.Dictionary(item);
var clusterNumber = areaDict.getNumber('cluster').format();
var area = areaDict.getNumber('sum');
return ee.Feature(null, {cluster: clusterNumber, area: area});
});
var clusterAreaFc = ee.FeatureCollection(clusterAreas);
print('Cluster Areas', clusterAreaFc);
// This region has 2 primary crops - corn and soybean
// Pick the 2 clusters with the highest area
var selectedFc = clusterAreaFc.sort('area', false).limit(2);
print('Top 2 Clusters by Area', selectedFc);
// We do not know which is what crops
// Use the crop statistics and match those areas
// Cerro Gordo County, Iowa
// Corn statistics https://www.nass.usda.gov/Statistics_by_State/Iowa/Publications/County_Estimates/2023/IA-CtyEst-Corn-02-23.pdf
// Soybean statistics https://www.nass.usda.gov/Statistics_by_State/Iowa/Publications/County_Estimates/2023/IA-CtyEst-Soybeans-02-23.pdf
// Corn Area: 163,500 Acres
// Soybean Area: 110,500 Acres
// From the 2 clusters, the one with the highest area is 'Corn'
// Other is Soybean
var cornFeature = selectedFc.sort('area', false).first();
var soybeanFeature = selectedFc.sort('area').first();
var cornCluster = cornFeature.get('cluster');
var soybeanCluster = soybeanFeature.get('cluster');
print('Corn Area (Detected)', cornFeature.getNumber('area').round());
print('Corn Area (From Crop Statistics)', 163500);
print('Soybean Area (Detected)', soybeanFeature.getNumber('area').round());
print('Soybean Area (From Crop Statistics)', 110500);
// Create a Crop Map
// ****************************************************
// Select the clusters to create the crop map
var corn = clustered.eq(ee.Number.parse(cornCluster));
var soybean = clustered.eq(ee.Number.parse(soybeanCluster));
// Visualize the final output
var merged = corn.add(soybean.multiply(2));
var cropVis = {min:0, max:2, palette: ['#bdbdbd', '#ffd400', '#267300']};
Map.addLayer(merged.clip(geometry), cropVis, 'Crop Map (Detected)');
// Add a Legend
var legend = ui.Panel({
layout: ui.Panel.Layout.Flow('horizontal'),
style: {position: 'bottom-center', padding: '8px 15px'}});
var addItem = function(color, name) {
var colorBox = ui.Label({
style: {color: '#ffffff',
backgroundColor: color,
padding: '10px',
margin: '0 4px 4px 0',
}
});
var description = ui.Label({
value: name,
style: {
margin: '0px 10px 0px 2px',
}
});
return ui.Panel({
widgets: [colorBox, description],
layout: ui.Panel.Layout.Flow('horizontal')}
)};
var title = ui.Label({
value: 'Legend',
style: {fontWeight: 'bold',
fontSize: '16px',
margin: '0px 10px 0px 4px'}});
legend.add(title);
legend.add(addItem('#ffd400', 'Corn'));
legend.add(addItem('#267300', 'Soybean'));
legend.add(addItem('#bdbdbd', 'Other Crops'));
Map.add(legend);
// Validate the results
// ****************************************************
// Compare our results with the crop type map from CDL
var cdl = ee.ImageCollection('USDA/NASS/CDL')
.filter(ee.Filter.date(startDate, endDate))
.first();
var cropLandcover = cdl.select('cropland');
var cropMap = cropLandcover.updateMask(croplandMask).rename('crops');
// Original data has unique values for each crop ranging from 0 to 254
var cropClasses = ee.List.sequence(0, 254);
// We remap all values as following
// Crop | Source Value | Target Value
// Corn | 1 | 1
// Soybean | 5 | 2
// All other| 0-255 | 0
var targetClasses = ee.List.repeat(0, 255).set(1, 1).set(5, 2);
var cropMapReclass = cropMap.remap(cropClasses, targetClasses).rename('crops');
var cropVis = {min: 0, max: 2, palette: ['#bdbdbd', '#ffd400', '#267300']};
Map.addLayer(cropMapReclass.clip(geometry), cropVis, 'Crop Landcover (CDL)');
// Exercise: Crop Type Mapping
// ****************************************************
// Select the region
// ****************************************************
var geometry = ee.Geometry.Polygon([[
[83.6180, 21.43577],
[83.6180, 21.26181],
[83.8391, 21.26181],
[83.8391, 21.43577]
]]);
Map.centerObject(geometry, 12);
Map.setOptions('SATELLITE');
Map.addLayer(geometry, {color: 'red'}, 'Selected Region', false);
// Prepare the Satellite Embedding dataset
// ****************************************************
var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
var year = 2024;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');
var filteredembeddings = embeddings
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
var embeddingsImage = filteredembeddings.mosaic();
// Visualize three axes of the embedding space as an RGB.
var visParams = {min: -0.3, max: 0.3, bands: ['A01', 'A16', 'A09']};
Map.addLayer(embeddingsImage.clip(geometry), visParams, 'Embeddings Image', false);
// Create a Cropland Mask
// ****************************************************
// Use ESA Worldcover cropland
// This dataset is from 2021 so there maybe a mismatch
// in cropland extent in recent years
var worldcover = ee.ImageCollection('ESA/WorldCover/v200');
var classification = worldcover.first();
var cropLandcover = classification.eq(40);
var croplandMask = cropLandcover.rename('cropmask');
// Visualize the crop mask
var croplandMaskVis = {min:0, max:1, palette: ['white', 'green']};
Map.addLayer(croplandMask.clip(geometry), croplandMaskVis, 'Crop Mask', false);
// Extract Training Samples
// ****************************************************
// Mask all non-cropland pixels
var clusterImage = embeddingsImage.updateMask(croplandMask);
Map.addLayer(clusterImage.clip(geometry), visParams,
'Embeddings Image (with Crop Mask)', false);
// We need to extract well distributed training samples
// for all target crops in the county
// Stratified random sampling to ensure we get desired
// number of samples exluding the masked pixels
var training = clusterImage.addBands(croplandMask).stratifiedSample({
numPoints: 1000,
classBand: 'cropmask',
region: geometry,
scale: 10,
tileScale: 16,
seed: 100,
dropNulls: true,
geometries: true
});
// Perform Unsupervised Clustering
// ****************************************************
var minClusters = 2;
var maxClusters = 5;
var clusterer = ee.Clusterer.wekaCascadeKMeans({
minClusters:minClusters, maxClusters: maxClusters}).train({
features: training,
inputProperties: clusterImage.bandNames()
});
var clustered = clusterImage.cluster(clusterer);
Map.addLayer(clustered.randomVisualizer().clip(geometry), {}, 'Clusters');
// Add Sentinel-2 NDVI Time-Series
// ****************************************************
var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');
// Load the Cloud Score+ collection
var csPlus = ee.ImageCollection('GOOGLE/CLOUD_SCORE_PLUS/V1/S2_HARMONIZED');
var csPlusBands = csPlus.first().bandNames();
// We need to add Cloud Score + bands to each Sentinel-2
// image in the collection
// This is done using the linkCollection() function
var s2WithCs = s2.linkCollection(csPlus, csPlusBands);
// Function to mask pixels with low CS+ QA scores.
function maskLowQA(image) {
var qaBand = 'cs';
var clearThreshold = 0.5;
var mask = image.select(qaBand).gte(clearThreshold);
return image.updateMask(mask);
}
function addNDVI(image) {
var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
return image.addBands(ndvi);
}
// Function to create and display NDVI time-series chart
// when a point is clicked
function displayChart(point) {
chartPanel.clear();
var pointGeom = ee.Geometry.Point(point.lon, point.lat);
var filtered = s2WithCs
.filter(ee.Filter.date(startDate, endDate))
.map(maskLowQA)
.map(addNDVI)
.filter(ee.Filter.bounds(pointGeom));
var chart = ui.Chart.image.series({
imageCollection: filtered.select('ndvi'),
region: pointGeom,
reducer: ee.Reducer.mean(),
scale: 20}).setOptions({
title: 'NDVI Time Series',
vAxis: {title: 'NDVI', viewWindow: {min:0, max:1}},
hAxis: {title: 'Date', gridlines: {count: 12}},
interpolateNulls: true,
pointSize: 2,
lineWidth: 1
});
chartPanel.add(chart);
}
var chartPanel = ui.Panel({
style: {width: '400px', position: 'bottom-right'}
});
Map.add(chartPanel);
Map.onClick(displayChart);
// Exercise
// Delete the geometry
// Draw a geometry for your region of interest
// Adjust the minClusters and maxClusters based on your knowledge
// Click on any location to see the NDVI Time-Series
// Use your local knowledge to identify the crop(s)
// Note: Interactive visualization of clusters will only work for
// small regions. Export your training samples as Asset first
// if classifying large regions.
// The region selected here is in the Bargarh distrct, Odisha, India
// with the primary crop being Rice.
// Data from https://upag.gov.in/
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var geometry =
/* color: #98ff00 */
/* shown: false */
ee.Geometry.Polygon(
[[[39.4926, -4.39833],
[39.4926, -4.47394],
[39.5491, -4.47394],
[39.5491, -4.39833]]]),
mangroves =
/* color: #6bd651 */
/* shown: false */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Point([39.53332459156346, -4.424306862786138]),
{
"landcover": 1,
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Point([39.515674132076356, -4.417484208564611]),
{
"landcover": 1,
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Point([39.521682280269715, -4.414916932798933]),
{
"landcover": 1,
"system:index": "2"
}),
ee.Feature(
ee.Geometry.Point([39.53301193114862, -4.412092919198809]),
{
"landcover": 1,
"system:index": "3"
}),
ee.Feature(
ee.Geometry.Point([39.52305557128534, -4.41904596364173]),
{
"landcover": 1,
"system:index": "4"
}),
ee.Feature(
ee.Geometry.Point([39.52751876708612, -4.418767843115292]),
{
"landcover": 1,
"system:index": "5"
}),
ee.Feature(
ee.Geometry.Point([39.512952520329506, -4.42470302325086]),
{
"landcover": 1,
"system:index": "6"
}),
ee.Feature(
ee.Geometry.Point([39.51191450544074, -4.425050671107723]),
{
"landcover": 1,
"system:index": "7"
}),
ee.Feature(
ee.Geometry.Point([39.51075895498842, -4.429791895347292]),
{
"landcover": 1,
"system:index": "8"
}),
ee.Feature(
ee.Geometry.Point([39.51114519308656, -4.429235662261579]),
{
"landcover": 1,
"system:index": "9"
})]),
water =
/* color: #0b4a8b */
/* shown: false */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Point([39.51274523032135, -4.4343394780686385]),
{
"landcover": 2,
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Point([39.51441892874664, -4.429162247319931]),
{
"landcover": 2,
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Point([39.52403196585602, -4.429418970360026]),
{
"landcover": 2,
"system:index": "2"
}),
ee.Feature(
ee.Geometry.Point([39.52016958487457, -4.425782052317534]),
{
"landcover": 2,
"system:index": "3"
}),
ee.Feature(
ee.Geometry.Point([39.50879701865143, -4.443581386549747]),
{
"landcover": 2,
"system:index": "4"
}),
ee.Feature(
ee.Geometry.Point([39.50553545248932, -4.447860008667267]),
{
"landcover": 2,
"system:index": "5"
}),
ee.Feature(
ee.Geometry.Point([39.50399050009674, -4.449913738457232]),
{
"landcover": 2,
"system:index": "6"
}),
ee.Feature(
ee.Geometry.Point([39.51965460074371, -4.445635128266346]),
{
"landcover": 2,
"system:index": "7"
}),
ee.Feature(
ee.Geometry.Point([39.51171526205963, -4.469081606555194]),
{
"landcover": 2,
"system:index": "8"
}),
ee.Feature(
ee.Geometry.Point([39.50347551596588, -4.469680594368735]),
{
"landcover": 2,
"system:index": "9"
}),
ee.Feature(
ee.Geometry.Point([39.525425885851405, -4.417474500749167]),
{
"landcover": 2,
"system:index": "10"
})]),
other =
/* color: #79776d */
/* shown: false */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Point([39.50560992076606, -4.4242595999510455]),
{
"landcover": 3,
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Point([39.50620000674934, -4.423307578260568]),
{
"landcover": 3,
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Point([39.50448339297981, -4.423799634568]),
{
"landcover": 3,
"system:index": "2"
}),
ee.Feature(
ee.Geometry.Point([39.50197284534187, -4.423649878335117]),
{
"landcover": 3,
"system:index": "3"
}),
ee.Feature(
ee.Geometry.Point([39.503313949849314, -4.4228369153997535]),
{
"landcover": 3,
"system:index": "4"
}),
ee.Feature(
ee.Geometry.Point([39.497137934254695, -4.416632173880207]),
{
"landcover": 3,
"system:index": "5"
}),
ee.Feature(
ee.Geometry.Point([39.49610796599298, -4.418386475891598]),
{
"landcover": 3,
"system:index": "6"
}),
ee.Feature(
ee.Geometry.Point([39.504884153889705, -4.415434111585769]),
{
"landcover": 3,
"system:index": "7"
}),
ee.Feature(
ee.Geometry.Point([39.540219677644, -4.402738757778825]),
{
"landcover": 3,
"system:index": "8"
}),
ee.Feature(
ee.Geometry.Point([39.537083376051925, -4.414620272781714]),
{
"landcover": 3,
"system:index": "9"
}),
ee.Feature(
ee.Geometry.Point([39.54329128212492, -4.400688640340887]),
{
"landcover": 3,
"system:index": "10"
}),
ee.Feature(
ee.Geometry.Point([39.543870639272136, -4.399725891211968]),
{
"landcover": 3,
"system:index": "11"
}),
ee.Feature(
ee.Geometry.Point([39.50106019752159, -4.41120573786903]),
{
"landcover": 3,
"system:index": "12"
}),
ee.Feature(
ee.Geometry.Point([39.50085098521843, -4.411943834251456]),
{
"landcover": 3,
"system:index": "13"
})]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
// Supervised Classification with Satellite Embeddings
// Mapping Mangroves
// ****************************************************
// Select a region
// ****************************************************
// Draw a polygon to define the region
// Save it as the variable 'geometry'
Map.centerObject(geometry);
// Collect Training Samples
// ****************************************************
// Pick a year for classification
var year = 2020;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');
// Create a Sentinel-2 Compsite for the selected year
// for selecting training samples
var s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED');
var filteredS2 = s2
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
// Use the Cloud Score+ collection for cloud masking
var csPlus = ee.ImageCollection('GOOGLE/CLOUD_SCORE_PLUS/V1/S2_HARMONIZED');
var csPlusBands = csPlus.first().bandNames();
var filteredS2WithCs = filteredS2.linkCollection(csPlus, csPlusBands);
function maskLowQA(image) {
var qaBand = 'cs';
var clearThreshold = 0.6;
var mask = image.select(qaBand).gte(clearThreshold);
return image.updateMask(mask);
}
var filteredS2Masked = filteredS2WithCs
.map(maskLowQA)
.select('B.*');
// Create a median composite of cloud-masked images
var composite = filteredS2Masked.median();
// Display the input composite in false color
// that helps distinguish between
// water, vegetation and built surfaces
var swirVis = {min: 300, max: 4000, bands: ['B11', 'B8', 'B4']};
Map.centerObject(geometry);
Map.addLayer(composite.clip(geometry), swirVis, 'S2 Composite (False Color)');
// Merge the collected training samples
var gcps = mangroves.merge(water).merge(other);
// Train a Classifier
// ****************************************************
// Sample Embedding Vectors
var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
var embeddingsFiltered = embeddings
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
var embeddingsImage = embeddingsFiltered.mosaic();
// Overlay the samples on the image to get training data.
var training = embeddingsImage.sampleRegions({
collection: gcps,
properties: ['landcover'],
scale: 10
});
// Train a classifier.
var classifier = ee.Classifier.smileKNN().train({
features: training,
classProperty: 'landcover',
inputProperties: embeddingsImage.bandNames()
});
// Classify the Satellite Embedding Mosaic
// ****************************************************
var classified = embeddingsImage.classify(classifier);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Export classified image to an asset (optional)
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Replace this with your asset folder
// The folder must exist before exporting
var exportFolder = 'projects/spatialthoughts/assets/satellite_embedding/';
var classifiedExportImage = 'mangrove_classification';
var classifiedExportImagePath = exportFolder + classifiedExportImage;
Export.image.toAsset({
image: classified.clip(geometry),
description: 'Classified_Image_Export',
assetId: classifiedExportImagePath,
region: geometry,
scale: 10,
pyramidingPolicy: 'MODE',
maxPixels: 1e10
});
// Wait for the export to complete and continue with
// the exported asset from here onwards.
// Use the exported asset
var classified = ee.Image(classifiedExportImagePath);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// End optional export section
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Visualize the classification
// ****************************************************
// Choose a 3-color palette
// Assign a color for each class in the following order
// Mangrove, Water, Other
var palette = ['green', 'blue', 'gray'];
Map.addLayer(
classified.clip(geometry),
{min: 1, max: 3, palette: palette},
'Classified Satellite Embeddings Image');
// Extract mangroves class
var mangrovesImage = classified.eq(1).selfMask();
var mangroveVis = {min:0, max:1, palette: ['green']};
Map.addLayer(mangrovesImage.clip(geometry),
mangroveVis, 'Mangroves (Satellite Embedding Classification)');
// Exercise: Mapping Mangroves
// ****************************************************
// Select the region
// ****************************************************
var geometry = ee.Geometry.Polygon([[
[39.4926, -4.39833],
[39.4926, -4.47394],
[39.5491, -4.47394],
[39.5491, -4.39833]
]]);
Map.centerObject(geometry);
// Pick a year for classification
var year = 2020;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');
// Create a Sentinel-2 Compsite for the selected year
// for selecting training samples
var s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED');
var filteredS2 = s2
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
// Use the Cloud Score+ collection for cloud masking
var csPlus = ee.ImageCollection('GOOGLE/CLOUD_SCORE_PLUS/V1/S2_HARMONIZED');
var csPlusBands = csPlus.first().bandNames();
var filteredS2WithCs = filteredS2.linkCollection(csPlus, csPlusBands);
function maskLowQA(image) {
var qaBand = 'cs';
var clearThreshold = 0.6;
var mask = image.select(qaBand).gte(clearThreshold);
return image.updateMask(mask);
}
var filteredS2Masked = filteredS2WithCs
.map(maskLowQA)
.select('B.*');
// Create a median composite of cloud-masked images
var composite = filteredS2Masked.median();
// Display the input composite in false color
// that helps distinguish between
// water, vegetation and built surfaces
var swirVis = {min: 300, max: 4000, bands: ['B11', 'B8', 'B4']};
Map.centerObject(geometry);
Map.addLayer(composite.clip(geometry), swirVis, 'S2 Composite (False Color)');
// Global Mangrove Watch reference layer
var gmw = ee.ImageCollection('projects/earthengine-legacy/assets/projects/sat-io/open-datasets/GMW/extent/GMW_V3');
var gmwFiltered = gmw
.filter(ee.Filter.date(startDate, endDate));
var gmwImage = gmwFiltered.mosaic();
Map.addLayer(gmwImage,
{min:0, max:1, palette: ['purple']},
'Reference Mangrove Layer', false);
// Exercise
// Delete the geometry and draw a polygon for your region of interest
// Tip: Turn on Reference Mangrove Layer to previously mapped
// locations of mangroves.
// Add training samples for 3 classes
// Create FeatureCollections and the
// 'landcover' property as follows
// mangroves: 1
// water: 2
// other: 3
// After adding samples, uncomments lines below
// Use Ctrl + / keyboard shortcut for uncommenting selection
// // ****************************************************
// // Merge the collected training samples
// var gcps = mangroves.merge(water).merge(other);
// // Train a Classifier
// // ****************************************************
// // Sample Embedding Vectors
// var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
// var embeddingsFiltered = embeddings
// .filter(ee.Filter.date(startDate, endDate))
// .filter(ee.Filter.bounds(geometry));
// var embeddingsImage = embeddingsFiltered.mosaic();
// // Overlay the samples on the image to get training data.
// var training = embeddingsImage.sampleRegions({
// collection: gcps,
// properties: ['landcover'],
// scale: 10
// });
// // Train a classifier.
// var classifier = ee.Classifier.smileKNN().train({
// features: training,
// classProperty: 'landcover',
// inputProperties: embeddingsImage.bandNames()
// });
// // Classify the Satellite Embedding Mosaic
// // ****************************************************
// var classified = embeddingsImage.classify(classifier);
// // Visualize the classification
// // ****************************************************
// // Choose a 3-color palette
// // Assign a color for each class in the following order
// // Mangrove, Water, Other
// var palette = ['green', 'blue', 'gray'];
// Map.addLayer(
// classified.clip(geometry),
// {min: 1, max: 3, palette: palette},
// 'Classified Satellite Embeddings Image');
// // Extract mangroves class
// var mangrovesImage = classified.eq(1).selfMask();
// var mangroveVis = {min:0, max:1, palette: ['green']};
// Map.addLayer(mangrovesImage.clip(geometry),
// mangroveVis, 'Mangroves (Satellite Embedding Classification)');
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var samples = /* color: #bf04c2 */ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Point([72.57492570563792, 23.141105013380294]),
{
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Point([72.60209347873312, 23.160608676844905]),
{
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Point([72.61008969270353, 23.212196741036685]),
{
"system:index": "2"
})]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
// Similarity Search with Satellite Embeddings
// Mapping Brick Kiln locations
// Select the Search Region
// ****************************************************
// Use GAUL 2024 dataset from GEE Community Catalog
var admin2 = ee.FeatureCollection('projects/sat-io/open-datasets/FAO/GAUL/GAUL_2024_L2');
// Gandhinagar district, Gujarat, India
var filteredAdmin2 = admin2
.filter(ee.Filter.eq('gaul2_name', 'Gandhinagar'))
.filter(ee.Filter.eq('gaul1_name', 'Gujarat'));
var geometry = filteredAdmin2.geometry();
Map.centerObject(geometry);
Map.addLayer(geometry, {color: 'red'}, 'Search Area');
// Select Reference Location(s)
// ****************************************************
// Use the satellite basemap
Map.setOptions('SATELLITE');
// Add a few reference locations of Brick Kilns
// in the 'samples' FeatureCollection
// Select a time-period
// ****************************************************
var year = 2024;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');
// Filter and mosaic the Satellite Embedding dataset
// ****************************************************
var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
var mosaic = embeddings
.filter(ee.Filter.date(startDate, endDate))
.mosaic();
// Choose the scale
// You may choose a larger value for larger objects
var scale = 20;
// Extract the embedding vector from the samples
var sampleEmbeddings = mosaic.sampleRegions({
collection: samples,
scale: scale
});
// Calculate Similarity
// ****************************************************
// We compute the dot product between two embedding vectors
// Results are interepreted as distances in embedding space
// Values closer to 0 are closer together (more similar)
// Values closer to 1 are further apart (less similar)
var bandNames = mosaic.bandNames();
var sampleDistances = ee.ImageCollection(sampleEmbeddings.map(function (f) {
var arrayImage = ee.Image(f.toArray(bandNames)).arrayFlatten([bandNames]);
var dotProduct = arrayImage.multiply(mosaic)
.reduce('sum')
.rename('similarity');
return dotProduct;
}));
// Calculate mean distance from all reference locations
var meanDistance = sampleDistances.mean();
// Visualize the distance image
var palette = [
'000004', '2C105C', '711F81', 'B63679',
'EE605E', 'FDAE78', 'FCFDBF', 'FFFFFF'
];
var similarityVis = {palette: palette, min: 0.5, max: 1};
Map.addLayer(meanDistance.clip(geometry), similarityVis,
'Similarity (bright = close)', false);
// Extract Location Matches
// ****************************************************
// Apply a threshold
var threshold = 0.97;
var similarPixels = meanDistance.gt(threshold);
// Vectorize the results
// Mask 0 values using selfMask()
// to get polygons only for the matched pixels
var polygons = similarPixels.selfMask().reduceToVectors({
scale: scale,
eightConnected: false,
maxPixels: 1e10,
geometry: geometry
});
// Extract the centroids of vectorized polygons
var predictedMatches = polygons.map(function(f) {
return f.centroid({maxError:1});
});
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Export matches to an asset (optional)
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Vectorization operation is a memory and compute-intensive
// operation. To prevent errors, Export the results as an Asset first.
// Once the asset is exported, it can be imported and visualized
// Replace this with your asset folder
// The folder must exist before exporting
var exportFolder = 'projects/spatialthoughts/assets/satellite_embedding/';
var matchesExportFc = 'predicted_brick_kiln_matches';
var matchesExportFcPath = exportFolder + matchesExportFc;
Export.table.toAsset({
collection: predictedMatches,
description: 'Predicted_Matches_Export',
assetId: matchesExportFcPath
});
// Wait for the export to complete and continue with
// the exported asset from here onwards.
//var predictedMatches = ee.FeatureCollection(matchesExportFcPath);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// End optional export section
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Visualize the Matches
// ****************************************************
Map.addLayer(predictedMatches, {color: 'cyan'} , 'Predicted Matches');
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var samples = /* color: #bf04c2 */ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Point([71.62064756880882, 23.417896432110815]),
{
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Point([71.5828687753274, 23.47579517396437]),
{
"system:index": "1"
})]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
// Exercise: Mapping Solar Farms
// ****************************************************
// Select the Search Region
// ****************************************************
var geometry = ee.Geometry.Polygon([[
[71.2208, 23.6897],
[71.2208, 23.1642],
[71.8614, 23.1642],
[71.8614, 23.6897]
]]);
Map.centerObject(geometry);
Map.addLayer(geometry, {color: 'red'}, 'Search Area');
// Select Reference Location(s)
// ****************************************************
// Use the satellite basemap
Map.setOptions('SATELLITE');
// Mark location(s) with solar farms in the 'samples' FeatureCollection
// Select a time-period
// ****************************************************
var year = 2024;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');
// Filter and mosaic the Satellite Embedding dataset
// ****************************************************
var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
var mosaic = embeddings
.filter(ee.Filter.date(startDate, endDate))
.mosaic();
// Choose the scale
// You may choose a larger value for larger objects
var scale = 10;
// Extract the embedding vector from the samples
var sampleEmbeddings = mosaic.sampleRegions({
collection: samples,
scale: scale
});
// Calculate Similarity
// ****************************************************
// We compute the dot product between two embedding vectors
// Results are interepreted as distances in embedding space
// Values closer to 0 are closer together (more similar)
// Values closer to 1 are further apart (less similar)
var bandNames = mosaic.bandNames();
var sampleDistances = ee.ImageCollection(sampleEmbeddings.map(function (f) {
var arrayImage = ee.Image(f.toArray(bandNames)).arrayFlatten([bandNames]);
var dotProduct = arrayImage.multiply(mosaic)
.reduce('sum')
.rename('similarity');
return dotProduct;
}));
// Calculate mean distance from all reference locations
var meanDistance = sampleDistances.mean();
// Visualize the distance image
var palette = [
'000004', '2C105C', '711F81', 'B63679',
'EE605E', 'FDAE78', 'FCFDBF', 'FFFFFF'
];
var similarityVis = {palette: palette, min: 0.5, max: 1};
Map.addLayer(meanDistance.clip(geometry), similarityVis,
'Similarity (bright = close)', false);
// Extract Location Matches
// ****************************************************
// Apply a threshold
var threshold = 0.95;
var similarPixels = meanDistance.gt(threshold);
// Vectorize the results
// Mask 0 values using selfMask()
// to get polygons only for the matched pixels
var polygons = similarPixels.selfMask().reduceToVectors({
scale: scale,
eightConnected: false,
maxPixels: 1e10,
geometry: geometry
});
// Extract the centroids of vectorized polygons
var predictedMatches = polygons.map(function(f) {
return f.centroid({maxError:1});
});
// Visualize the Matches
// ****************************************************
Map.addLayer(predictedMatches, {color: 'cyan'} , 'Predicted Matches');
// Use the Global Photovoltaics Inventory dataset
// https://gee-community-catalog.org/projects/global_pv/
var solarFarms = ee.FeatureCollection('projects/sat-io/open-datasets/global_photovoltaic/predicted_set');
Map.addLayer(solarFarms, {color:'yellow'}, 'Solar Farms Database', false);
// Exercise
// Delete the geometry
// Draw a geometry for your region of interest
// Tip: Use a rural region without rooftop solar
// Adjust the scale and threshold
// Visualize the results
// Note: Interactive visualization of results will only work for
// small regions. Export the predicted matches as Asset first
// if working in a large regions.
// Unsupervised Clustering with Satellite Embeddings
// Adaptation of the 'waterdetect' algorithm using
// Satellite Embedding dataset
// Reference: https://github.com/cordmaur/WaterDetect
// Cordeiro, M. C. R.; Martinez, J.-M.; Peña-Luque, S.
// Automatic Water Detection from Multidimensional Hierarchical Clustering for Sentinel-2 Images
// and a Comparison with Level 2A Processors.
// Remote Sensing of Environment 2021, 253, 112209. https://doi.org/10.1016/j.rse.2020.112209.
// Use the satellite basemap
Map.setOptions('SATELLITE');
// Draw a polygon to define the region
var geometry = ee.Geometry.Polygon([[
[77.48932, 13.0311],
[77.48932, 12.8130],
[77.72828, 12.8130],
[77.72828, 13.0311]
]]);
Map.centerObject(geometry, 12);
// Prepare the Satellite Embedding dataset
// ****************************************************
var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
var year = 2024;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');
var filteredEmbeddings = embeddings
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
var embeddingsImage = filteredEmbeddings.mosaic();
print('Satellite Embeddings Image', embeddingsImage);
// Perform Unsupervised Clustering
// ****************************************************
// Make the training dataset for unsupervised clustering
var training = embeddingsImage.sample({
region: geometry,
scale: 10,
numPixels: 1000
});
print(training.first());
// Instantiate the clusterer and train it.
var clusterer = ee.Clusterer.wekaCascadeKMeans({
minClusters: 10,
maxClusters: 12
}).train(training);
// Cluster the stacked image
var clustered = embeddingsImage.cluster(clusterer);
// Automatic Detection of Water Cluster
// ****************************************************
// We need to identify which of the clusters represent water
// Use Sentinel-2 MNDWI to find the 'water' cluster automaticallly
// Prepare a Sentinel-2 composite for the selected region
var s2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED");
var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
// Load the Cloud Score+ collection
var csPlus = ee.ImageCollection('GOOGLE/CLOUD_SCORE_PLUS/V1/S2_HARMONIZED');
var csPlusBands = csPlus.first().bandNames();
// We need to add Cloud Score + bands to each Sentinel-2
// image in the collection
// This is done using the linkCollection() function
var filteredS2WithCs = filtered.linkCollection(csPlus, csPlusBands);
// Function to mask pixels with low CS+ QA scores.
function maskLowQA(image) {
var qaBand = 'cs';
var clearThreshold = 0.5;
var mask = image.select(qaBand).gte(clearThreshold);
return image.updateMask(mask);
}
var filteredMasked = filteredS2WithCs
.map(maskLowQA)
.select('B.*');
var image = filteredMasked.median();
// Calculate Modified Normalized Difference Water Index (MNDWI)
// 'GREEN' (B3) and 'SWIR1' (B11)
var mndwi = image.normalizedDifference(['B3', 'B11']).rename(['mndwi']);
// We use the MNDWI band and select the cluster with the
// highest average MNDWI values of all pixels within the cluster
// Calculate the stats on MNDWI band, grouped by clusters
// Copmpute at lower resolution as accuracy is not
// important. We just need to find the cluster with
// highest MNDWI
var stats = mndwi.addBands(clustered).reduceRegion({
reducer: ee.Reducer.mean().group({
groupField: 1,
groupName: 'cluster',
}),
geometry: geometry,
scale: 100,
maxPixels: 1e8
});
print(stats);
// Extract the cluster-wise stats as a list of lists
// We get a list in the following format
// [[avg_mndwi, cluster_number], [avg_mndwi, cluster_number] ...]]
var groupStats = ee.List(stats.get('groups'));
var groupStatsLists = groupStats.map(function(item) {
var areaDict = ee.Dictionary(item);
var clusterNumber = ee.Number(
areaDict.get('cluster'));
var mndwi = ee.Number(
areaDict.get('mean'));
return ee.List([mndwi, clusterNumber]);
});
// Use the ee.Reducer.max() on the list of lists
// It will pick the list with the highest MNDWI
var waterClusterList = ee.Dictionary(ee.List(groupStatsLists)
.reduce(ee.Reducer.max(2)));
// Extract the cluster number
var waterCluster = ee.Number(waterClusterList.get('max1'));
// Select all pixels from the water cluster and mask everything else
var water = clustered.eq(waterCluster).selfMask();
// The original waterdetect algorithm has an additional step
// to train a supervised classifier using the water vs. non-water
// samples detected from the procedure above.
// In our testing, there was no significant improvement to the
// output, so we have not added that step.
// Visualize the results
// ****************************************************
var waterVis = {min:0, max:1, palette: ['white', 'blue']};
Map.setCenter(77.61, 13.08, 14);
Map.centerObject(geometry, 10);
Map.addLayer(clustered.clip(geometry).randomVisualizer(), {}, 'clusters');
Map.addLayer(water.clip(geometry), waterVis, 'water');
// Interactive visualization may time-out for large images
// Export the image to use the batch processing mode
Export.image.toDrive({
image: water,
description: 'Water_Cluster',
folder: 'earthengine',
fileNamePrefix: 'water_cluster',
region: geometry,
scale: 10,
maxPixels: 1e10});
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var geometry =
/* color: #d63000 */
/* shown: false */
/* displayProperties: [
{
"type": "rectangle"
}
] */
ee.Geometry.Polygon(
[[[77.45008052370622, 13.099222201663046],
[77.45008052370622, 12.81148072984957],
[77.74739802858903, 12.81148072984957],
[77.74739802858903, 13.099222201663046]]], null, false),
built = /* color: #ff0400 */ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[77.55746624775949, 12.935821122826876],
[77.55747697659555, 12.935429001761442],
[77.55777738400522, 12.935193728826327],
[77.55752062496639, 12.935648232422064],
[77.55799269375301, 12.935836450444983],
[77.55782103237605, 12.936249483941939],
[77.55753135380245, 12.936228570869929]]]),
{
"landcover": 1,
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.56818411665238, 12.93297109349934],
[77.56808755712784, 12.932829928374142],
[77.56798026876724, 12.932767188292866],
[77.5675940306691, 12.9324744010383],
[77.56758866625107, 12.93219729849878],
[77.56778178530014, 12.93198293594578],
[77.56807682829178, 12.931805171737762],
[77.56834504919327, 12.931894053857597],
[77.56850598173416, 12.93213455825844],
[77.56860790567673, 12.932254810371916],
[77.56883857565201, 12.932087503067805],
[77.56881711797989, 12.932312322231782],
[77.5688922198323, 12.932411660867626],
[77.56909606771744, 12.9324744010383],
[77.56909606771744, 12.932741046587681],
[77.56893513517655, 12.932892668439655]]]),
{
"landcover": 1,
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.55966542082108, 12.92704470371513],
[77.55993364172257, 12.926971505255315],
[77.55999801473892, 12.927159729822899],
[77.56005434112824, 12.927525721631364],
[77.55993095951355, 12.927606762602116],
[77.55952326374329, 12.92761460527531]]]),
{
"landcover": 1,
"system:index": "2"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.58913514122024, 12.908931210607625],
[77.58953210815444, 12.908910295247637],
[77.58983251556411, 12.908878922204362],
[77.59030458435073, 12.909004414353815],
[77.59054061874404, 12.908638395408474],
[77.59106633171096, 12.908648853100065],
[77.59147402748123, 12.909067160404927],
[77.5910019586946, 12.909443636380821],
[77.59061572059646, 12.909276313794859],
[77.58974668487564, 12.909224025463784],
[77.58923170074478, 12.909725992990666]]]),
{
"landcover": 1,
"system:index": "3"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.61573227314476, 12.921415857429206],
[77.61545332340721, 12.920662940987198],
[77.61613996891502, 12.921196257034753],
[77.61602195171837, 12.921363571638516],
[77.61619361309532, 12.921792314799008],
[77.61573227314476, 12.921666829072132]]]),
{
"landcover": 1,
"system:index": "4"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.62816320274716, 12.882943381724802],
[77.62788425300961, 12.882880629123182],
[77.62794862602597, 12.882587783441089],
[77.62773404930478, 12.882368148954866],
[77.62801299904233, 12.881949797019837],
[77.62857089851742, 12.881562820857978],
[77.63010456075271, 12.883191640487594],
[77.62838794698318, 12.883024300347486]]]),
{
"landcover": 1,
"system:index": "5"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.61221335121711, 12.9521074223386],
[77.61397288033088, 12.951396422136343],
[77.61474535652717, 12.952379274820865],
[77.61435911842902, 12.954094029794597],
[77.61392996498664, 12.954094029794597],
[77.6133291501673, 12.954554083998717],
[77.6129858274134, 12.953968560318724]]]),
{
"landcover": 1,
"system:index": "6"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.59805128761847, 12.95846451042281],
[77.5994245786341, 12.958307676320405],
[77.59967134186347, 12.959102301421517],
[77.59932801910956, 12.959583257487568],
[77.59893105217536, 12.960053757087966],
[77.59813711830695, 12.959896923986635]]]),
{
"landcover": 1,
"system:index": "7"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.63455221948686, 13.010374248303735],
[77.63442347345415, 13.009370717999056],
[77.6357109337813, 13.008743509496409],
[77.63618300256792, 13.009098927842672],
[77.63607847733172, 13.00986916075317],
[77.63577806992205, 13.010193217206663],
[77.63577806992205, 13.010465006163697],
[77.63474810166034, 13.010590447120325]]]),
{
"landcover": 1,
"system:index": "8"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.67136979766062, 13.015590361873178],
[77.6714556283491, 13.015355164770845],
[77.67200279898813, 13.015480603253204],
[77.67196524806192, 13.015809878967339],
[77.67188478179148, 13.015971903364512],
[77.67164874739817, 13.016008489504053],
[77.67131615348032, 13.015956223588763]]]),
{
"landcover": 1,
"system:index": "9"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.60055607512109, 12.937216602088446],
[77.60086721136682, 12.937132950114206],
[77.60142511084192, 12.937028385106942],
[77.60136073782556, 12.936359168022458],
[77.60157531454675, 12.936254602690832],
[77.60167187407129, 12.936526472461921],
[77.60184353544824, 12.937112037116247],
[77.60250872328393, 12.936965646081536],
[77.60322755529992, 12.936777428910661],
[77.60324901297204, 12.93708066761605],
[77.6023048753988, 12.937143406612513],
[77.60206884100549, 12.937310710525937],
[77.60194009497278, 12.937572122665994],
[77.60224050238244, 12.938889635681452],
[77.60199373915307, 12.938973287066492],
[77.60184353544824, 12.938241336496006],
[77.60156458571069, 12.937342079997205],
[77.60078138067834, 12.937436188387357]]]),
{
"landcover": 1,
"system:index": "10"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.66150849386902, 12.94914575556225],
[77.67097132727356, 12.949961321813811],
[77.67094986960144, 12.950525943039601],
[77.6614870361969, 12.949689466693222]]]),
{
"landcover": 1,
"system:index": "11"
})]),
largePark =
/* color: #0b4a8b */
/* shown: false */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[77.57171894317565, 13.00974571743543],
[77.57220174079833, 13.009421660397162],
[77.57245923286376, 13.009191684177605],
[77.5727167249292, 13.009557555335734],
[77.57275964027343, 13.010048867184636],
[77.57264162307678, 13.010634258755037],
[77.57257725006042, 13.011052394744919],
[77.57242704635559, 13.011125568470652],
[77.57201935058532, 13.01079105983387],
[77.57148290878234, 13.010498364406496]]]),
{
"landcover": 2,
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.57116564512269, 13.013013671615555],
[77.5708974242212, 13.012313298973975],
[77.57144459486024, 13.012114685476725],
[77.57174655647032, 13.012832946597658],
[77.5716714546179, 13.013679663736696],
[77.57112428397886, 13.013679663736696]]]),
{
"landcover": 2,
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.58499108728763, 12.949247564868747],
[77.58530222353336, 12.94904890097151],
[77.58524857935306, 12.948662028717099],
[77.5853987830579, 12.948170595527872],
[77.58580647882816, 12.94804512306893],
[77.58636437830326, 12.9488816049352],
[77.58607469972965, 12.949027988973114],
[77.58563481745121, 12.94949850851256]]]),
{
"landcover": 2,
"system:index": "2"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.52127227201635, 12.881502572157066],
[77.52011355772191, 12.87924345560438],
[77.52277430906469, 12.876775138310093],
[77.5245767535227, 12.877528186841339],
[77.5240188540476, 12.883426988708969],
[77.52187308683568, 12.883217813712905]]]),
{
"landcover": 2,
"system:index": "3"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.5910989048272, 12.973849327897769],
[77.59060537836847, 12.972448359695232],
[77.59021914027032, 12.97177923776914],
[77.58953249476251, 12.969646399617162],
[77.58923208735284, 12.9687681668278],
[77.59107744715509, 12.970022784149249],
[77.59116327784356, 12.971151934328653],
[77.59217178843316, 12.971193754607238],
[77.59281551859674, 12.97175832767994],
[77.59318029902276, 12.972343809512944],
[77.59223616144952, 12.972992019934718]]]),
{
"landcover": 2,
"system:index": "4"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.6027780366433, 12.977741635500964],
[77.60281022315148, 12.976978434405225],
[77.60407622580651, 12.976549786187062],
[77.60455902342919, 12.977908912140418],
[77.60427391550836, 12.978271735441785],
[77.60305082819757, 12.9786376521642]]]),
{
"landcover": 2,
"system:index": "5"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.53948055718051, 13.060069056320518],
[77.54076801750766, 13.058396839354431],
[77.54205547783481, 13.05929565738082],
[77.54291378471957, 13.06080064768324],
[77.54115426366407, 13.063026769886232],
[77.53853641960727, 13.062619165396288]]]),
{
"landcover": 2,
"system:index": "6"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.59158319925616, 12.895966653150252],
[77.59147591089557, 12.893644917177667],
[77.59269899820636, 12.893456667371083],
[77.59269899820636, 12.89577840509002]]]),
{
"landcover": 2,
"system:index": "7"
})]),
garden = /* color: #ffc82d */ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[77.58051928977152, 12.921638012882644],
[77.58051928977152, 12.921638012882644],
[77.58051928977152, 12.921638012882644],
[77.58051928977152, 12.921638012882644]]], null, false),
{
"landcover": 3,
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.58496639231821, 12.91928514355793],
[77.58513268927713, 12.919034169521753],
[77.58549210528513, 12.919295600803975],
[77.58540627459665, 12.919478602538726],
[77.58515951136728, 12.919713890286383],
[77.58493420581003, 12.919630232445938]]]),
{
"landcover": 3,
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.59550341650595, 12.92529082586494],
[77.59546586557974, 12.924935287789802],
[77.59614714666952, 12.924945744799238],
[77.59613641783346, 12.925322196847263]]]),
{
"landcover": 3,
"system:index": "2"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.59431788012137, 12.92495620180823],
[77.59510644957174, 12.924914373769615],
[77.59514400049795, 12.92530128285948],
[77.59436615988363, 12.92534833932951]]]),
{
"landcover": 3,
"system:index": "3"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.58106893991778, 12.915020807178204],
[77.58195943331073, 12.914958062621785],
[77.58203453516315, 12.91569008146616],
[77.58114710419804, 12.915747072340457]]]),
{
"landcover": 3,
"system:index": "4"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.58189215023758, 12.925264271803345],
[77.58189751465561, 12.92447476736639],
[77.58269681294205, 12.924453853307629],
[77.58268608410599, 12.925353156252465],
[77.5820584471965, 12.925311328280348]]]),
{
"landcover": 3,
"system:index": "5"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.56846373124301, 12.913512524240808],
[77.5687855963248, 12.913282459401634],
[77.56951515717685, 12.91307330936403],
[77.56950442834079, 12.913303374395756],
[77.56964390320957, 12.913721673910816],
[77.56910746140659, 12.913617099097701],
[77.5688392405051, 12.913993568220112],
[77.56890361352146, 12.914767419635023],
[77.56829206986606, 12.914223632404603]]]),
{
"landcover": 3,
"system:index": "6"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.5766396110571, 12.95210406839103],
[77.57675226383573, 12.951962914098635],
[77.5769078319586, 12.951926318528294],
[77.57703121357328, 12.952009965538327],
[77.57709558658964, 12.952153032144517],
[77.57709558658964, 12.952524215199473],
[77.57659133129484, 12.95259740615912]]]),
{
"landcover": 3,
"system:index": "7"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.56584841450672, 12.925263166983274],
[77.56563383778553, 12.92441614887677],
[77.56615955075245, 12.92430112150488],
[77.56631511887531, 12.925163825502247]]]),
{
"landcover": 3,
"system:index": "8"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.57480676422192, 12.941854345206552],
[77.57474239120556, 12.940798256612911],
[77.57671649704052, 12.940714605840054],
[77.57667358169628, 12.942338160476737],
[77.57476384887768, 12.942484548357596]]]),
{
"landcover": 3,
"system:index": "9"
})]),
isolatedGreen = /* color: #00ffff */ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[77.60793656057083, 12.939272671495173],
[77.60765224641526, 12.938326364701208],
[77.60823160356247, 12.938221800194288],
[77.6084890956279, 12.939042630394946],
[77.60844618028366, 12.939220389445568]]]),
{
"landcover": 4,
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.56368912846887, 12.957003080995905],
[77.56478883416497, 12.957065814977387],
[77.56514825017297, 12.957118093283214],
[77.56517507226312, 12.95723310551739],
[77.56489612252557, 12.957206966377932],
[77.56476737649285, 12.95718082723571],
[77.56363548428857, 12.95718082723571]]]),
{
"landcover": 4,
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.56614762047808, 12.958907604405269],
[77.56607373386241, 12.958714176008982],
[77.5664867940507, 12.958724631601802],
[77.56747384696818, 12.958766453968751],
[77.56793518691875, 12.958803048534051],
[77.5684126201234, 12.95878736514958],
[77.5684501710496, 12.958944198949833],
[77.56737192302562, 12.958912832197685],
[77.56666918426372, 12.958965110115738]]]),
{
"landcover": 4,
"system:index": "2"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.56851088472689, 12.962117252093533],
[77.56853770681704, 12.96190291527356],
[77.56853770681704, 12.96138014176794],
[77.5684035963663, 12.961181487547947],
[77.56838213869418, 12.960972377671425],
[77.56858062216128, 12.9607946341383],
[77.56829094358767, 12.960710990078788],
[77.56826412149752, 12.960836456157512],
[77.56805284969072, 12.961259903706358],
[77.5678704594777, 12.961348775322676],
[77.56767734042863, 12.96126513144937],
[77.56800993434648, 12.961056021643113],
[77.5680850361989, 12.960559385149299],
[77.56849273196916, 12.960564612907033],
[77.56864830009202, 12.96062211823478],
[77.56888433448533, 12.960616890478253],
[77.56897552959184, 12.960810317396321],
[77.56881996146898, 12.960862594915943],
[77.56896480075578, 12.96126513144937],
[77.56912573329667, 12.961834954779917],
[77.56897552959184, 12.961981331204726],
[77.56871267310838, 12.962357727330419],
[77.5684820031331, 12.962326361008344]]]),
{
"landcover": 4,
"system:index": "3"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.58580109726185, 12.90900320022248],
[77.58615514885182, 12.90908686162086],
[77.58623219979488, 12.909280328497383],
[77.58618392003261, 12.909526083503001],
[77.58595861447536, 12.909510397020505],
[77.58577622426235, 12.909494710537018]]]),
{
"landcover": 4,
"system:index": "4"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.5790603355235, 12.90459440164502],
[77.57903887785137, 12.904510738743422],
[77.57924540794552, 12.904461063882374],
[77.57926686561764, 12.904560413594627]]]),
{
"landcover": 4,
"system:index": "5"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.57874919927777, 12.904591787179776],
[77.57874383485974, 12.90440354560986],
[77.57878406799496, 12.904372172001098],
[77.57882966554821, 12.904515967675595],
[77.57878675020397, 12.90453688340318],
[77.57879479683102, 12.904591787179776],
[77.57881357229412, 12.904659763267412],
[77.57878675020397, 12.904696365768501],
[77.57870896614254, 12.904712052553036]]]),
{
"landcover": 4,
"system:index": "6"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.57269545353115, 12.905980064381774],
[77.57309242046536, 12.905964377676778],
[77.57305486953915, 12.906089871289156],
[77.57274909771145, 12.906152618071733],
[77.57244869030178, 12.90628334048485],
[77.57246478355587, 12.906126473580901]]]),
{
"landcover": 4,
"system:index": "7"
})]),
waterbody =
/* color: #d63000 */
/* shown: false */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[77.61944514570256, 12.985154431540222],
[77.61768561658879, 12.983774436127218],
[77.61614066419621, 12.982603524918357],
[77.61614066419621, 12.981767156391507],
[77.61678439435978, 12.981432608192684],
[77.61794310865422, 12.980888966409168],
[77.61858683881779, 12.980428960894367],
[77.61905890760441, 12.97938349064927],
[77.61957389173527, 12.978965301320063],
[77.6203892832758, 12.97988531691568],
[77.62068969068547, 12.98047077961271],
[77.61957389173527, 12.980888966409168],
[77.6187155848505, 12.98118169674804],
[77.6172564631464, 12.981808974884697],
[77.61699897108097, 12.982478069818768],
[77.61811477003117, 12.982478069818768],
[77.61957389173527, 12.982143522576896],
[77.62068969068547, 12.981307152502035],
[77.62163382825871, 12.981767156391507],
[77.62017470655461, 12.982812616610275]]]),
{
"landcover": 5,
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.61705279323951, 12.913604751308693],
[77.61610865566627, 12.909338061409425],
[77.61520743343726, 12.90766482980356],
[77.61829733822242, 12.907204689148696],
[77.61975645992652, 12.908585108572662],
[77.62035727474586, 12.911680566841879],
[77.61808276150123, 12.911513245753333]]]),
{
"landcover": 5,
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.57954478237525, 12.901180951571499],
[77.57864356014625, 12.899967820203194],
[77.57804274532691, 12.899173006806603],
[77.57902979824439, 12.89904750972368],
[77.57945895168677, 12.898169028380611],
[77.58031725857154, 12.898252693403306],
[77.58126139614478, 12.898880180181855],
[77.58104681942359, 12.901264615586943]]]),
{
"landcover": 5,
"system:index": "2"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.52197671633247, 12.940890936500946],
[77.52076435785774, 12.940368118904518],
[77.52090383272652, 12.939709367172293],
[77.521172053628, 12.939500239274341],
[77.52134371500496, 12.939918494894872],
[77.52155829172615, 12.939918494894872],
[77.52168703775887, 12.939677997998777],
[77.52201963167671, 12.939542064867965],
[77.5223414967585, 12.940420400713496],
[77.52243805628304, 12.940681809593913]]]),
{
"landcover": 5,
"system:index": "3"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.56002218990443, 12.952976210240205],
[77.55957157878993, 12.952286124244173],
[77.5592067983639, 12.951784242319086],
[77.55905659465907, 12.951177800310667],
[77.55978615551112, 12.951470565602486],
[77.56034405498622, 12.951470565602486],
[77.56098778514979, 12.951094153021254],
[77.56128819255946, 12.951073241194504],
[77.56120236187098, 12.951386918411366],
[77.56120236187098, 12.951888801136858],
[77.56081612377284, 12.95211883038148],
[77.5607732084286, 12.952620711632493],
[77.5607732084286, 12.9528507402013]]]),
{
"landcover": 5,
"system:index": "4"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.57648022441981, 12.934489610227581],
[77.57602961330531, 12.934217738236644],
[77.57594378261683, 12.933830842969495],
[77.57621200351832, 12.933297553915116],
[77.5764051225674, 12.93355897026068],
[77.57675917415736, 12.933736733219199],
[77.57697375087855, 12.933297553915116],
[77.57757456569789, 12.933768103139917],
[77.57716686992762, 12.934123628632285],
[77.57694156437037, 12.934416413951483]]]),
{
"landcover": 5,
"system:index": "5"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.67427425528479, 12.938407462236507],
[77.67119310727965, 12.936608947194635],
[77.6713647686566, 12.9337229308417],
[77.67406843534361, 12.933597451112467],
[77.67518423429381, 12.93619068602391]]]),
{
"landcover": 5,
"system:index": "6"
})]),
openarea =
/* color: #98ff00 */
/* shown: false */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[77.73264788022887, 12.900468596814665],
[77.73093126645934, 12.897707660746448],
[77.73350618711363, 12.896034351332165],
[77.73556612363707, 12.899380958970472]]]),
{
"landcover": 6,
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.66170496421522, 12.882563666756962],
[77.66091103034681, 12.88112035075511],
[77.66170496421522, 12.880095382168715],
[77.66247744041151, 12.880764749883824],
[77.66365761237806, 12.881475951121704],
[77.66479486900037, 12.882354491040031],
[77.66569609122938, 12.883023852719427],
[77.66417259650892, 12.882710089654891],
[77.66367907005018, 12.882249903116058],
[77.66247744041151, 12.882166232745451],
[77.66211265998548, 12.882647336994827],
[77.66217703300184, 12.883233027877445]]]),
{
"landcover": 6,
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.6221119302609, 12.873985908882297],
[77.6222192186215, 12.873839480886895],
[77.62215484560514, 12.873536165481486],
[77.62255181253934, 12.873504788004801],
[77.62271274508024, 12.87336881889381],
[77.62284149111295, 12.873536165481486],
[77.62251962603116, 12.873870858321686],
[77.62275566042447, 12.874236928104006],
[77.62271274508024, 12.874393814989942],
[77.62235869349027, 12.874111418524581]]]),
{
"landcover": 6,
"system:index": "2"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.61023930358279, 12.872511695027958],
[77.61100105094302, 12.87229205171123],
[77.61121562766421, 12.873139246301209],
[77.61040023612368, 12.873400725534772]]]),
{
"landcover": 6,
"system:index": "3"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.60768523145241, 12.871591723168615],
[77.60928382802528, 12.871246568032364],
[77.60929455686134, 12.871999633171612],
[77.60892977643532, 12.872334328063065],
[77.60818948674721, 12.872428460920776]]]),
{
"landcover": 6,
"system:index": "4"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.61582841802162, 12.88325350376569],
[77.61574258733314, 12.882981576048445],
[77.6160215370707, 12.882741024360186],
[77.61745920110268, 12.882019367909525],
[77.61758794713539, 12.882636436597595],
[77.61707296300453, 12.882772400680446],
[77.61690130162758, 12.882992034812252],
[77.61690130162758, 12.883232586259464],
[77.61610736775917, 12.88325350376569]]]),
{
"landcover": 6,
"system:index": "5"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.62236659510695, 12.889833138178536],
[77.62222175582015, 12.88934158923451],
[77.62270455344283, 12.889289296736871],
[77.6227903841313, 12.889686719445061],
[77.622554349738, 12.889723324136458],
[77.62261872275435, 12.890146892319073],
[77.62241487486922, 12.890173038479695]]]),
{
"landcover": 6,
"system:index": "6"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.62784366591536, 12.889618739289698],
[77.62814943774306, 12.889597822315109],
[77.62848203166091, 12.889691948687021],
[77.62850348933303, 12.889854055133474],
[77.62826745493972, 12.88997955682638],
[77.62794558985793, 12.889922035224945]]]),
{
"landcover": 6,
"system:index": "7"
})]),
golfCourse =
/* color: #546346 */
/* shown: false */
ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[77.5838022436437, 12.988757253656859],
[77.58417775290579, 12.988851342609596],
[77.58414556639761, 12.988924522881524],
[77.58373787062735, 12.988924522881524]]]),
{
"landcover": 7,
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.58739640372366, 12.98718909919782],
[77.58762170928091, 12.986959102378103],
[77.58767535346121, 12.987126372813568],
[77.5873320307073, 12.987325006309396]]]),
{
"landcover": 7,
"system:index": "1"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.64769243139946, 12.950758866624172],
[77.64769243139946, 12.9509993528292],
[77.64741348166191, 12.951229382895052],
[77.64748858351433, 12.950821602178308]]]),
{
"landcover": 7,
"system:index": "2"
})]),
wetland = /* color: #49ffb8 */ee.FeatureCollection(
[ee.Feature(
ee.Geometry.Polygon(
[[[77.70036294170843, 13.01687860196935],
[77.69993378826605, 13.015456970137205],
[77.70168258854376, 13.016408209986377]]]),
{
"landcover": 8,
"system:index": "0"
}),
ee.Feature(
ee.Geometry.Polygon(
[[[77.70662271981143, 13.047484527460087],
[77.70747566227817, 13.047437494117524],
[77.70758295063877, 13.04788692346974],
[77.70671391491794, 13.04793395672681]]]),
{
"landcover": 8,
"system:index": "1"
})]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
// Supervised Classification with Satellite Embeddings
// Classifying Urban Tree Cover
// Credit: Training samples are adapted from original work by
// Nishalini, Shweta, Raj Bhagat P, Janhavi Mane, Jyoti
// for the 'Urban True Tree Cover Project'
// ****************************************************
// Select a region
// ****************************************************
// Draw a polygon to define the region
// Save it as the variable 'geometry'
Map.centerObject(geometry, 12);
// Collect Training Samples
// ****************************************************
// Pick a year for classification
var year = 2024;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');
// Create a Sentinel-2 Compsite for the selected year
// for selecting training samples
var s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED');
var filteredS2 = s2
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
// Use the Cloud Score+ collection for cloud masking
var csPlus = ee.ImageCollection('GOOGLE/CLOUD_SCORE_PLUS/V1/S2_HARMONIZED');
var csPlusBands = csPlus.first().bandNames();
var filteredS2WithCs = filteredS2.linkCollection(csPlus, csPlusBands);
function maskLowQA(image) {
var qaBand = 'cs';
var clearThreshold = 0.6;
var mask = image.select(qaBand).gte(clearThreshold);
return image.updateMask(mask);
}
var filteredS2Masked = filteredS2WithCs
.map(maskLowQA)
.select('B.*');
// Create a median composite of cloud-masked images
var composite = filteredS2Masked.median();
// Display the input composite in false color
// that helps distinguish between
// water, vegetation and built surfaces
var rgbVis = {min: 300, max: 4000, bands: ['B4', 'B3', 'B2']};
Map.addLayer(composite.clip(geometry), rgbVis, 'S2 Composite (RGB)', false);
// Merge the collected training samples
var gcps = built.merge(largePark).merge(garden)
.merge(isolatedGreen).merge(waterbody)
.merge(openarea).merge(golfCourse).merge(wetland);
// Train a Classifier
// ****************************************************
// Sample Embedding Vectors
var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
var embeddingsFiltered = embeddings
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
var embeddingsImage = embeddingsFiltered.mosaic();
// Take mean values for each polygon
var training = embeddingsImage.reduceRegions({
collection: gcps,
reducer: ee.Reducer.mean(),
scale: 10,
tileScale: 16
});
// Some small polygons end up with null values
training = training.filter(ee.Filter.notNull(['A00']));
// Train a classifier.
var classifier = ee.Classifier.smileKNN().train({
features: training,
classProperty: 'landcover',
inputProperties: embeddingsImage.bandNames()
});
// Classify the Satellite Embedding Mosaic
// ****************************************************
var classified = embeddingsImage.classify(classifier);
// Visualize the classification
// ****************************************************
var palette = ['ff0000','129b0a','b9ff14','f7ae08','21e0ff','faff08', '546346', '#49ffb8'];
var viz_class = {
'min':1,
'max':8,
'palette': palette
};
Map.addLayer(classified.clip(geometry), viz_class, 'Classified');
// Add a Legend
var legend = ui.Panel({style: {position: 'middle-right', padding: '8px 15px'}});
var makeRow = function(color, name) {
var colorBox = ui.Label({
style: {color: '#ffffff',
backgroundColor: color,
padding: '10px',
margin: '0 0 4px 0',
}
});
var description = ui.Label({
value: name,
style: {
margin: '0px 0 4px 6px',
}
});
return ui.Panel({
widgets: [colorBox, description],
layout: ui.Panel.Layout.Flow('horizontal')}
)};
var title = ui.Label({
value: 'Legend',
style: {fontWeight: 'bold',
fontSize: '16px',
margin: '0px 0 4px 0px'}});
legend.add(title);
var palette = ['ff0000','129b0a','b9ff14','f7ae08','21e0ff','faff08'];
var classes = ['Built', 'National Parks', 'Garden', 'Isolated Green',
'Water', 'Open Area', 'Golf Course', 'Wetland'];
legend.add(makeRow('#ff0000','Built'));
legend.add(makeRow('#129b0a','Large Park'));
legend.add(makeRow('#b9ff14','Garden'));
legend.add(makeRow('#f7ae08','Isolated Green'));
legend.add(makeRow('#546346','Golf Course'));
legend.add(makeRow('#21e0ff','Water'));
legend.add(makeRow('#49ffb8','Wetland'));
legend.add(makeRow('#faff08','Open Area'));
Map.add(legend);
The course material (text, images, presentation, videos) is licensed under a Creative Commons Attribution 4.0 International License.
The code (scripts, Jupyter notebooks etc.) is licensed under the MIT License. For a copy, see https://opensource.org/licenses/MIT
Kindly give appropriate credit to the original author as below:
Copyright © 2025 Ujaval Gandhi www.spatialthoughts.com
You can cite the course materials as follows
If you want to report any issues with this page, please comment below.