利用GEE批量逐月下载L8影像归一化的NDVI数据

想要批量下载逐月的NDVI数据,需要建立两个for循环依次筛选年份和月份;

本文以Landsat 8数据集为例,实现逐月下载归一化后的NDVI数据;

大致步骤是:数据集去云处理——筛选所需要的月份并根据研究区裁剪——剔除无效数据——水体掩膜、计算NDVI并归一化——批量下载。

下文是逐月批量下载归一化后的NDVI完整代码:


// 定义成自己的研究区
var roi = table;

// 在图层上显示
Map.addLayer(roi, {}, 'yanjiuqu');

// 定义去云函数,阈值设置为5
var Cloudmask = function(image){
  var clouds = ee.Algorithms.Landsat.simpleCloudScore(image).select(['cloud'])
  return image.updateMask(clouds.lt(5))
};

// 定义L8数据集并进行去云处理
var imagecol = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA')
                 .filterBounds(roi)
                 .filterDate('2013-04-08', '2022-12-31')
                 .filterMetadata('CLOUD_COVER', 'less_than', 50)
                 .sort('CLOUD_COVER', true)
                 .map(function(image){
                   return image.set('year', ee.Image(image).date().get('year')).set('month', ee.Image(image).date().get('month'));
                 }) // 在影像属性里添加‘年’和‘月’字段,方便后期筛选
                 .map(Cloudmask);

print('CloudRemoved_Images', imagecol);

//_______________________________________________________________________________________
// 数据准备
// 利用for循环筛选出想要的月份数据并裁剪
var imgList = ee.List([]);
for (var year = 2013; year < 2023; year++) {
  for (var month = 1; month <= 12; month++) { // 默认为1-12月,可以更改为特定某一月份
    var img = imagecol.filterMetadata('year', 'equals', year)
                      .filterMetadata('month', 'equals', month)
                      .mosaic()
                      .clip(roi);
    var image = img.set('year', year).set('month', month); // 在列表里增添多个字段的方法,默认按照字段名首字母排序
    var imgList = imgList.add(image);
  }
}

print('Filtered_Images', imgList);

// 利用函数将无效波段剔除掉
var validImgs = ee.ImageCollection(imgList)
                 .map(function(image) {
                        var bands = image.bandNames();
                        var hasBands = bands.size().gt(0);
                        return ee.Algorithms.If(hasBands, image, null);
                  },true);

print('Valid_Images', validImgs);

//_______________________________________________________________________________________
// 数据处理
// 定义水体掩膜函数
function waterMask(image) {
  var ndwi = image.normalizedDifference(['B3', 'B5'])
  var mask = ndwi.lt(0.1)
  return image.updateMask(mask)
}

// 定义计算NDVI函数并保留年份和月份字段
function addTimeAndNDVI(image) {
  var year = image.get('year');
  var month = image.get('month');
  var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
  return ndvi.set('year', year).set('month', month);
}

// 定义归一化函数
function getNorm(image) {
  var minMax = image.reduceRegion({
    reducer: ee.Reducer.minMax(),
    geometry: roi,
    scale: 30,
    crs: 'EPSG:4326',
    bestEffort: true,
    maxPixels: 1e13
  });
  var year = image.get('year');
  var month = image.get('month');
  var yearmonth = ee.String(year).cat('-').cat(ee.String(month));
  var normalize  = ee.ImageCollection.fromImages(
      image.bandNames().map(function(name){
            name = ee.String(name);
            var band = image.select(name);
            return band.unitScale(ee.Number(minMax.get(name.cat('_min'))), ee.Number(minMax.get(name.cat('_max'))));
        })
    ).toBands().rename('Normed_NDVI').set('yearmonth', yearmonth);
    return normalize;
}

// 计算归一化后的NDVI
var NormedNDVI_Imgs = ee.ImageCollection(validImgs)
                        .map(waterMask)
                        .map(addTimeAndNDVI)
                        .map(getNorm);

print('Normed_NDVI_Images', NormedNDVI_Imgs);

//_______________________________________________________________________________________
// 数据导出
// 定义批量下载函数
function exportImage(image, fileName) {  
    Export.image.toDrive({  
      image: image,
      description: 'Image_' + fileName,
      folder: 'GEE_export',
      region: roi,
      scale: 30,
      crs: 'EPSG:4326',
      maxPixels: 1e13  //最大像元素
  });  
}

// 生成列表,迭代下载
var indexList = NormedNDVI_Imgs.reduceColumns(ee.Reducer.toList(), ['system:index']).get('list'); 
indexList.evaluate(function(indexs) {
  for (var i = 0; i < indexs.length; i++) { 
    var image = ee.Image(NormedNDVI_Imgs.filter(ee.Filter.eq('system:index', indexs[i])).first());
    
    var name = parseInt(indexs[i]);
     
    exportImage(image, name);
  }
});

在以上代码中,批量下载代码参考了小郭学地信博主的代码,导出文件名以列表的索引号命名。


代码实现结果:

运行后的任务框试图如下:

51d4ac5bd6704328a66d49e5778d1e91.jpeg

 很遗憾的是,由于本人菜鸡,实验了多种批量导出代码,最终未能实现以影像时间命名的方案,需要查对影像日期的话,可以去console对话框查看打印属性如下图:

f4a70fd61a4a4a1ca83f11becc101e3b.jpeg

 欢迎有能力的大佬去解决导出时以文件日期命名的问题。


批量导出:

为了能让影像批量RUN,这里借鉴了一位博主的批量RUN代码http://t.csdn.cn/YBybz,代码如下:

runTasks = function() {
    const evt = new MouseEvent('click', {bubbles: true, cancelable: true, ctrlKey: true})
    $$('.run-button' ,$$('ee-task-pane')[0].shadowRoot).forEach(function(e) {
        e.dispatchEvent(evt)
    })
}
runTasks()

运行出现RUN图标后,按F12,点击console对话框,复制粘贴进去即可批量导出到指定位置。

批量导出的结果如下图:

54b9499a8a9f4369bf6a7de6b8f1dc49.jpeg


 影像展示:

导出到云盘后即可下载到本地,如下图:

1f8aba3f72fc43bc88eb6b0db28ff8da.jpeg

用打开Image_65 影像(影像时间2018年6月),如下图:

9806b4a9d6f5440bb98ddcb745c786ba.jpeg

 对其进行统计计算,结果如下:

6cc5218405b7477f9c5a385fcd151ccf.jpeg

 可以看到,影像的NDVI结果是归一化到了0 ~ 1之间!


注:由于云量等原因,可能会导致某些影像在区域内显示不完全!

 

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值