Yeah! mapping with a 10m spatial resolution.

Both new Sentinel-1 and Sentinel-2 satellites take measurements of the earth with a very high spatial and good temporal resolution. These data are very useful for mapping landuse and landuse change. This tutorial show how simple algorithms can be used to identify areas with water, dense vegetation, settlements and rice paddies.

1. Import the Sentinel-1 and Sentinel-2 ImageCollection.


2. Define the geographic and temporal domain.

// Define period
var startdate = ee.Date.fromYMD(2014,1,1);
var enddate = ee.Date.fromYMD(2016,12,1);

// Define geograpic domain
var Ca = ee.FeatureCollection('ft:1T7GmJ0tJCu4QwclY5qiG9EGBFgNhhNjttq8F7gQm');

3. Filter the data.

// filter s2 data</pre>
var Sentinel2 = s2.filterBounds(Ca)
.filterDate(startdate, enddate)

// filter s1 data
var Sentinel1 =  ee.ImageCollection('COPERNICUS/S1_GRD')
.filterDate(startdate, enddate)
.filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VV'))

4. remove the clouds from Sentinel-2

// cloud function to remove clouds
var cloudfunction_ST2 = function(image){
  //use add the cloud likelihood band to the image
  var quality ="QA60").unmask();
  //get pixels above the threshold
  var cloud01 =;
  //create a mask from high likelihood pixels
  var cloudmask = image.mask().and(cloud01.not());
  //mask those pixels from the image
  return image.updateMask(cloudmask);

// remove the clouds
var ST2_nocloud =;

5. Calculate the NDBI, NDVI and NDWI from the median of Sentinel-2

// take the median
var st2median = ST2_nocloud.median();

// the normalized difference bare index
var ndbi = st2median.normalizedDifference(['B12', 'B8']);

// the normalized difference vegetation index
var ndvi = st2median.normalizedDifference(['B8', 'B4']);

// the normalize difference water index
var ndwi = st2median.normalizedDifference(['B3', 'B8']);

6. Set the threshold for the indices.

// define thresholds
var bareThreshold = -0.32
var vegetationThreshold = 0.65
var waterThreshold = 0.2

7. Add the different layers to the canvas.

// show the urban area
var ndbi_th =
var myndbi = ndbi_th.updateMask(ndbi_th).clip(Ca)
var ndbi_viz = {palette:"111101"};
Map.addLayer(myndbi, ndbi_viz, 'Urban');

// show the water areas
var ndwi_th =
var myndwi = ndwi_th.updateMask(ndwi_th).clip(Ca)
var ndwi_viz = {palette:"24069b"};
Map.addLayer(myndwi, ndwi_viz, 'Water');

// show the forests
var ndvi_th =
var myndvi = ndvi_th.updateMask(ndvi_th).clip(Ca)
var ndvi_viz = {palette:"006b0c"};
Map.addLayer(myndvi, ndvi_viz, 'Vegetation');

8. Compare the wet from the dry conditions using a reducer function on the sentinel-1 images.

// create a map of the wet and dry conditions from sentinel-1
var wet = Sentinel1.reduce(ee.Reducer.percentile([10]))
var dry = Sentinel1.reduce(ee.Reducer.percentile([90]))

9. Identify the rice paddies which are inundated in the wet season, but dry in the dry season.

// calculate the difference between wet and dry conditions
var paddies = wet.subtract(dry)

10. Mountains can be identified as rice paddies, so we remove all slopes greater than 2 degrees.

// remove the mountains from the data
var hydrosheds = ee.Image('WWF/HydroSHEDS/03VFDEM');
var terrain = ee.Algorithms.Terrain(hydrosheds);
var slope ='slope');

// remove all slopes greater then 2 degrees
paddies = paddies.updateMask(;

11. Also add the paddies to the map based on the threshold of -8.

// set the paddy threshold
var paddies_th = -8;

// select areas smaller than the threshold
var paddies_th =;

// mask the areas that are not rice paddies
var mypaddies = paddies_th.updateMask(paddies_th).clip(Ca)

var paddies_viz = {palette:"c2c64d"};
Map.addLayer(mypaddies, paddies_viz, 'Rice');

Find the full script here.