# Calculating water occurrence of Sentinel-1 images in Google Earth Engine

I would like to derive the occurrence of surface water bodies from Sentinel-1 image collection in the Google Earth Engine.In my example I could already compute the water mask using Otsu’s method for image segmentation: https://code.earthengine.google.com/499580510635aa5f421886d4e409af03.

This procedure has now to be applied to the entire image collection, so that the variable threshold is recalculated for each image and then the water mask is determined.The occurrence of water bodies should be presented relatively (0%-no occurrence, 100%-always water present) as shown in Global Surface Water Explorer.

Does anyone have a solution or a hint for this?

Create the S1 image collection:

``````var s1 = ee.ImageCollection('COPERNICUS/S1_GRD')
.filterBounds(Map.getBounds(true))
.filterDate('2019-01-01','2019-12-31')
.map(function(image){return image.clip(Map.getBounds(true))});
print(s1);
``````

Otsu's method for image segmentation:

``````var histogram = image.select(s1_band).reduceRegion({
reducer: ee.Reducer.histogram()
.combine('mean', null, true)
.combine('variance', null, true),
geometry: polygon,
scale: 10,
bestEffort: true
});
print(histogram);

// Chart the histogram
print(Chart.image.histogram(image.select(s1_band), polygon, 10));

// 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();
var total = counts.reduce(ee.Reducer.sum(), ).get();
var sum = means.multiply(counts).reduce(ee.Reducer.sum(), ).get();
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(), ).get();
var aMeans = means.slice(0, 0, i);
var aMean = aMeans.multiply(aCounts)
.reduce(ee.Reducer.sum(), ).get()
.divide(aCount);
var bCount = total.subtract(aCount);
var bMean = sum.subtract(aCount.multiply(aMean)).divide(bCount);
bCount.multiply(bMean.subtract(mean).pow(2)));
});

print(ui.Chart.array.values(ee.Array(bss), 0, means));

// Return the mean value corresponding to the maximum BSS.
return means.sort(bss).get([-1]);
};

var threshold = otsu(histogram.get(s1_band+'_histogram'));
print('threshold', threshold);
``````

Note on a tripping hazard for calculating the occurence:

The .filterBounds method based of an area of interest also selects truncated satellite images. Unfortunately I have no solution to prevent this.

Example of a truncated image

After some research and help, I finally have the solution to the described problem, which I also want to share with the community.

With the following line of code I could filter the undesired images:

``````.filter(ee.Filter.contains({leftField: ".geo", rightValue: aoi})) // Filter partial S1-Images of AOI
``````
• Nice work Stephan Feb 3, 2020 at 8:42

I think I found an error in the area chart:

``````*// Create and print a histogram chart
//Make time series of water pixels as area in km² within region
var ClassChart = ui.Chart.image.series({