[GIS] Water pixel detection in Landsat imagery using Google Earth Engine

google-earth-enginegoogle-earth-engine-javascript-apinormalized-difference-water-index

I want to extract or detect water bodies in a selected region using the relationship between water and vegetation indices, and these water and vegetation indices were calculated by using the cloud and snow free Landsat TM, ETM+ & OLI surface reflectance images based on the spectral bands and equation of mNDWI, NDVI & EVI. How can I use this code to solve this task?

Import the "selectedCountry" boundary region

var countries = ee.FeatureCollection('ft:1tdSwUL7MVpOauSgRzqVTOwdfy17KDbw-1d9omPw');
Map.addLayer(selectedCountry);
// Load Footprint of Landsat WRS-2 grids
var wrs2_descending = ee.FeatureCollection('ft:1_RZgjlcqixp-L9hyS6NYGqLaKOlnhSC35AB5M5Ll');

// get the Country names
var names = countries.aggregate_array('Country');

// Initialize a selection field 
// Once a country has been selected, the redraw function is going
var select = ui.Select({items: names.getInfo(), onChange: redraw });

//select.setPlaceholder('Choose a country ...'); 

// Add the drop-down 'select' widget to the map
Map.add(select);
function redraw(key){

  // get the selected country
  //var selectedCountry = ee.Feature(countries.filter(ee.Filter.eq('Country', key)).first());
  Map.centerObject(selectedCountry);

  // store the name of the selected country
  var selectedCountry_Strg = ee.String(selectedCountry.get('Country'))

  // add the country geometry to the map
  var layer0 = ui.Map.Layer(selectedCountry, {color:'purple'}, 'Selected country');
  Map.layers().set(0, layer0);

  // filter the WRS-2 grids from the selected country footprint and add the grids to the map
  var wrs2_filtered = wrs2_descending.filterBounds(selectedCountry.geometry());
  var layer1 = ui.Map.Layer(wrs2_filtered,{color:'blue'}, 'WRS2 filtered');
  Map.layers().set(1, layer1);
  var a1 ='1986-01-01';
  var a2 ='1998-09-20';
  var a3 ='1998-09-23';
  var a4 ='2019-12-31';
  var b1 = ee.Filter.date(a1,a2);
  var b2 = ee.Filter.date(a3,a4);



var l4_coll = ee.ImageCollection('LANDSAT/LT4_L1T_TOA');  //Aug 22, 1982 - Dec 14, 1993
var l5_coll = ee.ImageCollection('LANDSAT/LT5_L1T_TOA').filter(ee.Filter.or(b1,b2));
var l7_coll = ee.ImageCollection('LANDSAT/LE7_L1T_TOA');  //Jan 1, 1999 - Apr 30, 2017
var l8_coll = ee.ImageCollection('LANDSAT/LC8_L1T_TOA');  //Apr 11, 2013 - Apr 30, 2017

var merged_collection = ee.ImageCollection(l4_coll.merge(l5_coll)
.merge(l7_coll).merge(l8_coll));

// filter the ImageCollection with the boundary of the selected country
var iC = merged_collection.filterBounds(selectedCountry.geometry());
iC = iC.map(function(img){
var year  = img.date().format("Y");            // get the acquisition year
var CC = img.get('CLOUD_COVER');
return img.set('year', ee.Number.parse(year)).set('clouds', ee.Number.parse(CC)); // 
});
}

Best Answer

There are a number of ways you can do this.

  • If you use the Landsat surface reflectance collections, you can extract water from the CFmask QA band associated with each image. Here is a toy example:
// Define area of interest.
var aoi = ee.Geometry.Point([-95.82, 46.84]);

// Import Landsat 8 surface reflectance collection.
var l8SrCol = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR');

// Filter collection to area and date.
var img = l8SrCol
 .filterBounds(aoi)
 .filterDate('2019-06-01', '2019-10-01')
 // for this example, get the first least cloudy image.
 .sort('CLOUD_COVER')
 .first();

// Select the image's CFmask band and make all water pixels value 1, all else 0.
var mask = img.select('pixel_qa').bitwiseAnd(4).neq(0);

// Display results to map.
Map.centerObject(img, 8);
Map.addLayer(img, {bands: ['B6', 'B5', 'B4'], min:100, max:4000});
Map.addLayer(mask);

enter image description here

Code Editor script

  • Train a model to predict water pixels from your derived vegetation and water indices. See the Earth Engine Developer guide Supervised Classification page.

  • Use image band histogram slicing to distinguish water from non-water. See this Earth Engine UI example to understand the concept and help pick band threshold values that separate water from non-water.

Related Question