基于GEE与哨兵1号影像数据提取水体

在进行光学数据提取水体时,常会发现部分时间、部分区域内由于云的存在而出现大面积的空白区域,从而使得我们提取水体面积过程中存在不精确的问题。因此,基于微波数据进行云的提取就成为我们较好的一个选择,通过阅读各种文献以及实践,我在原有基于GEE平台和哨兵1号影像提取水体代码的基础上,进行了部分补充,从而使得提取水体的精度更加准确。代码如下所示:

原文链接:基于GEE与哨兵1号影像数据提取水体

// An highlighted blockvar slope_lib = require('users/wushupu18/Nanhu:slope_correction_lib.js');var start = '2020-04-01';var end = '2020-04-30';Map.centerObject(Buffer, 12);var s1_collection = ee.ImageCollection('COPERNICUS/S1_GRD')    .filterBounds(Buffer)    .filterDate(start, end)    .filter(ee.Filter.and(    ee.Filter.listContains('transmitterReceiverPolarisation', 'VV'),    ee.Filter.listContains('transmitterReceiverPolarisation', 'VH'),    ee.Filter.eq('instrumentMode', 'IW')    ));print(s1_collection)//地形校正 var volume = slope_lib.slope_correction(s1_collection,     {'model': 'volume',     'elevation': ee.Image('USGS/SRTMGL1_003'),     'buffer': 50           });var surface = slope_lib.slope_correction(s1_collection,    {'model': 'surface',     'elevation': ee.Image('USGS/SRTMGL1_003'),     'buffer': 50          });print(s1_collection.mean(), 'First image of the original S1 collection')print(volume.mean(), 'First image of the corrected S1 collection');print(volume.mean(), 'First image of the corrected S1 collection');var S1 = volume.map(function(img){
   
      img = img.clip(Buffer)   return img; });Map.addLayer(S1.mean(),{bands: 'VV',min: -18, max: 0}, 'S1')var filterSpeckles = function(img) {
   
   var vv = img.select('VV') var vh= img.select('VH')//滤波处理 var vv_smoothed = vv.focal_mean(50,'circle','meters').rename('VV_Filtered')var vh_smoothed = vh.focal_mean(50,'circle','meters').rename('VH_Filtered')return img.addBands(vv_smoothed).addBands(vh_smoothed)}S1 = S1.map(filterSpeckles)Map.addLayer(S1.mean(),{bands: 'VV_Filtered',min: -30, max: 0}, 'Filtered SAR image')var SVV = S1.select("VV_Filtered").reduce(ee.Reducer.mean()).rename("VV_mean");var SVH = S1.select("VH_Filtered").reduce(ee.Reducer.mean()).rename("VH_mean");;var Sen1=SVV.addBands(SVH)print(Sen1)//SDWIfunction SDWI_V1(Sen1) {
   
   var VH = Sen1.select("VH_mean");var VV = Sen1.select("VV_mean");var x = VV.multiply(VH).multiply(10);var y=(x).log();var sdwi=y.subtract(8);return sdwi;}var sdwi1 = SDWI_V1(Sen1).select("VV_mean").rename("sdwi");print(sdwi1)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);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 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: 10e9,}); 
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 sdwi2=sdwi1.select('sdwi')var sdwi3=normalization(sdwi2,Buffer,10)var sdwi_1=sdwi3.multiply(10000)print(sdwi1)var histogram = sdwi_1.select('sdwi').reduceRegion({
   
   reducer: ee.Reducer.histogram(255, 2)     .combine('mean', null, true)      .combine('variance', null, true),  geometry: Buffer,   scale: 10, bestEffort: true});print(Chart.image.histogram(sdwi_1.select('sdwi'), Buffer, 10));print(histogram); var threshold = otsu(histogram.get('sdwi_histogram'));print('threshold', threshold);var classA = sdwi_1.select('sdwi').gt(threshold);
Map.addLayer(classA.mask(classA), {palette: 'red'}, 'class A');var countDictionary = classA.mask(classA).reduceRegion({
   
     reducer: ee.Reducer.count(),   geometry: Buffer,  scale: 10,   maxPixels: 1e13 });print(countDictionary);

经过实验发现,哨兵1号影像在平坦的地区适用性较好,但是在山地地区,常会出现阴影被误判成山体的情况。代码中参考前人研究成果,加入了地形校正去除阴影的处理,但是提升有限,部分阴影并不能完全去除。大家在用代码时,尽量结合自己的研究区进行修改参数,从而使得提取效果更好。

猜你喜欢

转载自blog.csdn.net/weixin_58566962/article/details/128224502