0

I'm trying to extract water located in mountainous areas using Landsat satellite images in GEE. But the method I used will misclassify terrain shadow as water. I try to use DEM to remove terrain shadow, however, there are some errors in my code.

Here is the code:

//-----------------------------------------------------------------------------------

var roi = ee.Geometry.Polygon([
  [[100.6636076429711,26.655075483873333], 
  [98.75836472304923,26.655075483873333],
  [98.75836472304923,22.839494424963217], 
  [100.6636076429711,22.839494424963217], 
  [100.6636076429711,26.655075483873333]]]);

Map.centerObject(roi)

var sDate_T1 = "2014-01-01";
 
var eDate_T1 = "2014-12-31"; 

var bn8 = ['B1', 'B2', 'B3', 'B4', 'B6', 'pixel_qa', 'B5', 'B7'];

var bn7 = ['B1', 'B1', 'B2', 'B3', 'B5', 'pixel_qa', 'B4', 'B7'];

var bns = ['uBlue', 'Blue', 'Green', 'Red', 'Swir1', 'BQA', 'Nir', 'Swir2'];

var ls7 = (ee.ImageCollection("LANDSAT/LE07/C01/T1_SR")
  .filterDate('1999-04-15', '2003-05-30')
  .select(bn7, bns));

var ls8 = ee.ImageCollection("LANDSAT/LC08/C01/T1_SR").select(bn8, bns);

var merged = ls7.merge(ls8);

var Ndvi = function(image) {
  var ndvi = image.normalizedDifference(['Nir', 'Red']).rename('ndvi');
  return(ndvi);
};

var Mndwi = function(image) {
  var mndwi = image.normalizedDifference(['Green', 'Swir1']).rename('mndwi');
  return(mndwi);
};

var Evi = function(image) {
  var evi = image.expression('2.5 * (Nir - Red) / (1 + Nir + 6 * Red - 7.5 * Blue)', {
    'Nir': image.select(['Nir']),
    'Red': image.select(['Red']),
    'Blue': image.select(['Blue'])
    });
  return(evi.rename(['evi']));
};

var params_true = {crs: 'EPSG:4326', region: roi, min: 0.0, max: 0.3, bands: ["Red", "Green", "Blue"], dimensions: 1000};

var waterViz = {min: 0, max: 1, palette: ['white', 'blue']};

var imgCloud = merged.filterDate(sDate_T1, eDate_T1) 
                 .filterBounds(roi)
                 .map(function(image) { 
                    var cloudsBitMask = 1 << 3; 
                    var cloudShadowBitMask = 1 << 4;
                    var snowBitMask = 1 << 5; 
                    var qa = image.select('BQA'); 
                    var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0) 
                                 .and(qa.bitwiseAnd(cloudsBitMask).eq(0))
                                 .and(qa.bitwiseAnd(snowBitMask).eq(0)); 
                    return image.updateMask(mask).multiply(0.0001).clip(roi)
                   }); 

//----------------------------------------------------------------------------

var dem = ee.Image('USGS/SRTMGL1_003');

function hillshade(image) {
  var elevation = dem.clip(roi)
  var azimuth = image.getNumber('SUN_AZIMUTH')
  var zenith = ee.Number(100).subtract(image.getNumber('SUN_ELEVATION'))
  var shaded_relief = ee.Terrain.hillShadow(elevation, azimuth, zenith)
  return image.updateMask(shaded_relief);
}

var imgCol = imgCloud.map(hillshade);

function shade(image) {
  var elevation = dem.clip(roi)
  var azimuth = image.getNumber('SUN_AZIMUTH')
  var zenith = ee.Number(100).subtract(image.getNumber('SUN_ELEVATION'))
  var shaded_relief = ee.Terrain.hillShadow(elevation, azimuth, zenith)
  return image.updateMask(shaded_relief.not());
}

var hillshademask = imgCloud.map(shade);

//--------------------------------------------------------------------------

var bnp50 = ['uBlue_p50', 'Blue_p50', 'Green_p50', 'Red_p50', 'Swir1_p50', 'BQA_p50', 'Nir_p50', 'Swir2_p50'];

var p50 = imgCol.reduce(ee.Reducer.percentile([50])).select(bnp50, bns);

var mndwi_p50 = Mndwi(p50);

var ndvi_p50 = Ndvi(p50);

var evi_p50 = Evi(p50);

var water_p50 = (mndwi_p50.gt(ndvi_p50).or(mndwi_p50.gt(evi_p50))).and(evi_p50.lt(0.1));

var waterMasked_p50 = water_p50.updateMask(water_p50.gt(0));

var True_colour = p50.select(["Red", "Green", "Blue"]);

var Wetted_channel = waterMasked_p50;

Map.addLayer(True_colour.clip(roi), params_true, 'True colour temporal composite', false);

Map.addLayer(hillshademask.median().clip(roi), params_true, 'hillshade mask', false);

Map.addLayer(Wetted_channel, waterViz, 'Wetted channel', false)

//--------------------------------------------------------------------------------------

The error is displayed as:

Layer error: ImageCollection.reduce: Error in map(ID=null): Number.subtract: Parameter 'right' is required.

How can I solve the problem?

1 Answer 1

0

The problem is that the images within the image collection you are using don't have the SUN_ELEVATION or SUN_AZIMUTH properties. More importantly, that image collection is deprecated, in favor of the Collection 02:

var bn8 = ['SR_B1', 'SR_B2', 'SR_B3', 'SR_B4', 'SR_B6', 'QA_PIXEL', 'SR_B5', 'SR_B7'];

var bn7 = ['SR_B1', 'SR_B1', 'SR_B2', 'SR_B3', 'SR_B5', 'QA_PIXEL', 'SR_B4', 'SR_B7'];

var bns = ['uBlue', 'Blue', 'Green', 'Red', 'Swir1', 'BQA', 'Nir', 'Swir2'];

var ls7 = (ee.ImageCollection("LANDSAT/LE07/C02/T1_L2")
  .filterDate('1999-04-15', '2003-05-30')
  .select(bn7, bns));

var ls8 = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2").select(bn8, bns);

Another problem is that ee.Image.multiply() doesn't keep properties, e.g.:

var foo = ee.Image(1).set({"property":"bar"})
print(foo)
print(foo.multiply(1))   // Doesn't show the property "bar"
print(foo.multiply(1).copyProperties(foo)) 

At the same time, because you will be using C02 instead of C01, the scaling factors are different. So you can add .copyProperties and update the scaling factors in the same line:

var imgCloud = merged.filterDate(sDate_T1, eDate_T1) 
                 .filterBounds(roi)
                 .map(function(image) { 
                    var cloudsBitMask = 1 << 3; 
                    var cloudShadowBitMask = 1 << 4;
                    var snowBitMask = 1 << 5; 
                    var qa = image.select('BQA'); 
                    var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0) 
                                 .and(qa.bitwiseAnd(cloudsBitMask).eq(0))
                                 .and(qa.bitwiseAnd(snowBitMask).eq(0)); 
                    return image.updateMask(mask).multiply(2.75e-05).add(-0.2).clip(roi).copyProperties(image)
                   });

Here is the complete code with these changes:

https://code.earthengine.google.com/fb057ca8d7e984a4857d8336c249ebee

5
  • Thanks for your great answer! The problem has been solved.
    – YX Zhao
    Commented Aug 3, 2023 at 1:23
  • Glad it worked out. Would you mind marking the answer as accepted? Commented Aug 3, 2023 at 8:26
  • Certainly. How should I mark the answer as accepted? Sorry I don't know how to do.
    – YX Zhao
    Commented Aug 7, 2023 at 8:36
  • stackoverflow.com/help/someone-answers Commented Aug 7, 2023 at 10:35
  • Oh I get it now. Thanks!
    – YX Zhao
    Commented Aug 7, 2023 at 12:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.