基于GEE平台提取水体

本文主要介绍如何利用GEE平台与哨兵2号影像提取水体。水体的提取主要是基于NDWI指数进行,当然,通过改变波段运算,也可以根据MNDWI进行提取。主要代码如下:
下面展示一些 内联代码片

//首先对数据进行去云处理   
var s2_rmcloud = function(image) {
 var quality = image.select("QA60").unmask();
 return image.updateMask(quality.eq(0));
};
//NDWI
var s2_ndwi = function(image) {
 return image.addBands(image.normalizedDifference(["B3", "B8"]).rename("NDWI"));
};
//筛选数据 

var s2_nocloud = s2_col.map(s2_rmcloud)
                       .filterBounds(roi)
                       .filterDate("2020-11-20", "2020-11-25");
var ndwi = s2_nocloud.map(s2_ndwi).select("NDWI").reduce(ee.Reducer.mean()).clip(roi);
print(ndwi)
var visParam = {
 min: -0.5,
 max: 0.5,
 palette: ['00FFFF', '0000FF']
};
Map.addLayer(ndwi, visParam, "ndwi");
Map.centerObject(roi,12);
//otsu算法 
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([0]);
  var total = counts.reduce(ee.Reducer.sum(), [0]).get([0]);
  var sum = means.multiply(counts).reduce(ee.Reducer.sum(), [0]).get([0]);
  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(), [0]).get([0]);
    var aMeans = means.slice(0, 0, i);
    var aMean = aMeans.multiply(aCounts)
        .reduce(ee.Reducer.sum(), [0]).get([0])
        .divide(aCount);
    var bCount = total.subtract(aCount);
    var bMean = sum.subtract(aCount.multiply(aMean)).divide(bCount);
    return aCount.multiply(aMean.subtract(mean).pow(2)).add(
           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]);
};
//归一化,去除异常值  
function normalization(image,region,scale){
var mean_std = image.reduceRegion({
  reducer: ee.Reducer.mean()
            .combine(ee.Reducer.stdDev(),null, true),
  geometry: region,
  scale: scale,
  maxPixels: 1e13,
  // tileScale: 16
}); 
var unitScale = ee.ImageCollection.fromImages(
  image.bandNames().map(function(name){
    name = ee.String(name);
    var band = image.select(name);
    var mean=ee.Number(mean_std.get(name.cat('_mean')));
    var std=ee.Number(mean_std.get(name.cat('_stdDev')));
    var max=mean.add(std.multiply(3))
    var min=mean.subtract(std.multiply(3))
    var band1=ee.Image(min).multiply(band.lt(min)).add(ee.Image(max).multiply(band.gt(max)))
                        .add(band.multiply(ee.Image(1).subtract(band.lt(min)).subtract(band.gt(max))))
    var result_band=band1.subtract(min).divide(max.subtract(min));
    return result_band;
})).toBands().rename(image.bandNames());
  return unitScale;
}
var ndwi2=ndwi.select('NDWI_mean')
var ndwi3=normalization(ndwi2,roi,10)
var ndwi1=ndwi3.multiply(10000)
print(ndwi1)
var histogram = ndwi1.select('NDWI_mean').reduceRegion({
  reducer: ee.Reducer.histogram(255, 2)
      .combine('mean', null, true)
      .combine('variance', null, true), 
  geometry: roi, 
  scale: 10,
  bestEffort: true
});
print(Chart.image.histogram(ndwi1.select('NDWI_mean'), roi, 12));
print(histogram);
var threshold = otsu(histogram.get('NDWI_mean_histogram'));
print('threshold', threshold);
var water_mask = ndwi1.select('NDWI_mean').gt(threshold);

Map.addLayer(water_mask.mask(water_mask), {palette: 'red'}, 'water');
Export.image.toDrive({
  image: water_mask.mask(water_mask),
  description: "202009",
  folder:"UltimateS2_R2",
  fileNamePrefix: "202009",
  scale: 10,
  region:roi,
  maxPixels: 1e13});
  Map.addLayer(water_mask.mask(water_mask), {palette: 'red'}, 'class A');
var countDictionary = water_mask.mask(water_mask).reduceRegion({
  reducer: ee.Reducer.count(),
  geometry: roi,
  scale: 10,
  maxPixels: 1e13
});
//把统计结果打印出来
print(countDictionary);

虽然看着很长,但是基本思想时利用阈值法提取水体,借鉴了Otsu算法确定阈值,另外加了剔除异常值的归一化算法。
基于哨兵2号1-C的数据源,作者在写代码的时候发现哨兵2号2A和哨兵2号1C的数据在去云后数据数量上不相同了,暂时不知道是什么原因,欢迎各位小伙伴来交流哇。

  • 17
    点赞
  • 152
    收藏
    觉得还不错? 一键收藏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值