0

I plan to obtain the range and area of water bodies from Dynamic World products. But the water area I calculated in GEE does not match the obtained water range. In other words, the water range extracted by my code is significantly larger than the water area calculated by GEE based on the 'water' band, and this area value is different from its area after vectorization in ArcGIS. I don't know where the problem lies, here is my code https://code.earthengine.google.com/85a51959dee944bfca9397dac2ed5799

var roi = table;
var styling = { color: "red", fillColor: "00000000" };
Map.centerObject(roi,12)
Map.addLayer(roi,styling,'roi');

var start = '2019-1-1';
var end = '2020-1-1';

var colFilter = ee.Filter.and(
    ee.Filter.bounds(roi),
    ee.Filter.date(start, end));
    
var dwCol = ee.ImageCollection('GOOGLE/DYNAMICWORLD/V1').filter(colFilter);
print('dwCol',dwCol)

var s2Col = ee.ImageCollection('COPERNICUS/S2_SR')
                  .filterBounds(roi)
                  .filterDate(start, end)
                  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))
print('s2Col',s2Col)

function mosaicByDate(imcol){
  var imlist = imcol.toList(imcol.size())
  //print('imlist',imlist)

  var unique_dates = imlist.map(function(im){
    return ee.Image(im).date().format("YYYY-MM-dd")
  }).distinct()
  //print('unique_dates',unique_dates)
  var mosaic_imlist = unique_dates.map(function(d){
    d = ee.Date(d)
    //print(d)
    var im = imcol
      .filterDate(d, d.advance(1, "day"))
      .mosaic()
      .set(
        "system:time_start", d.millis(),
        "system:id", d.format("YYYY-MM-dd")
      )
      .set("system:index", imcol.filterDate(d, d.advance(1, "day")).first().id()); // Preserve the original system:index of the image
    
    //print(im)
    return im
    // .set(
    //     "system:time_start", d.millis(), 
    //     "system:id", d.format("YYYY-MM-dd"))
  })

  return ee.ImageCollection(mosaic_imlist)
}

var dwVisParams = {
  min: 0,
  max: 8,
  palette: ['#419BDF', '#397D49', '#88B053', '#7A87C6',
    '#E49635', '#DFC35A', '#C4281B', '#A59B8F', '#B39FE1']
};

// Clip the composite and add it to the Map
Map.addLayer(dwCol.select('water'), dwVisParams, 'Classified Composite')

// Compute water area
function calculateWaterArea(image) {
  
  // Select water mask
  var waterMask = image.select('water');
  
  // Calculate water area (unit: square meters)
  var waterArea = waterMask.multiply(ee.Image.pixelArea()).reduceRegion({
    reducer: ee.Reducer.sum(),
    geometry: roi,
    scale: 10,
    bestEffort: true
  });

  // // Add water area and range properties to image metadata
  image = image.set('waterArea_sqm', waterArea.get('water'));
  
  return image;
}
var s2Mosaic = mosaicByDate(s2Col)
// print('s2Mosaic',s2Mosaic)
var dwMosaic = mosaicByDate(dwCol)
// print('dwMosaic',dwMosaic)

var DW_withWaterArea = dwMosaic.map(calculateWaterArea);
print('DW_withWaterArea', DW_withWaterArea);

var image = DW_withWaterArea.first().select('label')
var projection = image.projection();
print('projection',projection)

// Function to format date as YYYYMMDD
function formatDate(dateString) {
  // Extract date from system:index string
  var date = ee.Date(ee.String(dateString).slice(0, 8));
  
  var year = ee.Number(date.get('year')).format('%04d');
  var month = ee.Number(date.get('month')).format('%02d');
  var day = ee.Number(date.get('day')).format('%02d');
  
  return ee.String(year).cat(month).cat(day);
}

// Export water area information to a CSV file
function exportWaterAreaCSV(image) {
  var index = image.get('system:index');
  var formattedDate = formatDate(index);
  var waterArea = image.get('waterArea_sqm');
  
  // Print formatted date and water area
  //print('Date:', formattedDate, 'Water Area (sqm):', waterArea);
  
  // Return a feature containing the exported properties
  return ee.Feature(null, {
    'Date': formattedDate,
    'Water_Area_m3': waterArea
  });
}

// Apply the export function to the S2_withWaterArea collection
var waterAreaFeatures = DW_withWaterArea.map(exportWaterAreaCSV);

// Create a feature collection from the features
var waterAreaFeatureCollection = ee.FeatureCollection(waterAreaFeatures);

// Export the feature collection to a CSV file
Export.table.toDrive({
  collection: waterAreaFeatureCollection,
  description: '2019Esk_DWWater_area',
  folder: 'EskDW', // Change to desired folder name
  fileFormat: 'CSV'
});

// Export water images iteratively
function exportImageCollection(imgCol) {
  var indexList = imgCol.reduceColumns(ee.Reducer.toList(), ["system:index"])
                        .get("list");
  indexList.evaluate(function(indexs) {
    for (var i=0; i<indexs.length; i++) {
      var image = imgCol.filter(ee.Filter.eq("system:index", indexs[i])).first();
      image = image.toInt16();
      Export.image.toDrive({
        image: image.select('label'),
        description: "DW_Esk_"+indexs[i],
        fileNamePrefix: "DW_Esk_"+indexs[i],
        folder: 'DW_Esk',
        region: roi,
        scale: 10,
        maxPixels: 1e13,
        fileFormat: 'GeoTIFF'
      });
    }
  });
}
exportImageCollection(dwMosaic);

1 Answer 1

2

The water band is a probability, not a 0/1 mask. But you're multiplying the area times that probability. So your numbers are meaningless. You need to figure out how you intend to identify water (use a threshold or find the class with the highest probability are good options), and turn that into a 0/1 image, first.

1
  • I understand. Based on your answer, I calculated the water area using class with the highest probability. Thank you very much for your help@NoelGorelick
    – Holly
    Mar 11 at 3:10

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.