├── 01_GEE_RS_EXTRACTDATA.ipynb ├── 10 - Reductores.txt ├── 11 - Series de Tiempo Exportar a CSV.txt ├── 11 - Series de Tiempo.txt ├── 12 - Clasificacion SVM.txt ├── 13 - Clasificacion RF y Matriz de Confusion.txt ├── 14 - Aplicacion GEE.txt ├── 15 - Comparacion Visual de Imagenes Años ├── 2 - Visualizacion Imagen L9.txt ├── 3 - Filtrar imagen Sentinel-2.txt ├── 4 - Mosaico y Mediana Sentinel-2.txt ├── 5 - Vectores FeatureCollections.txt ├── 7 - Clip Imagen Sentinel-2.txt ├── 8 - Exportar imágenes a Google Drive.txt ├── 9 - NDVI.txt ├── Part 1 - Remote Sensing with GEE - Spanish.pdf ├── Part 2 - Remote Sensing with GEE - Spanish.pdf ├── README.md ├── TRATAMENTO DADOS ESPACIAIS GEE - Portuguese.pdf └── Using GEE - English.pdf /10 - Reductores.txt: -------------------------------------------------------------------------------- 1 | //Forest loss between 2000 to 2020 2 | var year = 20; //Choose the year between 2000 (00) to 2020 (20) 3 | var country = 'EC'; //Choose the country initials [Two-letter FIPS country code](https://en.wikipedia.org/wiki/List_of_FIPS_country_codes 4 | 5 | // Load country features from Large Scale International Boundary (LSIB) dataset. 6 | var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017'); 7 | var selected = countries.filter(ee.Filter.eq('country_co', ee.String(country))); 8 | 9 | // Make the clip boundary. 10 | var clipToCol = function(image){ 11 | return image.clip(selected); 12 | }; 13 | 14 | var gfc2020 = ee.Image('UMD/hansen/global_forest_change_2020_v1_8'); 15 | 16 | // Canopy loss during the selected year 17 | var loss = gfc2020.select(['lossyear']).eq(year).clip(selected) //ClipGeometry can any geometry or feature or shapfile 18 | 19 | // Get the forest loss in square kilometers. 20 | var areaImage = loss.multiply(ee.Image.pixelArea()).divide(1000000); 21 | 22 | var stats = areaImage.reduceRegion({ 23 | reducer: ee.Reducer.sum(), 24 | geometry: selected, 25 | scale: 30, 26 | maxPixels: 1e9 27 | }); 28 | print('Pixels representing loss during the year choosed: ', stats.get('lossyear'), 'square kilometers in 20', year); 29 | 30 | // Showing the map result 31 | var losscolors = { 32 | bands: ['lossyear'], 33 | min: 0, 34 | max: 20, 35 | palette: ['black', 'green'] 36 | }; 37 | Map.addLayer(loss, losscolors,'tree cover'); 38 | Map.centerObject(selected,7); -------------------------------------------------------------------------------- /11 - Series de Tiempo Exportar a CSV.txt: -------------------------------------------------------------------------------- 1 | var s2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED"); 2 | var geometry = ee.Geometry.Polygon([[ 3 | [82.60642647743225, 27.16350437805251], 4 | [82.60984897613525, 27.1618529901377], 5 | [82.61088967323303, 27.163695288375266], 6 | [82.60757446289062, 27.16517483230927] 7 | ]]); 8 | Map.addLayer(geometry, {color: 'red'}, 'Farm') 9 | Map.centerObject(geometry) 10 | var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']}; 11 | 12 | var filtered = s2.filter(ee.Filter.date('2017-01-01', '2022-01-01')) 13 | .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) 14 | .filter(ee.Filter.bounds(geometry)) 15 | 16 | // Write a function for Cloud masking 17 | function maskS2clouds(image) { 18 | var qa = image.select('QA60') 19 | var cloudBitMask = 1 << 10; 20 | var cirrusBitMask = 1 << 11; 21 | var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and( 22 | qa.bitwiseAnd(cirrusBitMask).eq(0)) 23 | return image.updateMask(mask)//.divide(10000) 24 | .select("B.*") 25 | .copyProperties(image, ["system:time_start"]) 26 | } 27 | 28 | var filtered = filtered.map(maskS2clouds) 29 | // Write a function that computes NDVI for an image and adds it as a band 30 | function addNDVI(image) { 31 | var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi'); 32 | return image.addBands(ndvi); 33 | } 34 | 35 | // Map the function over the collection 36 | var withNdvi = filtered.map(addNDVI); 37 | 38 | // Display a time-series chart 39 | var chart = ui.Chart.image.series({ 40 | imageCollection: withNdvi.select('ndvi'), 41 | region: geometry, 42 | reducer: ee.Reducer.median(), 43 | scale: 10 44 | }).setOptions({ 45 | lineWidth: 1, 46 | title: 'Serie de Tiempo NDVI', 47 | interpolateNulls: true, 48 | vAxis: {title: 'NDVI'}, 49 | hAxis: {title: '', format: 'YYYY-MMM'} 50 | }) 51 | print(chart); 52 | 53 | var withNDVI = withNdvi.select('ndvi') 54 | var withNDVI = ee.ImageCollection(withNDVI).toBands(); 55 | 56 | // Get Zonal Statistics 57 | var reduced = withNDVI.reduceRegions({ 58 | collection: geometry, 59 | reducer: ee.Reducer.mean(), 60 | scale: 100, 61 | }); 62 | print(reduced); 63 | 64 | // the resulting mean is a FeatureCollection 65 | // so you can export it as a table 66 | Export.table.toDrive({ 67 | collection: reduced, 68 | description: 'NDVIpolygons', 69 | fileNamePrefix: 'NDVIpolygons', 70 | fileFormat: 'CSV' 71 | }) -------------------------------------------------------------------------------- /11 - Series de Tiempo.txt: -------------------------------------------------------------------------------- 1 | var s2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED"); 2 | var geometry = ee.Geometry.Polygon([[ 3 | [82.60642647743225, 27.16350437805251], 4 | [82.60984897613525, 27.1618529901377], 5 | [82.61088967323303, 27.163695288375266], 6 | [82.60757446289062, 27.16517483230927] 7 | ]]); 8 | Map.addLayer(geometry, {color: 'red'}, 'Farm') 9 | Map.centerObject(geometry) 10 | var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']}; 11 | 12 | var filtered = s2.filter(ee.Filter.date('2017-01-01', '2022-01-01')) 13 | .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) 14 | .filter(ee.Filter.bounds(geometry)) 15 | 16 | // Write a function for Cloud masking 17 | function maskS2clouds(image) { 18 | var qa = image.select('QA60') 19 | var cloudBitMask = 1 << 10; 20 | var cirrusBitMask = 1 << 11; 21 | var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and( 22 | qa.bitwiseAnd(cirrusBitMask).eq(0)) 23 | return image.updateMask(mask)//.divide(10000) 24 | .select("B.*") 25 | .copyProperties(image, ["system:time_start"]) 26 | } 27 | 28 | var filtered = filtered.map(maskS2clouds) 29 | // Write a function that computes NDVI for an image and adds it as a band 30 | function addNDVI(image) { 31 | var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi'); 32 | return image.addBands(ndvi); 33 | } 34 | 35 | // Map the function over the collection 36 | var withNdvi = filtered.map(addNDVI); 37 | 38 | 39 | // Display a time-series chart 40 | var chart = ui.Chart.image.series({ 41 | imageCollection: withNdvi.select('ndvi'), 42 | region: geometry, 43 | reducer: ee.Reducer.median(), 44 | scale: 10 45 | }).setOptions({ 46 | lineWidth: 1, 47 | title: 'Serie de Tiempo NDVI', 48 | interpolateNulls: true, 49 | vAxis: {title: 'NDVI'}, 50 | hAxis: {title: '', format: 'YYYY-MMM'} 51 | }) 52 | print(chart); -------------------------------------------------------------------------------- /12 - Clasificacion SVM.txt: -------------------------------------------------------------------------------- 1 | var country = 'CH'; 2 | var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017'); 3 | var table = countries.filter(ee.Filter.eq('country_co', ee.String(country))); 4 | 5 | // Make the clip boundary. 6 | var clipToCol = function(image){ 7 | return image.clip(table); 8 | }; 9 | 10 | // Make a cloud-free Landsat 7 TOA composite (from raw imagery). 11 | var l8 = ee.ImageCollection('LANDSAT/LE07/C01/T1') 12 | .map(clipToCol); 13 | 14 | var image = ee.Algorithms.Landsat.simpleComposite({ 15 | collection: l8.filterDate('2000-01-01', '2000-12-31'), 16 | asFloat: true 17 | }); 18 | 19 | // Use these bands for prediction. We only used the multiespectral bands 20 | var bands = ['B1','B2', 'B3', 'B4', 'B5', 'B7']; 21 | 22 | // Manually created polygons. Only I add two polygons to each category forest or non-forest 23 | var forest1 = ee.Geometry.Rectangle(106.024466, 28.470375,106.114408, 28.385354); 24 | var forest2 = ee.Geometry.Rectangle(123.926517, 52.129826, 124.431256, 51.743099); 25 | var nonForest1 = ee.Geometry.Rectangle( 82.564232,40.174726, 85.900993, 38.822149); 26 | var nonForest2 = ee.Geometry.Rectangle(100.003374,37.005547,100.315863,36.751742); 27 | 28 | // Make a FeatureCollection from the hand-made geometries. 29 | var polygons = ee.FeatureCollection([ 30 | ee.Feature(nonForest1, {'class': 0}), 31 | ee.Feature(nonForest2, {'class': 0}), 32 | ee.Feature(forest1, {'class': 1}), 33 | ee.Feature(forest2, {'class': 1}), 34 | ]); 35 | 36 | // Get the values for all pixels in each polygon in the training. 37 | var training = image.sampleRegions({ 38 | // Get the sample from the polygons FeatureCollection. 39 | collection: polygons, 40 | // Keep this list of properties from the polygons. 41 | properties: ['class'], 42 | // Set the scale to get Landsat pixels in the polygons. 43 | scale: 1000 44 | }); 45 | 46 | // Create an SVM classifier with custom parameters. 47 | var classifier = ee.Classifier.libsvm({ 48 | kernelType: 'RBF', 49 | gamma: 0.5, 50 | cost: 10 51 | }); 52 | 53 | // Train the classifier. 54 | var trained = classifier.train(training, 'class', bands); 55 | 56 | // Classify the image. 57 | var classified = image.classify(trained); 58 | 59 | // Display the classification result and the input image. 60 | Map.centerObject(table,4); 61 | Map.addLayer(polygons, {}, 'training polygons'); 62 | Map.addLayer(classified, 63 | {min: 0, max: 1, palette: ['red', 'green']}, 64 | 'deforestation'); -------------------------------------------------------------------------------- /13 - Clasificacion RF y Matriz de Confusion.txt: -------------------------------------------------------------------------------- 1 | // A Sentinel-2 surface reflectance image, reflectance bands selected, 2 | // serves as the source for training and prediction in this contrived example. 3 | var img = ee.Image('COPERNICUS/S2_SR/20210109T185751_20210109T185931_T10SEG') 4 | .select('B.*'); 5 | 6 | // ESA WorldCover land cover map, used as label source in classifier training. 7 | var lc = ee.Image('ESA/WorldCover/v100/2020'); 8 | 9 | // Remap the land cover class values to a 0-based sequential series. 10 | var classValues = [10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 100]; 11 | var remapValues = ee.List.sequence(0, 10); 12 | var label = 'lc'; 13 | lc = lc.remap(classValues, remapValues).rename(label).toByte(); 14 | 15 | // Add land cover as a band of the reflectance image and sample 100 pixels at 16 | // 10 m scale from each land cover class within a region of interest. 17 | var roi = ee.Geometry.Rectangle(-122.347, 37.743, -122.024, 37.838); 18 | var sample = img.addBands(lc).stratifiedSample({ 19 | numPoints: 100, 20 | classBand: label, 21 | region: roi, 22 | scale: 10, 23 | geometries: true 24 | }); 25 | 26 | // Add a random value field to the sample and use it to approximately split 80% 27 | // of the features into a training set and 20% into a validation set. 28 | sample = sample.randomColumn(); 29 | var trainingSample = sample.filter('random <= 0.8'); 30 | var validationSample = sample.filter('random > 0.8'); 31 | 32 | // Train a 10-tree random forest classifier from the training sample. 33 | var trainedClassifier = ee.Classifier.smileRandomForest(10).train({ 34 | features: trainingSample, 35 | classProperty: label, 36 | inputProperties: img.bandNames() 37 | }); 38 | 39 | // Get information about the trained classifier. 40 | print('Results of trained classifier', trainedClassifier.explain()); 41 | 42 | // Get a confusion matrix and overall accuracy for the training sample. 43 | var trainAccuracy = trainedClassifier.confusionMatrix(); 44 | print('Training error matrix', trainAccuracy); 45 | print('Training overall accuracy', trainAccuracy.accuracy()); 46 | 47 | // Get a confusion matrix and overall accuracy for the validation sample. 48 | validationSample = validationSample.classify(trainedClassifier); 49 | var validationAccuracy = validationSample.errorMatrix(label, 'classification'); 50 | print('Validation error matrix', validationAccuracy); 51 | print('Validation accuracy', validationAccuracy.accuracy()); 52 | 53 | // Classify the reflectance image from the trained classifier. 54 | var imgClassified = img.classify(trainedClassifier); 55 | 56 | // Add the layers to the map. 57 | var classVis = { 58 | min: 0, 59 | max: 10, 60 | palette: ['006400' ,'ffbb22', 'ffff4c', 'f096ff', 'fa0000', 'b4b4b4', 61 | 'f0f0f0', '0064c8', '0096a0', '00cf75', 'fae6a0'] 62 | }; 63 | Map.setCenter(-122.184, 37.796, 12); 64 | Map.addLayer(img, {bands: ['B11', 'B8', 'B3'], min: 100, max: 3500}, 'img'); 65 | Map.addLayer(lc, classVis, 'lc'); 66 | Map.addLayer(imgClassified, classVis, 'Classified'); 67 | Map.addLayer(roi, {color: 'white'}, 'ROI', false, 0.5); 68 | Map.addLayer(trainingSample, {color: 'black'}, 'Training sample', false); 69 | Map.addLayer(validationSample, {color: 'white'}, 'Validation sample', false); -------------------------------------------------------------------------------- /14 - Aplicacion GEE.txt: -------------------------------------------------------------------------------- 1 | /////////////////NDVI COMPUTATION AND IMAGE SELECTION CODES///////////////// 2 | //Choosing the Country from the Feature Collection located in GEE 3 | var country = 'EC'; 4 | var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017'); 5 | var table = countries.filter(ee.Filter.eq('country_co', ee.String(country))); 6 | var geometry = table.geometry() 7 | 8 | //Set the Satellite image as base map 9 | Map.setOptions('Satellite') 10 | 11 | //SENTINEL-2 12 | //Select the Sentinel-2 images to 2022 13 | var S2_2022 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") 14 | .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) 15 | .filter(ee.Filter.date('2022-01-01', '2023-01-01')) 16 | .filter(ee.Filter.bounds(geometry)) 17 | // Write a function that computes NDVI for an image and adds it as a band to Sentinel-2 18 | function S2NDVI(image) { 19 | var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi'); 20 | return image.addBands(ndvi); 21 | } 22 | // Map the function over the collection of Sentinel-2 23 | var S2NDVI_I = S2_2022.map(S2NDVI); 24 | var S2NDVI_I = S2NDVI_I.median() 25 | var S2NDVI_I = S2NDVI_I.select('ndvi').clip(geometry) 26 | 27 | //LANDSAT-8 28 | //Select the Landsat-8 images to 2013 - 2015 29 | var L8_2014 = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') 30 | .filterDate('2013-01-01', '2016-01-01') 31 | .filterMetadata('CLOUD_COVER', 'Less_Than', 30) 32 | .filter(ee.Filter.bounds(geometry)) 33 | //Function to compute NDVI using Landsat-8 34 | function L8NDVI(image) { 35 | var ndvi = image.normalizedDifference(['SR_B5', 'SR_B4']).rename('ndvi'); 36 | return image.addBands(ndvi); 37 | } 38 | // Map the function over the collection of Landsat-8 39 | var L8NDVI_I = L8_2014.map(L8NDVI); 40 | var L8NDVI_I = L8NDVI_I.median() 41 | var L8NDVI_I = L8NDVI_I.select('ndvi').clip(geometry) 42 | 43 | //LANDSAT-7 44 | //Select the Landsat-7 images to 2000 - 2002 45 | var L7_2001 = ee.ImageCollection('LANDSAT/LE07/C02/T1_L2') 46 | .filterDate('2000-01-01', '2002-01-01') 47 | .filterMetadata('CLOUD_COVER', 'Less_Than', 30) 48 | .filter(ee.Filter.bounds(geometry)) 49 | //Function to compute NDVI using Landsat-8 50 | function L7NDVI(image) { 51 | var ndvi = image.normalizedDifference(['SR_B4', 'SR_B3']).rename('ndvi'); 52 | return image.addBands(ndvi); 53 | } 54 | // Map the function over the collection of Landsat-7 55 | var L7NDVI_I = L7_2001.map(L7NDVI); 56 | var L7NDVI_I2 = L7NDVI_I 57 | var L7NDVI_I = L7NDVI_I.median() 58 | var L7NDVI_I = L7NDVI_I.select('ndvi').clip(geometry) 59 | 60 | //Showing the country boundaries 61 | Map.centerObject(table,7); 62 | Map.addLayer(table, {color: 'red'}, 'Country Boundary') 63 | 64 | //Creating the color palette to NDVI 65 | var palette = [ 66 | 'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', 67 | '74A901', '66A000', '529400', '3E8601', '207401', '056201', 68 | '004C00', '023B01', '012E01', '011D01', '011301']; 69 | var ndviVis = {min:0, max:1, palette: palette } 70 | 71 | //Adding data to map 72 | var S2NDVI_S = ui.Map.Layer(S2NDVI_I, ndviVis, '2022 NDVI',false) 73 | Map.add(S2NDVI_S) 74 | var L8NDVI_S = ui.Map.Layer(L8NDVI_I, ndviVis, '2014 NDVI',false) 75 | Map.add(L8NDVI_S) 76 | var L7NDVI_S = ui.Map.Layer(L7NDVI_I, ndviVis, '2001 NDVI',false) 77 | Map.add(L7NDVI_S) 78 | 79 | 80 | 81 | 82 | /////////////////APPLICATION CUSTOMS///////////////// 83 | //App Title 84 | Map.style().set('cursor', 'crosshair'); 85 | var header = ui.Label('NDVI in Ecuador during the last 20 years', 86 | {fontSize: '25px', fontWeight: 'bold', color: '484848', textAlign: 'center'}); 87 | 88 | //App summary 89 | var text = ui.Label( 90 | 'NDVI in Ecuador' + 91 | ' Using Landsat-7 (2000-2002), Landsat-8 (2013-2015) and Sentinel-2 (2022-2023).', 92 | {fontSize: '15px', textAlign: 'center', color: 'green'}); 93 | 94 | // Create a panel to hold text 95 | var panel = ui.Panel({ 96 | widgets:[header, text],//Adds header and text 97 | style:{width: '300px',position:'top-center'}}); 98 | 99 | var intro = ui.Panel([ 100 | ui.Label({ 101 | value: 'Credits: Cesar I. Alvarez-Mendoza PhD.', 102 | style: {fontWeight: 'bold', color: 'black',textAlign: 'center'}, 103 | }), 104 | ui.Label({ 105 | value: '___________________________________________', 106 | style: {fontWeight: 'bold', color: 'black'}, 107 | }), 108 | ui.Label({ 109 | value:'Select layers to display.', 110 | style: {fontSize: '15px', fontWeight: 'bold'} 111 | })]); 112 | panel.add(intro) 113 | 114 | //Add this main panel 115 | ui.root.insert(1,panel) 116 | 117 | //Add more text 118 | var extLabel = ui.Label({value:'Ecuador NDVI by periods', 119 | style: {fontWeight: 'bold', fontSize: '16px', margin: '10px 5px'} 120 | }); 121 | 122 | //Checks to select the NDVI layer 123 | var extCheck = ui.Checkbox('Landsat-7 (2000-2002)').setValue(false); //false = unchecked 124 | var extCheck2 = ui.Checkbox('Landsat-8 (2013-2015)').setValue(false);// 125 | var extCheck3 = ui.Checkbox('Sentinel-2 (2022-2023)').setValue(false); 126 | 127 | //Function to create the legend using the palette of NDVI 128 | function makeLegend (ndviVis) { 129 | var lon = ee.Image.pixelLonLat().select('longitude'); 130 | var gradient = lon.multiply((ndviVis.max-ndviVis.min)/100.0).add(ndviVis.min); 131 | var legendImage = gradient.visualize(ndviVis); 132 | 133 | var thumb = ui.Thumbnail({ 134 | image: legendImage, 135 | params: {bbox:'0,0,100,8', dimensions:'256x20'}, 136 | style: {position: 'bottom-center'} 137 | }); 138 | var panel2 = ui.Panel({ 139 | widgets: [ 140 | ui.Label('0 - Unhealthy'), 141 | ui.Label({style: {stretch: 'horizontal'}}), 142 | ui.Label('1 - Very Healty') 143 | ], 144 | layout: ui.Panel.Layout.flow('horizontal'), 145 | style: {stretch: 'horizontal', maxWidth: '270px', padding: '0px 0px 0px 8px'} 146 | }); 147 | return ui.Panel().add(panel2).add(thumb); 148 | } 149 | 150 | //Add an image or logo to explain your project 151 | var ndviexplained = ee.Image("projects/ee-cesarivanalvarezmendoza/assets/logos_images/ndviexplained"); 152 | var explanation = ui.Thumbnail({image:ndviexplained,params:{bands:['b1','b2','b3'],min:0,max:255},style:{width:'250px',height:'120px'}}); 153 | 154 | //Image credit links 155 | var imgCredits = ui.Label('Link NDVI reference'); 156 | imgCredits.style().set({margin: '1px 0px 2px 10px', fontSize: '12px'}); 157 | imgCredits.setUrl('https://eos.com/blog/ndvi-faq-all-you-need-to-know-about-ndvi/'); 158 | 159 | //Add widgets to the main panel 160 | panel.add(extLabel) 161 | .add(extCheck) 162 | .add(extCheck2) 163 | .add(extCheck3) 164 | .add(makeLegend(ndviVis)) 165 | .add(explanation) 166 | .add(imgCredits) 167 | 168 | //Layer to assign for each checkbox 169 | //Extent Landsat-7 2001 170 | var doCheckbox = function() { 171 | extCheck.onChange(function(checked){ 172 | L7NDVI_S.setShown(checked) 173 | }) 174 | } 175 | doCheckbox(); 176 | //Extent Landsat-8 2014 177 | var doCheckbox2 = function() { 178 | extCheck2.onChange(function(checked){ 179 | L8NDVI_S.setShown(checked) 180 | }) 181 | } 182 | doCheckbox2(); 183 | //Extent Sentinel-2 2022 184 | var doCheckbox3 = function() { 185 | extCheck3.onChange(function(checked){ 186 | S2NDVI_S.setShown(checked) 187 | }) 188 | } 189 | doCheckbox3(); -------------------------------------------------------------------------------- /15 - Comparacion Visual de Imagenes Años: -------------------------------------------------------------------------------- 1 | // Definir la región de interés (Quito, Ecuador) 2 | var quito = ee.Geometry.Point([-78.4678, -0.1807]).buffer(20000); 3 | 4 | // Función para filtrar y escalar las imágenes Landsat 5 | function getLandsatImage(year, collectionName) { 6 | var collection = ee.ImageCollection(collectionName) 7 | .filterDate(year + '-01-01', year + '-12-31') 8 | .filterBounds(quito) 9 | .filter(ee.Filter.lt('CLOUD_COVER', 50)) 10 | .sort('CLOUD_COVER'); 11 | 12 | // Calcular la mediana de la colección 13 | var image = collection.median(); 14 | return applyScaleFactors(image); 15 | } 16 | 17 | // Aplica factores de escala 18 | function applyScaleFactors(image) { 19 | var opticalBands = image.select('SR_B.') 20 | .multiply(0.0000275) 21 | .add(-0.2); 22 | var thermalBands = image.select('ST_B.*').multiply(0.00341802).add(149.0).add(-273.15); 23 | return image.addBands(opticalBands, null, true) 24 | .addBands(thermalBands, null, true); 25 | } 26 | 27 | // Definir parámetros de visualización 28 | var visParams = { 29 | bands: ['SR_B4', 'SR_B3', 'SR_B2'], 30 | min: 0, 31 | max: 0.3, 32 | }; 33 | 34 | // Crear dos paneles de mapas para comparar las imágenes 35 | var leftMap = ui.Map(); 36 | var rightMap = ui.Map(); 37 | var linker = ui.Map.Linker([leftMap, rightMap]); 38 | 39 | // Centrar ambos mapas en Quito 40 | leftMap.centerObject(quito, 10); 41 | rightMap.centerObject(quito, 10); 42 | 43 | // Crear cuadros de texto para seleccionar el año 44 | var year2014Input = ui.Textbox({placeholder: 'Año (2013-2021)', value: '2014'}); 45 | var year2023Input = ui.Textbox({placeholder: 'Año (2021-2024)', value: '2023'}); 46 | 47 | // Crear etiquetas para mostrar el año seleccionado en cada mapa 48 | var leftLabel = ui.Label('', {position: 'top-center', fontWeight: 'bold', color: 'white', backgroundColor: 'black'}); 49 | var rightLabel = ui.Label('', {position: 'top-center', fontWeight: 'bold', color: 'white', backgroundColor: 'black'}); 50 | 51 | leftMap.add(leftLabel); 52 | rightMap.add(rightLabel); 53 | 54 | // Función para actualizar las imágenes en función del año seleccionado 55 | function updateMaps() { 56 | var year2014 = parseInt(year2014Input.getValue(), 10); 57 | var year2023 = parseInt(year2023Input.getValue(), 10); 58 | 59 | // Verificar y ajustar los valores de los años 60 | if (year2014 < 2013 || year2014 > 2021) { 61 | year2014Input.setValue('2014'); 62 | year2014 = 2014; 63 | } 64 | if (year2023 < 2021 || year2023 > 2024) { 65 | year2023Input.setValue('2023'); 66 | year2023 = 2023; 67 | } 68 | 69 | // Obtener imágenes Landsat para los años seleccionados 70 | var landsat2014 = getLandsatImage(year2014, 'LANDSAT/LC08/C02/T1_L2'); 71 | var landsat2023 = getLandsatImage(year2023, 'LANDSAT/LC09/C02/T1_L2'); 72 | 73 | // Verificar si las imágenes existen antes de agregarlas al mapa 74 | if (landsat2014) { 75 | leftMap.layers().set(0, ui.Map.Layer(landsat2014, visParams, 'Landsat 8 - ' + year2014)); 76 | leftLabel.setValue('Año: ' + year2014 + ' (Valor mediano)'); 77 | } else { 78 | leftLabel.setValue('No hay datos para ' + year2014); 79 | } 80 | 81 | if (landsat2023) { 82 | rightMap.layers().set(0, ui.Map.Layer(landsat2023, visParams, 'Landsat 9 - ' + year2023)); 83 | rightLabel.setValue('Año: ' + year2023 + ' (Valor mediano)'); 84 | } else { 85 | rightLabel.setValue('No hay datos para ' + year2023); 86 | } 87 | } 88 | 89 | // Actualizar mapas al cambiar los cuadros de texto 90 | year2014Input.onChange(updateMaps); 91 | year2023Input.onChange(updateMaps); 92 | 93 | // Paneles para los inputs de los años 94 | var controlPanel = ui.Panel([ui.Label('Selecciona el año para cada imagen:'), 95 | ui.Panel([ui.Label('Landsat 8 (2013-2021):'), year2014Input]), 96 | ui.Panel([ui.Label('Landsat 9 (2021-2024):'), year2023Input])]); 97 | 98 | // Crear la interfaz dividida 99 | var splitPanel = ui.SplitPanel({ 100 | firstPanel: leftMap, 101 | secondPanel: rightMap, 102 | orientation: 'horizontal', 103 | wipe: true, 104 | }); 105 | 106 | // Añadir los controles y el panel dividido a la interfaz del GEE 107 | ui.root.widgets().reset([controlPanel, splitPanel]); 108 | 109 | // Inicializar la visualización de los mapas 110 | updateMaps(); 111 | -------------------------------------------------------------------------------- /2 - Visualizacion Imagen L9.txt: -------------------------------------------------------------------------------- 1 | var dataset = ee.ImageCollection('LANDSAT/LC09/C02/T1_L2') 2 | .filterDate('2022-09-01', '2022-10-01'); 3 | 4 | // Applies scaling factors. 5 | function applyScaleFactors(image) { 6 | var opticalBands = image.select('SR_B.').multiply(0.0000275).add(-0.2); 7 | var thermalBands = image.select('ST_B.*').multiply(0.00341802).add(149.0); 8 | return image.addBands(opticalBands, null, true) 9 | .addBands(thermalBands, null, true); 10 | } 11 | 12 | dataset = dataset.map(applyScaleFactors); 13 | 14 | var visualization = { 15 | bands: ['SR_B4', 'SR_B3', 'SR_B2'], 16 | min: 0.0, 17 | max: 0.3, 18 | }; 19 | 20 | Map.setCenter(-78, 0.01, 7); 21 | 22 | Map.addLayer(dataset, visualization, 'True Color (432)'); 23 | -------------------------------------------------------------------------------- /3 - Filtrar imagen Sentinel-2.txt: -------------------------------------------------------------------------------- 1 | var geometry = ee.Geometry.Point([-78.5, 0.02]) 2 | 3 | /** 4 | * Function to mask clouds using the Sentinel-2 QA band 5 | * @param {ee.Image} image Sentinel-2 image 6 | * @return {ee.Image} cloud masked Sentinel-2 image 7 | */ 8 | function maskS2clouds(image) { 9 | var qa = image.select('QA60'); 10 | 11 | // Bits 10 and 11 are clouds and cirrus, respectively. 12 | var cloudBitMask = 1 << 10; 13 | var cirrusBitMask = 1 << 11; 14 | 15 | // Both flags should be set to zero, indicating clear conditions. 16 | var mask = qa.bitwiseAnd(cloudBitMask).eq(0) 17 | .and(qa.bitwiseAnd(cirrusBitMask).eq(0)); 18 | 19 | return image.updateMask(mask).divide(10000); 20 | } 21 | 22 | var dataset = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED') 23 | .filterDate('2020-01-01', '2020-03-30') 24 | // Pre-filter to get less cloudy granules. 25 | .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',20)) 26 | .map(maskS2clouds) 27 | .filter(ee.Filter.bounds(geometry)); 28 | 29 | var visualization = { 30 | min: 0.0, 31 | max: 0.3, 32 | bands: ['B4', 'B3', 'B2'], 33 | //bands: ['B5', 'B4', 'B3'], 34 | }; 35 | 36 | Map.centerObject(geometry, 10) 37 | 38 | //Map.addLayer(dataset.mean(), visualization); 39 | Map.addLayer(dataset.mean(), visualization, 'RGB'); 40 | -------------------------------------------------------------------------------- /4 - Mosaico y Mediana Sentinel-2.txt: -------------------------------------------------------------------------------- 1 | var geometry = ee.Geometry.Point([-78.5, 0.02]) 2 | 3 | var filtered = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED') 4 | .filterDate('2020-01-01', '2022-01-01') 5 | // Pre-filter to get less cloudy granules. 6 | .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',20)) 7 | .filter(ee.Filter.bounds(geometry)); 8 | 9 | var mosaic = filtered.mosaic() //Crea un mosaico con los últimos pixeles de la colección encontrados 10 | 11 | var medianComposite = filtered.median(); //Genera una mediana de pixeles entre fechas 12 | 13 | var rgbVis = { 14 | min: 0.0, 15 | max: 3000, 16 | bands: ['B4', 'B3', 'B2'], 17 | }; 18 | 19 | // set styling 20 | Map.centerObject(geometry, 15) 21 | Map.addLayer(filtered, rgbVis, 'Colección original'); 22 | Map.addLayer(mosaic, rgbVis, 'Mosaico'); 23 | Map.addLayer(medianComposite, rgbVis, 'Composición mediana') 24 | Map.addLayer(geometry,{color: 'red', pointSize: 30, pointShape: 'circle'}, 'Punto'); -------------------------------------------------------------------------------- /5 - Vectores FeatureCollections.txt: -------------------------------------------------------------------------------- 1 | var country = 'BL'; //Choose the country initials [Two-letter FIPS country code](https://en.wikipedia.org/wiki/List_of_FIPS_country_codes 2 | 3 | // Load country features from Large Scale International Boundary (LSIB) dataset. 4 | var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017'); 5 | var table = countries.filter(ee.Filter.eq('country_co', ee.String(country))); 6 | 7 | Map.centerObject(table,5); 8 | Map.addLayer(table, {color: 'red'}) -------------------------------------------------------------------------------- /7 - Clip Imagen Sentinel-2.txt: -------------------------------------------------------------------------------- 1 | var s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED') 2 | var urban = ee.FeatureCollection("users/cesarivanalvarezmendoza/shapefiles/PLOTS4326") 3 | 4 | var geometry = urban.geometry() 5 | 6 | var rgbVis = { 7 | min: 0.0, 8 | max: 3000, 9 | bands: ['B4', 'B3', 'B2'], 10 | }; 11 | var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) 12 | .filter(ee.Filter.date('2021-01-01', '2022-01-01')) 13 | .filter(ee.Filter.bounds(geometry)) 14 | 15 | var image = filtered.median(); 16 | 17 | var clipped = image.clip(geometry) 18 | 19 | Map.centerObject(urban,17) 20 | Map.addLayer(clipped, rgbVis, 'Clipped') -------------------------------------------------------------------------------- /8 - Exportar imágenes a Google Drive.txt: -------------------------------------------------------------------------------- 1 | var country = 'BL'; //Choose the country initials [Two-letter FIPS country code] https://en.wikipedia.org/wiki/List_of_FIPS_country_codes 2 | 3 | // Load country features from Large Scale International Boundary (LSIB) dataset. 4 | var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017'); 5 | var table = countries.filter(ee.Filter.eq('country_co', ee.String(country))); 6 | 7 | // Make the clip boundary. 8 | var clipToCol = function(image){ 9 | return image.clip(table); 10 | }; 11 | 12 | var collection = ee.ImageCollection('COPERNICUS/S5P/OFFL/L3_NO2') 13 | .select('NO2_column_number_density') 14 | .filterBounds(table) 15 | .filterDate('2019-03-16', '2019-03-31') 16 | .map(clipToCol); 17 | 18 | var band_viz = { 19 | min: 0, 20 | max: 0.00009, 21 | palette: ['green','yellow', 'red'] 22 | }; 23 | 24 | Map.addLayer(collection.median(), band_viz, 'S5P N02'); 25 | Map.addLayer(table); 26 | Map.centerObject(table,5); 27 | 28 | print(collection.size()) 29 | 30 | // Export the image, specifying scale and region. 31 | Export.image.toDrive({ 32 | image: collection.median(), 33 | description: 'Bolivia_2019', 34 | scale: 10000, 35 | region: table 36 | }); -------------------------------------------------------------------------------- /9 - NDVI.txt: -------------------------------------------------------------------------------- 1 | var s2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED"); 2 | var country = 'EC'; 3 | var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017'); 4 | var table = countries.filter(ee.Filter.eq('country_co', ee.String(country))); 5 | var geometry = table.geometry() 6 | 7 | var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']}; 8 | 9 | var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) 10 | .filter(ee.Filter.date('2021-01-01', '2022-01-01')) 11 | .filter(ee.Filter.bounds(geometry)) 12 | 13 | var composite = filtered.median().clip(geometry) 14 | Map.addLayer(composite, rgbVis, 'RGB Ecuador') 15 | 16 | // Write a function that computes NDVI for an image and adds it as a band 17 | function addNDVI(image) { 18 | var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi'); 19 | return image.addBands(ndvi); 20 | } 21 | 22 | // Map the function over the collection 23 | var withNdvi = filtered.map(addNDVI); 24 | var composite = withNdvi.median() 25 | var ndviComposite = composite.select('ndvi').clip(geometry) 26 | 27 | var palette = [ 28 | 'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', 29 | '74A901', '66A000', '529400', '3E8601', '207401', '056201', 30 | '004C00', '023B01', '012E01', '011D01', '011301']; 31 | 32 | var ndviVis = {min:0, max:1, palette: palette } 33 | Map.addLayer(ndviComposite, ndviVis, 'NDVI') 34 | 35 | Map.centerObject(table,7); 36 | Map.addLayer(table, {color: 'red'}, 'Limite Ecuador') -------------------------------------------------------------------------------- /Part 1 - Remote Sensing with GEE - Spanish.pdf: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Part 2 - Remote Sensing with GEE - Spanish.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osoivan/GEEExercises/669db7d2e9a1de8a57f5fa8915aaeae935f56c2a/Part 2 - Remote Sensing with GEE - Spanish.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![image](https://github.com/user-attachments/assets/165bcb8d-cc21-4fbf-9f46-167ff8860453) 2 | 3 | 4 | Hola, aquí compartimos nuestro módulo desarrollado de Teledetección con Google Earth Engine, desde ejercicios sencillos para quien no sabe temas de programación, hasta algo más avanzado. 5 | 6 | https://www.linkedin.com/in/cesar-ivan-alvarez-0847253a/ 7 | 8 | https://scholar.google.com/citations?user=50ILKdkAAAAJ&hl=es 9 | -------------------------------------------------------------------------------- /TRATAMENTO DADOS ESPACIAIS GEE - Portuguese.pdf: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Using GEE - English.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osoivan/GEEExercises/669db7d2e9a1de8a57f5fa8915aaeae935f56c2a/Using GEE - English.pdf --------------------------------------------------------------------------------