This 5-hour hands-on workshop is designed to help participants learn the basics of the Google Earth Engine platform. This beginner-friendly class covers a range of topics to help participants get comfortable with the Code Editor environment and the Google Earth Engine API to implement remote sensing workflows. During the workshop, you will learn how to load, filter, analyze, and export datasets from the Earth Engine Data Catalog. The workshop also covers Map/Reduce programming concepts so you can scale your analysis to large regions and work with time-series data.
Pre-requisites:
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 course material and exercises are in the form of Earth Engine scripts shared via a code repository.
users/ujavalgandhi/GEE-Introduction
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.
The course is accompanied by a set of professionally edited videos recorded during Geo For Good 2023 conference and available via the Google Earth YouTube channel. Access the YouTube Playlist ↗
print('Hello World');
// Variables
var city = 'Bengaluru';
var country = 'India';
print(city, country);
var population = 8400000;
print(population);
// List
var majorCities = ['Mumbai', 'Delhi', 'Chennai', 'Kolkata'];
print(majorCities);
// Dictionary
var cityData = {
'city': city,
'population': 8400000,
'elevation': 930
};
print(cityData);
// Function
var greet = function(name) {
return 'Hello ' + name;
};
print(greet('World'));
// This is a comment
/**
* Function to mask clouds using the Sentinel-2 QA band
* @param {ee.Image} image Sentinel-2 image
* @return {ee.Image} cloud masked Sentinel-2 image
*/
function maskS2clouds(image) {
var qa = image.select('QA60');
// Bits 10 and 11 are clouds and cirrus, respectively.
var cloudBitMask = 1 << 10;
var cirrusBitMask = 1 << 11;
// Both flags should be set to zero, indicating clear conditions.
var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
.and(qa.bitwiseAnd(cirrusBitMask).eq(0));
return image.updateMask(mask).divide(10000);
}
// Map the function over a month of data and take the median.
// Load Sentinel-2 TOA reflectance data (adjusted for processing changes
// that occurred after 2022-01-25).
var dataset = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')
.filterDate('2022-01-01', '2022-01-31')
// Pre-filter to get less cloudy granules.
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
.map(maskS2clouds);
var rgbVis = {
min: 0.0,
max: 0.3,
bands: ['B4', 'B3', 'B2'],
};
Map.setCenter(-9.1695, 38.6917, 12);
Map.addLayer(dataset.median(), rgbVis, 'RGB');
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var geometry = /* color: #d63000 */ee.Geometry.Point([77.60412933051538, 12.952912912328241]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
Map.centerObject(geometry, 10)
var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');
// Filter by metadata
var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30));
// Filter by date
var filtered = s2.filter(ee.Filter.date('2019-01-01', '2020-01-01'));
// Filter by location
var filtered = s2.filter(ee.Filter.bounds(geometry));
// Let's apply all the 3 filters together on the collection
// First apply metadata fileter
var filtered1 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30));
// Apply date filter on the results
var filtered2 = filtered1.filter(
ee.Filter.date('2019-01-01', '2020-01-01'));
// Lastly apply the location filter
var filtered3 = filtered2.filter(ee.Filter.bounds(geometry));
// Instead of applying filters one after the other, we can 'chain' them
// Use the . notation to apply all the filters together
var filtered = s2
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
print(filtered.size());
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var geometry = /* color: #98ff00 */ee.Geometry.Point([77.60412933051538, 12.952912912328241]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
Map.centerObject(geometry, 10);
var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');
var filtered = s2
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
print(filtered.size());
// Exercise
// Delete the 'geometry' import
// Add a point at your chosen location
// Change the filter to find images from September 2023
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var geometry = /* color: #0B4A8B */ee.Geometry.Point([77.60412933051538, 12.952912912328241]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');
var rgbVis = {
min: 0.0,
max: 3000,
bands: ['B4', 'B3', 'B2'],
};
var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
var mosaic = filtered.mosaic();
var medianComposite = filtered.median();
Map.addLayer(filtered, rgbVis, 'Filtered Collection');
Map.addLayer(mosaic, rgbVis, 'Mosaic');
Map.addLayer(medianComposite, rgbVis, 'Median Composite');
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var geometry = /* color: #ffc82d */ee.Geometry.Point([77.60412933051538, 12.952912912328241]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
Map.centerObject(geometry, 10);
var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');
var rgbVis = {
min: 0.0,
max: 3000,
bands: ['B4', 'B3', 'B2'],
};
var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
var image2019 = filtered.median();
Map.addLayer(image2019, rgbVis, '2019');
// Exercise
// Delete the 'geometry' import
// Add a point at your chosen location
// Create a median composite for both 2019 and 2020
// Display both on the map
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2");
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filtered = admin2
.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))
.filter(ee.Filter.eq('ADM2_NAME', 'Bangalore Urban'));
Map.centerObject(filtered)
Map.addLayer(filtered, {'color': 'red'}, 'Selected Admin2');
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2");
/***** End of imports. If edited, may not auto-convert in the playground. *****/
Map.addLayer(admin2, {}, 'All Admin2');
// Exercise
// Inspect and find the name of ADM1_NAME and ADM2_NAME properties
// of your chosen Admin2 region
// Apply filters and display the chosen Admin2 region in 'blue' color
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2");
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredAdmin2 = admin2
.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))
.filter(ee.Filter.eq('ADM2_NAME', 'Bangalore Urban'));
var geometry = filteredAdmin2.geometry();
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
var image = filteredS2.median();
var clipped = image.clip(geometry);
var rgbVis = {
min: 0.0,
max: 3000,
bands: ['B4', 'B3', 'B2'],
};
Map.centerObject(geometry);
Map.addLayer(clipped, rgbVis, 'Clipped Composite');
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2");
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredAdmin2 = admin2
.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))
.filter(ee.Filter.eq('ADM2_NAME', 'Bangalore Urban'));
var geometry = filteredAdmin2.geometry();
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
var image = filteredS2.median();
var clipped = image.clip(geometry);
var rgbVis = {
min: 0.0,
max: 3000,
bands: ['B4', 'B3', 'B2'],
};
Map.centerObject(geometry)
Map.addLayer(clipped, rgbVis, 'Clipped Composite');
// Exercise
// Change the filters to select the Admin2 region of your choice
// Display the clipped composite
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2");
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredAdmin2 = admin2
.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))
.filter(ee.Filter.eq('ADM2_NAME', 'Bangalore Urban'));
var geometry = filteredAdmin2.geometry();
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
var image = filteredS2.median();
var clipped = image.clip(geometry);
var rgbVis = {
min: 0.0,
max: 3000,
bands: ['B4', 'B3', 'B2'],
};
Map.centerObject(geometry)
Map.addLayer(clipped, rgbVis, 'Clipped Composite');
var exportImage = clipped.select(['B4', 'B3', 'B2']);
Export.image.toDrive({
image: exportImage,
description: 'S2_Composite_Raw',
folder: 'earthengine',
fileNamePrefix: 's2_composite_raw',
region: geometry,
scale: 10,
maxPixels: 1e9
});
// Rather than exporting raw bands, we can apply a rendered image
// visualize() function allows you to apply the same parameters
// that are used in earth engine which exports a 3-band RGB image
print(clipped);
var visualized = clipped.visualize(rgbVis);
print(visualized);
// Now the 'visualized' image is RGB image, no need to give visParams
Map.addLayer(visualized, {}, 'Visualized Image');
Export.image.toDrive({
image: visualized,
description: 'S2_Composite_Visualized',
folder: 'earthengine',
fileNamePrefix: 'bs2_composite_visualized',
region: geometry,
scale: 10,
maxPixels: 1e9
});
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2");
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredAdmin2 = admin2
.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))
.filter(ee.Filter.eq('ADM2_NAME', 'Bangalore Urban'));
var geometry = filteredAdmin2.geometry();
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
var image = filteredS2.median();
var clipped = image.clip(geometry);
var rgbVis = {
min: 0.0,
max: 3000,
bands: ['B4', 'B3', 'B2'],
};
Map.centerObject(geometry)
Map.addLayer(clipped, rgbVis, 'Clipped Composite');
var exportImage = clipped.select(['B4', 'B3', 'B2']);
Export.image.toDrive({
image: exportImage,
description: 'S2_Composite',
folder: 'earthengine',
fileNamePrefix: 's2_composite',
region: geometry,
scale: 10,
maxPixels: 1e9
});
// Exercise
// Change the filters to select the Admin2 region of your choice
// Export the composite image
Take the short online quiz to recap your understanding of Part-1 of the workshop.
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
geometry = /* color: #d63000 */ee.Geometry.Point([77.60412933051538, 12.952912912328241]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
// Sort the collection and pick the least cloudy image
var filteredS2Sorted = filteredS2.sort('CLOUDY_PIXEL_PERCENTAGE');
var image = filteredS2Sorted.first()
// Calculate Normalized Difference Vegetation Index (NDVI)
// 'NIR' (B8) and 'RED' (B4)
var ndvi = image.normalizedDifference(['B8', 'B4']).rename(['ndvi']);
// Calculate Modified Normalized Difference Water Index (MNDWI)
// 'GREEN' (B3) and 'SWIR1' (B11)
var mndwi = image.normalizedDifference(['B3', 'B11']).rename(['mndwi']);
// Calculate Soil-adjusted Vegetation Index (SAVI)
// 1.5 * ((NIR - RED) / (NIR + RED + 0.5))
// For more complex indices, you can use the expression() function
// Note:
// For the SAVI formula, the pixel values need to converted to reflectances
// Multiplyng the pixel values by 'scale' gives us the reflectance value
// The scale value is 0.0001 for Sentinel-2 dataset
var savi = image.expression(
'1.5 * ((NIR - RED) / (NIR + RED + 0.5))', {
'NIR': image.select('B8').multiply(0.0001),
'RED': image.select('B4').multiply(0.0001),
}).rename('savi');
var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']};
var ndviVis = {min:0, max:1, palette: ['white', 'green']};
var ndwiVis = {min:0, max:0.5, palette: ['white', 'blue']};
Map.centerObject(geometry, 10)
Map.addLayer(image, rgbVis, 'Image');
Map.addLayer(ndvi, ndviVis, 'NDVI');
Map.addLayer(mndwi, ndwiVis, 'MNDWI');
Map.addLayer(savi, ndviVis, 'SAVI');
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
geometry = /* color: #d63000 */ee.Geometry.Point([77.60412933051538, 12.952912912328241]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
// Sort the collection and pick the least cloudy image
var filteredS2Sorted = filteredS2.sort('CLOUDY_PIXEL_PERCENTAGE');
var image = filteredS2Sorted.first()
Map.centerObject(geometry, 10)
var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']};
Map.addLayer(image, rgbVis, 'Image');
// Exercise
// Exercise
// Delete the 'geometry' import
// Add a point at your chosen location
// Calculate the Normalized Difference Built-Up Index (NDBI) for the image
// Hint: NDBI = (SWIR1 – NIR) / (SWIR1 + NIR)
// Visualize the index image using a 'red' palette
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2");
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredAdmin2 = admin2
.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))
.filter(ee.Filter.eq('ADM2_NAME', 'Bangalore Urban'));
var geometry = filteredAdmin2.geometry();
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry))
.select('B.*');
print('Number of images', filteredS2.size())
// Write a function that computes NDVI for an image and adds it as a band
function addNDVI(image) {
var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
return image.addBands(ndvi);
}
// Map the function over the collection
var withNdvi = filteredS2.map(addNDVI);
// Create a composite and visualize
var composite = withNdvi.median();
var ndviComposite = composite.select('ndvi')
var palette = ['#a6611a','#dfc27d','#f5f5f5','#80cdc1','#018571'];
var ndviVis = {min:0, max:0.5, palette: palette };
Map.centerObject(geometry, 10);
Map.addLayer(geometry, {}, 'Selected Region');
Map.addLayer(ndviComposite.clip(geometry), ndviVis, 'ndvi');
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2");
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredAdmin2 = admin2
.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))
.filter(ee.Filter.eq('ADM2_NAME', 'Bangalore Urban'));
var geometry = filteredAdmin2.geometry();
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry))
.select('B.*');
// This function calculates both NDVI and NDWI indices
// and returns an image with 2 new bands added to the original image.
function addIndices(image) {
var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
var ndwi = image.normalizedDifference(['B3', 'B8']).rename('ndwi');
return image.addBands(ndvi).addBands(ndwi);
}
// Map the function over the collection
var withIndices = filteredS2.map(addIndices);
// Composite
var composite = withIndices.median();
print(composite);
var ndviComposite = composite.select('ndvi')
var palette = ['#a6611a','#dfc27d','#f5f5f5','#80cdc1','#018571'];
var ndviVis = {min:0, max:0.5, palette: palette };
Map.centerObject(geometry, 10);
Map.addLayer(geometry, {}, 'Selected Region');
Map.addLayer(ndviComposite.clip(geometry), ndviVis, 'ndvi');
// Exercise
// Change the filters to select the Admin2 region of your choice
// Extract the 'ndwi' band and display a NDWI map
// use the palette ['white', 'blue']
// Hint: Use .select() function to select a band
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2");
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredAdmin2 = admin2
.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))
.filter(ee.Filter.eq('ADM2_NAME', 'Bangalore Urban'));
var geometry = filteredAdmin2.geometry();
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry))
.select('B.*');
print('Number of images', filteredS2.size())
// Write a function that computes NDVI for an image and adds it as a band
function addNDVI(image) {
var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
return image.addBands(ndvi);
}
// Map the function over the collection
var withNdvi = filteredS2.map(addNDVI);
// Apply a Median reducer
var medianComposite = withNdvi
.reduce(ee.Reducer.median()).regexpRename('_median', '');
print(medianComposite);
// Apply a Percentile Reducer
var percentileComposite = withNdvi
.reduce(ee.Reducer.percentile([25])).regexpRename('_p25', '');
print(percentileComposite);
var rgbVis = {min: 0, max: 3000, bands: ['B4', 'B3', 'B2']};
Map.centerObject(geometry);
Map.addLayer(geometry, {}, 'Selected Region');
Map.addLayer(medianComposite.clip(geometry),
rgbVis, 'Median Composite');
Map.addLayer(percentileComposite.clip(geometry),
rgbVis, '25th-Percentile Composite');
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2");
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredAdmin2 = admin2
.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))
.filter(ee.Filter.eq('ADM2_NAME', 'Bangalore Urban'));
var geometry = filteredAdmin2.geometry();
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry))
.select('B.*');
print('Number of images', filteredS2.size())
// Write a function that computes NDVI for an image and adds it as a band
function addNDVI(image) {
var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
return image.addBands(ndvi);
}
// Map the function over the collection
var withNdvi = filteredS2.map(addNDVI);
// Apply a Median reducer
var medianComposite = withNdvi
.reduce(ee.Reducer.median()).regexpRename('_median', '')
.clip(geometry);
var ndviComposite = medianComposite.select('ndvi');
var palette = ['#a6611a','#dfc27d','#f5f5f5','#80cdc1','#018571'];
var ndviVis = {min:0, max:0.5, palette: palette };
Map.addLayer(geometry, {}, 'Selected Region');
Map.addLayer(ndviComposite.clip(geometry), ndviVis, 'ndvi');
// Exercise
// Change the filters to select the Admin2 region of your choice
// Compute a Maximum NDVI Composite and add it to the Map
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
geometry = /* color: #d63000 */ee.Geometry.Polygon(
[[[82.60642647743225, 27.16350437805251],
[82.60984897613525, 27.1618529901377],
[82.61088967323303, 27.163695288375266],
[82.60757446289062, 27.16517483230927]]]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
// Sort the collection and pick the least cloudy image
var filteredS2Sorted = filteredS2.sort('CLOUDY_PIXEL_PERCENTAGE');
var image = filteredS2Sorted.first().select('B.*')
var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']};
Map.centerObject(geometry);
Map.addLayer(image, rgbVis, 'Image');
// If we want to compute the average value in each band,
// we can use reduceRegion instead
var stats = image.reduceRegion({
reducer: ee.Reducer.mean(),
geometry: geometry,
scale: 10,
maxPixels: 1e10
});
print('Average values of image bands in geometry', stats);
// Result of reduceRegion is a dictionary.
// We can extract the values using .get() function
print('Average value of B4 in geometry', stats.get('B4'));
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
geometry = /* color: #d63000 */ee.Geometry.Polygon(
[[[82.60642647743225, 27.16350437805251],
[82.60984897613525, 27.1618529901377],
[82.61088967323303, 27.163695288375266],
[82.60757446289062, 27.16517483230927]]]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
// Sort the collection and pick the least cloudy image
var filteredS2Sorted = filteredS2.sort('CLOUDY_PIXEL_PERCENTAGE');
var image = filteredS2Sorted.first().select('B.*')
// If we want to compute the average value in each band,
// we can use reduceRegion instead
var stats = image.reduceRegion({
reducer: ee.Reducer.mean(),
geometry: geometry,
scale: 10,
maxPixels: 1e10
});
print('Average values of image bands in geometry', stats);
// Calculate NDVI
var ndvi = image.normalizedDifference(['B8', 'B4']).rename(['ndvi']);
var palette = ['#a6611a','#dfc27d','#f5f5f5','#80cdc1','#018571'];
var ndviVis = {min:0, max:0.5, palette: palette };
Map.centerObject(geometry);
Map.addLayer(ndvi, ndviVis, 'NDVI Image');
// Exercise
// Delete the 'geometry'
// Draw a polygon over any farm of your choice
// Calculate the 'average' NDVI in the farm from the 'ndvi' image
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
geometry = /* color: #d63000 */ee.Geometry.Polygon(
[[[82.60642647743225, 27.16350437805251],
[82.60984897613525, 27.1618529901377],
[82.61088967323303, 27.163695288375266],
[82.60757446289062, 27.16517483230927]]]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
// Write a function for Cloud masking
function maskS2clouds(image) {
var qa = image.select('QA60');
var cloudBitMask = 1 << 10;
var cirrusBitMask = 1 << 11;
var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(
qa.bitwiseAnd(cirrusBitMask).eq(0));
return image.updateMask(mask)
.select('B.*')
.copyProperties(image, ['system:time_start']);
}
// Write a function that computes NDVI for an image and adds it as a band
function addNDVI(image) {
var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
return image.addBands(ndvi);
}
// Map the function over the collection
var withNdvi = filteredS2
.map(maskS2clouds)
.map(addNDVI);
// Display a time-series chart
var chart = ui.Chart.image.series({
imageCollection: withNdvi.select('ndvi'),
region: geometry,
reducer: ee.Reducer.mean(),
scale: 10
}).setOptions({
title: 'NDVI Time Series',
vAxis: {title: 'NDVI', viewWindow: {min:0, max:1}},
hAxis: {title: '', format: 'YYYY-MMM'},
lineWidth: 1,
pointSize: 2,
interpolateNulls: true
})
print(chart);
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED"),
geometry = /* color: #d63000 */ee.Geometry.Polygon(
[[[82.60642647743225, 27.16350437805251],
[82.60984897613525, 27.1618529901377],
[82.61088967323303, 27.163695288375266],
[82.60757446289062, 27.16517483230927]]]);
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var filteredS2 = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
.filter(ee.Filter.date('2019-01-01', '2020-01-01'))
.filter(ee.Filter.bounds(geometry));
// Write a function for Cloud masking
function maskS2clouds(image) {
var qa = image.select('QA60');
var cloudBitMask = 1 << 10;
var cirrusBitMask = 1 << 11;
var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(
qa.bitwiseAnd(cirrusBitMask).eq(0));
return image.updateMask(mask)
.select('B.*')
.copyProperties(image, ['system:time_start']);
}
// Write a function that computes NDVI for an image and adds it as a band
function addNDVI(image) {
var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
return image.addBands(ndvi);
}
// Map the function over the collection
var withNdvi = filteredS2
.map(maskS2clouds)
.map(addNDVI);
// Display a time-series chart
var chart = ui.Chart.image.series({
imageCollection: withNdvi.select('ndvi'),
region: geometry,
reducer: ee.Reducer.mean(),
scale: 10
}).setOptions({
title: 'NDVI Time Series',
vAxis: {title: 'NDVI', viewWindow: {min:0, max:1}},
hAxis: {title: '', format: 'YYYY-MMM'},
lineWidth: 1,
pointSize: 2,
interpolateNulls: true
})
print(chart);
// Exercise
// Delete the 'geometry'
// Draw a polygon over any farm of oyur choice
// Print the NDVI Time-Series chart.
Take the short online quiz to recap your understanding of Part-2 of the workshop.
The course material (text, images, presentation, videos) is licensed under a Creative Commons Attribution 4.0 International License.
The code (scripts, Jupyter notebooks) 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 © 2023 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.