Land-use classification using the Random Forest algorithm of the GEE - google-earth-engine

I am working on a land use classification program using the RS algorithm of the GEE platform. The codes are as the following link.
https://code.earthengine.google.com/7e99f1de58c1251bd9bff0ff7af9368b
Specific codes:
var table = ee.FeatureCollection("users/zongxuli/Jing_Jin_Ji");
//Set up bands and corresponding band names
var inBands = ee.List([1,2,3,4,5,7,6,'pixel_qa'])
var outBands = ee.List(['blue','green','red','nir','swir1','temp', 'swir2','pixel_qa'])
// Get Landsat data
var l8s = ee.ImageCollection("LANDSAT/LC08/C01/T1_SR")
.filterDate(2019-01-01,2019-12-31)
.filterBounds(table)
.select(inBands,outBands)
.filter(ee.Filter.lt("CLOUD_COVER",10))
function getIndexes(image){
// Normalized Difference Vegitation Index(NDWI)
var ndvi = image.normalizedDifference(['nir','red']).rename("ndvi");
image = image.addBands(ndvi);
// Normalized Difference Snow Index(NDWI)
var ndsi = image.normalizedDifference(['green','swir1']).rename("ndsi");
image = image.addBands(ndsi);
// Normalized Difference Water Index(NDWI)
var ndwi = image.normalizedDifference(['nir','swir1']).rename("ndwi");
image = image.addBands(ndwi);
// add Enhanced Vegetation Indexes
var evi = image.expression('2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
'NIR' : image.select('nir'),
'RED' : image.select('red'),
'BLUE': image.select('blue') }).float();
image = image.addBands(evi.rename('evi'));
// Add Index-Based Built-Up Index (IBI)
var ibiA = image.expression('2 * SWIR1 / (SWIR1 + NIR)', {
'SWIR1': image.select('swir1'),
'NIR' : image.select('nir')}).rename(['IBI_A']);
var ibiB = image.expression('(NIR / (NIR + RED)) + (GREEN / (GREEN + SWIR1))', {
'NIR' : image.select('nir'),
'RED' : image.select('red'),
'GREEN': image.select('green'),
'SWIR1': image.select('swir1')}).rename(['IBI_B']);
var ibiAB = ibiA.addBands(ibiB);
var ibi = ibiAB.normalizedDifference(['IBI_A', 'IBI_B']);
image = image.addBands(ibi.rename('ibi'));
return(image);
}
function getTopography(image,elevation) {
// Calculate slope, aspect and hillshade
var topo = ee.Algorithms.Terrain(elevation);
// From aspect (a), calculate eastness (sin a), northness (cos a)
var deg2rad = ee.Number(Math.PI).divide(180);
var aspect = topo.select(['aspect']);
var aspect_rad = aspect.multiply(deg2rad);
var eastness = aspect_rad.sin().rename(['eastness']).float();
var northness = aspect_rad.cos().rename(['northness']).float();
// Add topography bands to image
topo = topo.select(['elevation','slope','aspect']).addBands(eastness).addBands(northness);
image = image.addBands(topo);
return(image);
}
// Get an image to train and apply classification to.
var image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(table)
.first();
// get bands
var bands=image.bandNames();
print(bands);
// integers starting from zero in the training data.
var label = 'lcode';
// Overlay the points on the imagery to get training.
var trainings = image.select(bands).sampleRegions({
collection: l8s, //.filterDate(2019-01-01,2019-12-31),
properties: [label],
scale: 30
});
// The randomColumn() method will add a column of uniform random
// numbers in a column named 'random' by default.
var sample = trainings.randomColumn();
var split = 0.7; // Roughly 70% training, 30% testing.
var training = sample.filter(ee.Filter.lt('random', split));
print(training.size());
// Random forest
var classifier = (ee.Classifier.smileRandomForest(15)
.train({
features: training,
classProperty: label,
inputProperties: bands
}));
var classified = image.classify(classifier);
print(classified);
So far, I always received the wrong message "Number (Error) Empty date ranges not supported for the current operation." when running the program. What am I doing wrong?

There is a quotation problem in image collection date filtering:
// Get Landsat data
var l8s = ee.ImageCollection("LANDSAT/LC08/C01/T1_SR")
.filterDate(2019-01-01,2019-12-31)
.filterBounds(table)
.select(inBands,outBands)
.filter(ee.Filter.lt("CLOUD_COVER",10))
it must be:
// Get Landsat data
var l8s = ee.ImageCollection("LANDSAT/LC08/C01/T1_SR")
.filterDate('2019-01-01','2019-12-31')
.filterBounds(table)
.select(inBands,outBands)
.filter(ee.Filter.lt("CLOUD_COVER",10))
And in training for classifier section:
// Overlay the points on the imagery to get training.
var trainings = image.select(bands).sampleRegions({
collection: l8s, //.filterDate(2019-01-01,2019-12-31),
properties: [label],
scale: 30 });
it must be :
// Overlay the points on the imagery to get training.
var trainings =
image.select(bands).sampleRegions({
collection: table,
properties: [label],
scale: 30 });

Related

consider the values for all pixels in a polygon in google earth engine

I calculated the MNDWI value of the picture collection
function MNDWI(image) {
var mndwi = image.normalizedDifference(['SR_B6', 'SR_B3']).rename('mndwi');
return image.addBands(mndwi);
}
// display MNDWI layer
var withMndwi = filtered.map(MNDWI);
var composite = withMndwi.median().clip(polygon);
var MndwiComposite = composite.select('mndwi');
I also use statistic to calculate the threshold
var chart = ui.Chart.image.seriesByRegion({
imageCollection: withMndwi,
regions: pol,
band: 'mndwi',
reducer:ee.Reducer.mean(),
scale:10, });
Now I want to consider every single value of the image collection, I did try something as recommendation in this [post][1] like:
function masking (image){
var sample = image.sample();
var threshold = sample.gte(chart); // gte = greater (gt) + equal (eq)
var mask = threshold.updateMask(threshold);
return image.updateMask(mask);
}
But it notices that: sample.gte is not a function
What should I do for now?
[1]: extract the values for all pixels in a polygon in google earth engine

How to export a csv file from Google Earth Engine with attribute data and associated dates in a user defined date format?

Good Day
I am trying to generate an Enhanced Vegetation Index (EVI) in Google Earth Engine using Landsat 7 and 8 data. I have compiled the code below to filter the image collections, for a specific time period and region of interest, as well as to mask out a majority of the cloud cover in the images. I have then proceeded to calculate the EVI and add these values to the image collections as an attribute that I can select for further processing. I have undertaken this process separately for Landsat 7 and Landsat 8. However, since I am interested in the EVI that is generated from both these data sets I have merged these into one image collection.
Using this image collection, I would like to calculate the mean EVI value for a particular region of interest and then export these values along with the associated date (in the format dd-mm-yyyy) as a ".csv" file. I am aware that this is possible by clicking on the chart that is generated and downloading the associated ".csv" file or by exporting the data using the "Export.table.toDrive" function. However, none of these options provide the output in the structure as shown in the table below.
A sample of the code is provided here. Any assistance with this will be greatly appreciated. Kind Regards.
/// Add region of interest
var ROI = ee.FeatureCollection("users/shaedengokool/Eben_Sluis_15YO")
Map.addLayer(ROI, {}, 'ROI')
Map.centerObject(ROI, 10)
//1. Import the Landsat 8 TOA image collection.
var l8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterDate('2002-01-01','2020-01-01')
.filterBounds(ROI)
.map(function(image){return image.clip(ROI)})
var L8cloudlessEVI = l8.map(function(image) {
// Get a cloud score in [0, 100].
var cloud = ee.Algorithms.Landsat.simpleCloudScore(image).select('cloud');
// Create a mask of cloudy pixels from an arbitrary threshold.
var mask = cloud.lte(10);
// Compute EVI.
var evi = image.expression(
'2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
'NIR': image.select('B5'),
'RED': image.select('B4'),
'BLUE': image.select('B2')
}).rename('EVI');
// Return the masked image with an EVI band.
return image.addBands(evi).updateMask(mask);
});
var L8EVI_collection = L8cloudlessEVI
//2. Import the Landsat 7 TOA image collection.
var l7 = ee.ImageCollection('LANDSAT/LE07/C01/T1_TOA')
.filterDate('2002-01-01','2020-01-01')
.filterBounds(ROI)
.map(function(image){return image.clip(ROI)})
var L7cloudlessEVI = l7.map(function(image) {
// Get a cloud score in [0, 100].
var cloud = ee.Algorithms.Landsat.simpleCloudScore(image).select('cloud');
// Create a mask of cloudy pixels from an arbitrary threshold.
var mask = cloud.lte(10);
// Compute EVI.
var evi = image.expression(
'2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
'NIR': image.select('B4'),
'RED': image.select('B3'),
'BLUE': image.select('B1')
}).rename('EVI');
// Return the masked image with an EVI band.
return image.addBands(evi).updateMask(mask);
});
var L7EVI_collection = L7cloudlessEVI
var merged = ee.ImageCollection(L7EVI_collection.merge(L8EVI_collection));
print(merged, 'Merged')
var chart = ui.Chart.image.series({
imageCollection: merged.select('EVI'),
region: ROI,
reducer: ee.Reducer.mean(),
scale: 30,
})
print(chart, "EVI")
// get the mean value for the region from each image
var meanEVI = merged.map(function(image){
var date = image.get('system:time_start');
var mean = image.reduceRegion({
reducer: ee.Reducer.mean(),
geometry: ROI,
scale: 30
});
// and return a feature with 'null' geometry with properties (dictionary)
return ee.Feature(null, {'mean': mean.get('EVI'),
'date': date})
});
// Export a .csv table of date, mean NDVI for watershed
Export.table.toDrive({
collection: meanEVI,
description: 'EVI_Timeseries',
folder: 'Genus_Exchange_GEE_Data',
fileFormat: 'CSV',
})
;
In the code below I've added a date as an image property and exported it to a CSV. I also rearranged some of the code to decrease the computational time.
Here is the code:
var roi = ee.FeatureCollection("users/shaedengokool/Eben_Sluis_15YO")
// Define time of interest
var startdate = '2019-06-01' // insert
var enddate = '2020-06-01' // insert
var years = ee.List.sequence(ee.Date(startdate).get('year'), ee.Date(enddate).get('year'));
/// EVI calculations from Landsat
// This function masks clouds in Landsat 8 imagery.
function maskL8(im) {
var qa = im.select('BQA');
var mask = qa.eq(2720);
return im.updateMask(mask).copyProperties(im);
}
// This function masks clouds in Landsat 7 imagery.
function maskL7(im) {
var qa = im.select('BQA');
var mask = qa.eq(672);
return im.updateMask(mask).copyProperties(im);
}
// see: https://landsat.usgs.gov/sites/default/files/documents/landsat_QA_tools_userguide.pdf
var ls8toa = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterBounds(roi)
.filterDate(startdate, enddate)
.map(function(im) {return maskL8(im)})
var ls7toa = ee.ImageCollection('LANDSAT/LE07/C01/T1_TOA').filterBounds(roi).filterDate(startdate, enddate)
.map(function(im) {return maskL7(im)})
var ls7_evi = ls7toa.map(function(image) {
var evi = image.expression(
'2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
'NIR': image.select('B4'),
'RED': image.select('B3'),
'BLUE': image.select('B1')
}).rename('EVI')
return image.addBands(evi)
})
var ls8_evi = ls8toa.map(function(image) {
var evi = image.expression(
'2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
'NIR': image.select('B5'),
'RED': image.select('B4'),
'BLUE': image.select('B2')
}).rename('EVI')
return image.addBands(evi)
})
var landsat = ee.ImageCollection(ls7_evi.merge(ls8_evi));
var EVI = landsat.select(['EVI'])
print(EVI, 'EVI')
//create function to calculate mean values for each polygon
var pointsmean = function(image) {
var means = image.reduceRegions({
collection: roi, // used to be roi.select(['Id'])
reducer: ee.Reducer.mean(),
scale: 30
})
// assign time for every feature
means = means.map(function(f) { return f.set({date: image.date().format("YYYY-MM-dd")}) })
return means.copyProperties(image)
};
var finalEVI = EVI.map(pointsmean).flatten()
.sort('date', false)
.select(['date', 'mean'])
print(finalEVI.limit(100), 'final EVI')
Export.table.toDrive({
collection: finalEVI,
description: 'EVI_'+startdate+'TO'+enddate,
fileFormat: 'CSV'
});

" image.select(bands).sampleRegions is not a function error. what must i do?

I am trying to conduct a lulc classification on google earth engine using landsat5 data for 2000, but every time it is showing me the error:
image.select(bands).sampleRegions is not a function
var shp = ee.FeatureCollection(mws)
Map.addLayer(shp, {}, 'My Polygon')
var pol = ee.FeatureCollection(poly2000)
Map.addLayer(pol, {} )
//landcover for 2000//
var dataset = ee.ImageCollection("LANDSAT/LT05/C01/T1_TOA")
.filterBounds(roi1)
.filterDate('2000-01-01', '2000-01-31')
.map(function(image){return image.clip(mws)});
var trueColor432 = dataset.select(['B4', 'B3', 'B2']);
var trueColor432Vis = {};
Map.setCenter(88.41713038056656,26.861987108179317);
Map.addLayer(trueColor432, trueColor432Vis, 'True Color (432)');
var image = trueColor432;
// merging sample points together
var landcover = forest.merge(water).merge(clearing).merge(built_up);
print(landcover);
// selecting bands
var bands= ['B2','B3','B4'];
//sampling the input imagery to get a featurecollection of a training data
var training = image.select(bands).sampleRegions({
collection: landcover,
properties: ['landcover'],
scale: 30
});
//training the classifier
var classifier= ee.Classifier.svm().train({
features: training,
classProperty : 'landcover',
inputProperties: bands
});
//classifying the input imagery
var classified= image.select(bands).classify(classifier);
sampleRegions samples the pixels of an image: https://developers.google.com/earth-engine/apidocs/ee-image-sampleregions
Maybe adding .toBands() works?
var training = image.toBands().select(bands).sampleRegions({
collection: landcover,
properties: ['landcover'],
scale: 30
});

Extract Index vegetation by points over collection in GEE

How I can extract index vegetation points over collections by adapting this beautiful code by #Rodrigo E. Principe:
Extract pixel values by points and convert to a table in Google Earth Engine
I try extract all values mas GEE is crashing, so only NDVI or EVI can works fine.
I did it with this tutorial https://developers.google.com/earth-engine/tutorial_api_06
// Dataset do sensor LS8
var dataset = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterDate('2018-04-01', '2019-03-31')
.select('B5', 'B4')
.filterBounds(aoi6010)
.filter(ee.Filter.lt('CLOUD_COVER', 20));
var addNDVI = function(image) {
var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
return image.addBands(ndvi);
};
var withNDVI = dataset.map(addNDVI);
print(withNDVI);
// Empty Collection to fill
var ft = ee.FeatureCollection(ee.List([]))
var fill = function(img, ini) {
// type cast
var inift = ee.FeatureCollection(ini)
// gets the values for the points in the current img
var ft2 = img.reduceRegions(p601018, ee.Reducer.first(),30)
// gets the date of the img
var date = img.date().format()
// writes the date in each feature
var ft3 = ft2.map(function(f){return f.set("date", date)})
// merges the FeatureCollections
return inift.merge(ft3)
}
// Iterates over the ImageCollection
var newft = ee.FeatureCollection(withNDVI.iterate(fill, ft))

Google Earth Engine: Flatten a one-band ImageCollection into a multi-band single Image

I want to use supervised classification to classify a pattern that has a clear temporal pattern. For example, identifying stands of deciduous trees in a coniferous forest. NDVI would change overtime in the deciduous stands in a regular pattern that should be easily detectable. I assume there's an easy method to flatten the temporal dataset into a single image so that the bands in that image can be used in a classification algorithm. Maybe using .map(....)?
Here's some code to build the answer from:
var startDate = '2016-05-01';
var endDate = '2016-09-01';
var lng = -122.3424; var lat = 37.9344; //SF
var region = ee.Geometry.Point(lng, lat);
//Image Import
var l8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterBounds(region)
.filterDate(startDate,endDate);
// NDVI temporal
var ndvi = l8.map(function(image) {
var ndvi = image.normalizedDifference(['B5', 'B4']).rename("NDVI");
return ndvi;
});
Map.addLayer(ndvi,{},"NDVI Temporal"); // 8 images with 1 band
//NDVI FLATTENED??????? I want 1 image with 8 bands. The below code doesn't work...
var ndviFlat = ee.Image().addBands(ndvi.map(function(image){
var temp = image.select("NDVI");
return temp;
}));
From there, I will pass ndviFlat to .sampleRegions, which only works with Images not ImageCollections:
//Classification Model:
var points = ee.FeatureCollection([trainingPointsPos,trainingPointsNeg]).flatten();
var training = ndviFlat.sampleRegions({
collection: points,
properties: ['class'],
scale: 30
});
var trained = ee.Classifier.randomForest(20).train(training, 'class', bands);
classified = regLayers.select(bands).classify(trained);
Here's one way:
var startDate = '2016-05-01';
var endDate = '2016-09-01';
var lng = -122.3424;
var lat = 37.9344; //SF
var region = ee.Geometry.Point(lng, lat);
//Image Import
var l8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterBounds(region)
.filterDate(startDate, endDate);
var empty = ee.Image();
// NDVI temporal
var ndvi = ee.Image(l8.iterate(function(image, previous) {
var name = ee.String('NDVI_').cat(image.id());
var ndvi = image.normalizedDifference(['B5', 'B4']).rename(name);
return ee.Image(previous).addBands(ndvi);
}, empty));
// Remove the annoying non-band
ndvi = ndvi.select(ndvi.bandNames().remove('constant'));
Map.centerObject(region, 13);
Map.addLayer(ndvi, {}, 'ndvi');

Resources