GEE 时序插值实现MODIS 8天无云影像代码免费分享

本文利用MOD09Q1数据,通过GEE算法实现8天每景无云遥感影像,全年共计46景。算法珍贵,与君共享。文章代码大部分来源于https://code.earthengine.google.com/7eb9f43fd3da7fdfda5bfe432a5316e7?noload=true 算法扩展性强,可以利用于Landsat系列和Sentinel-2系列,代码:

var mod_sr = ee.ImageCollection("MODIS/006/MOD09Q1"),
    point = /* color: #d63000 */ee.Geometry.Point([104.12108820077502, 30.576261504840417]),
    table = ee.FeatureCollection("China_province_2019");
var roi = table.filter(ee.Filter.eq('provinces','sichuan'))
Map.centerObject(roi,6)
function replace_mask(img, newimg, nodata) {
    nodata   = nodata || 0;
    var mask = img.mask();
    img = img.unmask(nodata);
    img = img.where(mask.not(), newimg);
    img = img.updateMask(img.neq(nodata));
    return img;
}
/** Interpolation not considering weights */
function addTimeBand(img) {
    /** make sure mask is consistent */
    var mask = img.mask();
    var time = img.metadata('system:time_start').rename("time").mask(mask);
    return img.addBands(time);
}
var getQABits = function(image, start, end) {
    var pattern = 0;
    for (var i = start; i <= end; i++) {
       pattern += 1 << i;
    }
    // Return a single band image of the extracted QA bits
    return image.bitwiseAnd(pattern).rightShift(start);
};
function linearInterp(imgcol, frame, nodata){
    frame  = frame  || 32;
    nodata = nodata || 0;

    var time   = 'system:time_start';
    imgcol = imgcol.map(addTimeBand);

    var maxDiff = ee.Filter.maxDifference(frame * (1000*60*60*24), time, null, time);
    var cond    = {leftField:time, rightField:time};
    
    // Images after, sorted in descending order (so closest is last).
    var f1 = ee.Filter.and(maxDiff, ee.Filter.lessThanOrEquals(cond));
    var c1 = ee.Join.saveAll({matchesKey:'after', ordering:time, ascending:false})
        .apply(imgcol, imgcol, f1);
    
    // Images before, sorted in ascending order (so closest is last).
    var f2 = ee.Filter.and(maxDiff, ee.Filter.greaterThanOrEquals(cond));
    var c2 = ee.Join.saveAll({matchesKey:'before', ordering:time, ascending:true})
        .apply(c1, imgcol, f2);
    
    var interpolated = ee.ImageCollection(c2.map(function(img) {
        img = ee.Image(img);
        var before = ee.ImageCollection.fromImages(ee.List(img.get('before'))).mosaic();
        var after  = ee.ImageCollection.fromImages(ee.List(img.get('after'))).mosaic();
        img = img.set('before', null).set('after', null);
        // constrain after or before no NA values, confirm linear Interp having result
        before = replace_mask(before, after, nodata);
        after  = replace_mask(after , before, nodata);
        // Compute the ratio between the image times.
        var x1 = before.select('time').double();
        var x2 = after.select('time').double();
        var now = ee.Image.constant(img.date().millis()).double();
        var ratio = now.subtract(x1).divide(x2.subtract(x1));  // this is zero anywhere x1 = x2
        // Compute the interpolated image.
        before = before.select(0); //remove time band now;
        after  = after.select(0);
        img    = img.select(0); 
        var interp = after.subtract(before).multiply(ratio).add(before).toFloat();
        var qc = img.mask().not().rename('qc');
        interp = replace_mask(img, interp, nodata).rename('MOD_NDVI_INTER');
        return interp.addBands(qc).copyProperties(img, img.propertyNames());
    }));
    return interpolated;
}
function main(){
  var mod_ndvi = mod_sr.filterDate('2020-1-1','2021-1-1').filterBounds(point)
   .map(function(image){return image.clip(roi)})
   .map(function(image) {
   var ndvi = image.normalizedDifference(['sur_refl_b02', 'sur_refl_b01']);  //calculate Landsat NDVI
   var Q = image.select('State');
   var masknum = getQABits(Q, 0, 2);
   var mask = masknum.eq(ee.Image(0)).or(masknum.eq(ee.Image(3)));
   var ndvi_masked = ndvi.updateMask(mask);   //generate MODIS cloud mask from state band (0:clear;1: cloud/shadow/mixed)
   return ndvi_masked.rename(['MOD_NDVI']).copyProperties(image, image.propertyNames())});
  var nodata = -9999
  var frame = 8*4;
  var mod_ndvi_interp = linearInterp(mod_ndvi,frame,nodata)
  print(mod_ndvi_interp,'mod_ndvi_interp')
  Map.addLayer(mod_ndvi_interp.first().select('MOD_NDVI_INTER'),{min:-1,max:1},'mod_ndvi_interp')
  Map.addLayer(mod_ndvi.first().select('MOD_NDVI'),{min:-1,max:1},'mod_ndvi')
}
main()

原始影像效果(以四川省为例):
GEE 时序插值实现MODIS 8天无云影像代码免费分享_第1张图片
插值融合后影像:
GEE 时序插值实现MODIS 8天无云影像代码免费分享_第2张图片
讨论:
插值后仍有部分空缺,只需要调整frame的大小,就可以实现无空缺。
另外,算法经过修改,是可以用于Landsat系列和Sentinel-2系列的。
这对于GEE遥感学生来说,是非常有用的,且可以实现大范围高时间分辨率影像,大大增强了遥感数据的可用性。

关注我们
微信公众号:GEE遥感训练营
专注GEE遥感算法,包括遥感影像下载、遥感影像制图、遥感GIS空间分析、遥感生态评价、遥感影像融合、去干扰等多元遥感云计算,并分享前沿GEE知识。

你可能感兴趣的:(GEE,遥感,计算机视觉,人工智能)