I am a new user on GEE. Currently, I found a code for creating a water occurrence on GEE, I tried to apply this code for my AOI, but it have some error while running this.
Error:
ImageCollection (Error) Filter.contains: Unable to use a collection in an algorithm that requires a feature or image. This may happen when trying to use a collection of collections where a collection of features is expected; use flatten, or map a function to convert inner collections to features. Use clipToCollection (instead of clip) to clip an image to a collection.
Here is the code link: https://code.earthengine.google.com/329d8fec48149147034f685fdfbbc730?hideCode=true
var aoi = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level0").filter(ee.Filter.eq('ADM0_NAME', 'Pakistan'));
Map.addLayer(aoi, {color: 'black'}, 'Study Area',1);
// Zoom to regions of interest
Map.centerObject(aoi);
// import sentinel 1 and filter data series
var s1 = ee.ImageCollection('COPERNICUS/S1_GRD')
.filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VV'))
.filter(ee.Filter.eq('instrumentMode', 'IW'))
.filter(ee.Filter.eq('orbitProperties_pass', 'ASCENDING'))
.filterBounds(aoi)
//.filterBounds(Map.getBounds(true))
.filterDate('2018-11-01','2019-10-31')
.filter(ee.Filter.contains({leftField: ".geo", rightValue: aoi})) // Filter partial S1-Images of AOI
.map(function(image){return image.clip(Map.getBounds(true))})
.map(function(image){return image.addBands(image.select('VV').focal_median(parseFloat('50'),'circle','meters').rename('VV_smoothed'))}); // Smooth S1-Images
print(s1);
// Return the DN that maximizes interclass variance in S1-band (in the region).
var otsu = function(histogram) {
var counts = ee.Array(ee.Dictionary(histogram).get('histogram'));
var means = ee.Array(ee.Dictionary(histogram).get('bucketMeans'));
var size = means.length().get([0]);
var total = counts.reduce(ee.Reducer.sum(), [0]).get([0]);
var sum = means.multiply(counts).reduce(ee.Reducer.sum(), [0]).get([0]);
var mean = sum.divide(total);
var indices = ee.List.sequence(1, size);
// Compute between sum of squares, where each mean partitions the data.
var bss = indices.map(function(i) {
var aCounts = counts.slice(0, 0, i);
var aCount = aCounts.reduce(ee.Reducer.sum(), [0]).get([0]);
var aMeans = means.slice(0, 0, i);
var aMean = aMeans.multiply(aCounts)
.reduce(ee.Reducer.sum(), [0]).get([0])
.divide(aCount);
var bCount = total.subtract(aCount);
var bMean = sum.subtract(aCount.multiply(aMean)).divide(bCount);
return aCount.multiply(aMean.subtract(mean).pow(2)).add(
bCount.multiply(bMean.subtract(mean).pow(2)));
});
// Return the mean value corresponding to the maximum BSS.
return means.sort(bss).get([-1]);
};
// return image with water mask as additional band
var add_waterMask = function(image){
// Compute histogram
var histogram = image.select('VV').reduceRegion({
reducer: ee.Reducer.histogram(255, 2)
.combine('mean', null, true)
.combine('variance', null, true),
geometry: aoi,
scale: 10,
bestEffort: true
});
// Calculate threshold via function otsu (see before)
var threshold = otsu(histogram.get('VV_histogram'));
// get watermask
var waterMask = image.select('VV_smoothed').lt(threshold).rename('waterMask');
waterMask = waterMask.updateMask(waterMask); //Remove all pixels equal to 0
return image.addBands(waterMask);
};
s1 = s1.map(add_waterMask);
//Calculating water occurrence
var min_occurence = 10;
var water_sum = s1.select('waterMask').reduce(ee.Reducer.sum());
var water_frequency = water_sum.divide(s1.select('waterMask').size()).multiply(100);
var water_frequency_masked = water_frequency.updateMask(water_frequency.gt(min_occurence));
//Add color bar
//base code adapted from:
//https://gis.stackexchange.com/questions/290713/adding-map-key-to-map-or-console-in-google-earth-engine
//https://code.earthengine.google.com/9f890c110e98fa3391480543009c8028
function ColorBar(palette) {
return ui.Thumbnail({
image: ee.Image.pixelLonLat().select(0),
params: {
bbox: [0, 0, 1, 0.1],
dimensions: '300x15',
format: 'png',
min: 0,
max: 1,
palette: palette,
},
style: {stretch: 'horizontal', margin: '0px 22px'},
});
}
function makeLegend(lowLine, midLine, highLine,lowText, midText, highText, palette) {
var labelheader = ui.Label('Water occurrence during investigation period',{margin: '5px 17px', textAlign: 'center', stretch: 'horizontal', fontWeight: 'bold'});
var labelLines = ui.Panel(
[
ui.Label(lowLine, {margin: '-4px 21px'}),
ui.Label(midLine, {margin: '-4px 0px', textAlign: 'center', stretch: 'horizontal'}),
ui.Label(highLine, {margin: '-4px 21px'})
],
ui.Panel.Layout.flow('horizontal'));
var labelPanel = ui.Panel(
[
ui.Label(lowText, {margin: '0px 14.5px'}),
ui.Label(midText, {margin: '0px 0px', textAlign: 'center', stretch: 'horizontal'}),
ui.Label(highText, {margin: '0px 1px'})
],
ui.Panel.Layout.flow('horizontal'));
return ui.Panel({
widgets: [labelheader, ColorBar(palette), labelLines, labelPanel],
style: {position:'bottom-left'}});
}
Map.add(makeLegend('|', '|', '|', "0 %", '50 %', '100%', ['orange','yellow','lightblue','darkblue']));
// time-lapse animation
var timelapse = {
bands: ["VV","VV","VV"],
region: aoi,
min: -20,
max: 0,
framesPerSecond: 5};
var animation = ui.Thumbnail({
image: s1,
params: timelapse,
style: {
position: 'bottom-left',
width: '360px',
}});
//Add layers ans animation to map
Map.addLayer(s1.median(),{bands: ['VV','VV','VV'],min: -20,max: 0,},'S1-image [median]');
Map.addLayer(water_frequency_masked,{min:min_occurence,max:100,palette:['orange','yellow','lightblue','darkblue']},'Percentage of annual water occurence');
Map.add(animation);
// Create and print a histogram chart
//Make time series of water pixels as area in km² within region
var ClassChart = ui.Chart.image.series({
imageCollection: s1.select('waterMask'),
region: aoi,
reducer: ee.Reducer.sum(),
scale: 100,
})
.setOptions({
title: 'Area of the identified water mask',
vAxis: {'title': 'area'},
lineWidth: 1.5,
pointSize: 2
});
ClassChart.style().set({
position: 'bottom-right',
width: '492px',
height: '300px'
});
Map.add(ClassChart);
//Create callback function that adds image to the map coresponding with clicked data point on chart
ClassChart.onClick(function(xValue, yValue, seriesName) {
if (!xValue) return; // Auswahl zurücksetzen
// Show the image for the clicked date.
var equalDate = ee.Filter.equals('system:time_start', xValue);
//Find image coresponding with clicked data and clip water classification to aoi
var classification = ee.Image(s1.filter(equalDate).first()).clip(aoi).select('waterMask');
var SARimage = ee.Image(s1.filter(equalDate).first());
var date_string = new Date(xValue).toLocaleString('de-DE', {dateStyle: 'full', timeStyle: 'short' });
//Make map layer based on SAR image, reset the map layers, and add this new layer
var S1Layer = ui.Map.Layer(SARimage, {
bands: ['VV'],
max: 0,
min: -20
},'S1-Image ['+ new Date(xValue).toLocaleString('de-DE')+']');
Map.layers().reset([S1Layer]);
var visParamsS1Layer = {
min: 0,
max: 1,
palette: ['#FFFFFF','#0000FF']
};
//Add water classification on top of SAR image
Map.addLayer(classification,visParamsS1Layer,'water mask ['+date_string+']');
});