前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >遥感影像线性插值(基于GEE平台)

遥感影像线性插值(基于GEE平台)

作者头像
GIS与遥感开发平台
发布于 2022-12-03 01:53:46
发布于 2022-12-03 01:53:46
1.9K00
代码可运行
举报
运行总次数:0
代码可运行

线性插值填补空缺值

遥感影像中总是由于各种各样的原因会出现空缺值,包括云污染、传感器损坏呀之类的。最简单的方法当然还是利用线性插值的方法进行插补啦,就是利用缺失影像前后日期的数据进行线性插值,之后对缺失影像进行填补。今天我们就用GEE简单的实现一下这个方法。 这次我们对Sentinel-2的进行插补

准备数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var geometry = ee.Geometry.Polygon([[
  [82.60642647743225, 27.16350437805251],
  [82.60984897613525, 27.1618529901377],
  [82.61088967323303, 27.163695288375266],
  [82.60757446289062, 27.16517483230927]
]]); 
Map.addLayer(geometry, {color: 'red'}, 'Farm')
Map.centerObject(geometry)
var s2 = ee.ImageCollection("COPERNICUS/S2_SR");
var filtered = s2
  .filter(ee.Filter.date('2019-01-01', '2020-01-01'))
  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
  .filter(ee.Filter.bounds(geometry))
// 数据去云处理
function maskCloudAndShadowsSR(image) {
  var cloudProb = image.select('MSK_CLDPRB');
  var snowProb = image.select('MSK_SNWPRB');
  var cloud = cloudProb.lt(5);
  var snow = snowProb.lt(5);
  var scl = image.select('SCL'); 
  var shadow = scl.eq(3); // 3 = cloud shadow
  var cirrus = scl.eq(10); // 10 = cirrus
  var mask = (cloud.and(snow)).and(cirrus.neq(1)).and(shadow.neq(1));
  return image.updateMask(mask).divide(10000)
      .select("B.*")
      .copyProperties(image, ["system:time_start"]);
}
var filtered = filtered.map(maskCloudAndShadowsSR)

增加时间信息的波段

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var filtered = filtered.map(function(image) {
  var timeImage = image.metadata('system:time_start').rename('timestamp')
  var timeImageMasked = timeImage.updateMask(image.mask().select(0))
  return image.addBands(timeImageMasked)
})

对影像进行匹配

这只进行插值的核心步骤,我们对每个影像匹配其前几天的影像数据与后几天的影像数据,这个间隔天数可以自主设置。需要注意的是GEE里面使用Join进行匹配,匹配的时间单位是毫秒,这个我们需要把时间单位搞清楚。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//定义两个join,一个是距离目标影像30天范围内,并且是日期在目标影像之前,
//另一个是在目标影像之后的
var days = 30
var millis = ee.Number(days).multiply(1000*60*60*24)
var maxDiffFilter = ee.Filter.maxDifference({
  difference: millis,
  leftField: 'system:time_start',
  rightField: 'system:time_start'
})
var lessEqFilter = ee.Filter.lessThanOrEquals({
  leftField: 'system:time_start',
  rightField: 'system:time_start'
})
var greaterEqFilter = ee.Filter.greaterThanOrEquals({
  leftField: 'system:time_start',
  rightField: 'system:time_start'
})

var filter1 = ee.Filter.and(maxDiffFilter, lessEqFilter)
 
var join1 = ee.Join.saveAll({
  matchesKey: 'after',
  ordering: 'system:time_start',
  ascending: false})
   
var join1Result = join1.apply({
  primary: filtered,
  secondary: filtered,
  condition: filter1
})
var filter2 = ee.Filter.and(maxDiffFilter, greaterEqFilter)
 
var join2 = ee.Join.saveAll({
  matchesKey: 'before',
  ordering: 'system:time_start',
  ascending: true})
   
var join2Result = join2.apply({
  primary: join1Result,
  secondary: join1Result,
  condition: filter2
})

准备插值!

插值公式 y = y1 + (y2-y1)*((t – t1) / (t2 – t1)) y = 需要插值的数据 y1 = 目标之前数据,>y2 = 目标之前数据 t 其所对应的时间信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var interpolateImages = function(image) {
  var image = ee.Image(image)
  // 把匹配的数据合成一个影像
  var beforeImages = ee.List(image.get('before'))
  var beforeMosaic = ee.ImageCollection.fromImages(beforeImages).mosaic()
  var afterImages = ee.List(image.get('after'))
  var afterMosaic = ee.ImageCollection.fromImages(afterImages).mosaic()

  var t1 = beforeMosaic.select('timestamp').rename('t1')
  var t2 = afterMosaic.select('timestamp').rename('t2')
  var t = image.metadata('system:time_start').rename('t')
  var timeImage = ee.Image.cat([t1, t2, t])
  var timeRatio = timeImage.expression('(t - t1) / (t2 - t1)', {
    't': timeImage.select('t'),
    't1': timeImage.select('t1'),
    't2': timeImage.select('t2'),
  })
  // 计算插值数据
  var interpolated = beforeMosaic
    .add((afterMosaic.subtract(beforeMosaic).multiply(timeRatio)))
  var result = image.unmask(interpolated)
  return result.copyProperties(image, ['system:time_start'])
}

结果呈现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var interpolatedCol = ee.ImageCollection(
  join2Result.map(interpolateImages
  
function addNDVI(image) {
  var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
  return image.addBands(ndvi);
}

var ndviVis = {min:0, max: 0.9,  palette: [
    'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
    '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
    '012E01', '011D01', '011301'
  ]}

var visualizeImage = function(image) {
  return image.select('ndvi').visualize(ndviVis).clip(geometry)
}

var visCollectionOriginal = filtered
  .map(addNDVI)
  .map(visualizeImage)
var visCollectionInterpolated = interpolatedCol
  .map(addNDVI)
  .map(visualizeImage)

var videoArgs = {
  dimensions: 400,
  region: geometry,
  framesPerSecond: 1,
  crs: 'EPSG:3857',
};

print('Original NDVI Images', visCollectionOriginal.getVideoThumbURL(videoArgs))
print('Gap Filled NDVI Images', visCollectionInterpolated.getVideoThumbURL(videoArgs))
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GIS与遥感开发平台 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验