Google earth engine学习笔记 2: 通过分析提取植被物候的代码学习gee 1

2023-11-04

Google earth engine学习笔记 2: 通过分析提取植被物候的代码学习gee 1

通过一篇 根据 sentinel-2 影像计算植被指数并提取植被物候 的文章所附的代码学习gee,(原作者的github),写这个东西是为了自己学习,也希望国内的科研圈合作交流开源的氛围更好,所以如果有用到下文中的代码,希望可以引用原作者发表的文章。刚开始学习gee,难免有错误,希望指出。

首先简单介绍代码的主要组成部分,主要使用过创建和打印字符串变量来实现

var textSections = '' +
  "\n SECTION 1 - Define parameters and setup " +
  "\n SECTION 2 - Define function for cubic interpolation " +
  "\n SECTION 3 - Prepare Sentinel-2 data " +
  "\n SECTION 4 - Generate composites  " +
  "\n SECTION 5 - Increase window size for empty composites  " +
  "\n SECTION 6 - Interpolate time series " +
  "\n SECTION 7 - Estimate phenology metrics " +
  "\n SECTION 8 - Plot results " +
  "\n SECTION 9 - Display legends " 
print(textSections)
  • var str_var = ‘str’: 创建字符串变量
  • print(str_var): 打印

第一部分,定义相关参数通过earth engine的中的相关函数设置地图,通过创建字符串和数值变量定义参数,通过earth engine中的相关函数创建点和兴趣区这些空间对象

Map.setOptions('satellite')

var geom = /* color: #ff0000 */ee.Geometry.Point([91.38, 30.55]);
var point = geom // inspect results for this location
var roi = point.buffer(100000).bounds() // display results around the point of interest

var vegIndex = 'evi' // Specify the vegetation index (VI): 'ndvi', 'evi', 'gcc', or 'ndpi'.
var th = 0.5 // Define the percentage of amplitude for the estimation of the threshold 
var threshMin = 0.2 // minimum NDVI value for the reclassification of snow values
var scale = 50 // scale of the analysis
var year1 = 2019 // year of processing

var lag = 20 // temporal resolution of the composites

var startDate = year1+'-04-15'
var endDate = year1+'-12-20'

Map.centerObject(roi,7)
  • Map.setOptions(‘satellite’) : 设置地图底图为卫星图, 主要参数为地图类型(‘roadmap’,‘terrain’,'satellite’等),地图风格(一个字典)
  • Map.centerObject(): 使对象居中,数字参数为缩放等级
  • var geom = / color: #ff0000 */ee.Geometry.Point([91.38, 30.55]):使用*ee.Geometry.Point()*创建一个空间点对象,主要接收参数为点的坐标 / color: #ff0000 */ 设置点显示的颜色
  • var roi = point.buffer(100000).bounds():根据点对象创建roi,buffer() 函数根据对象建立缓冲区,主要参数为距离bounds()为对象添加边界

第二部分,定义插值函数

var cubicInterpolation = function(collection,step){ 

var listDekads = ee.List.sequence(1, collection.size().subtract(3), 1);

var colInterp = listDekads.map(function(ii){

  var ii = ee.Number(ii);
  
    var p0 = ee.Image(collection.toList(10000).get(ee.Number(ii).subtract(1)));
    var p1 = ee.Image(collection.toList(10000).get(ii));
    var p2 = ee.Image(collection.toList(10000).get(ee.Number(ii).add(1)));
    var p3 = ee.Image(collection.toList(10000).get(ee.Number(ii).add(2)));
  
    var diff01 = ee.Date(p1.get('system:time_start')).difference(ee.Date(p0.get('system:time_start')), 'day');
    var diff12 = ee.Date(p2.get('system:time_start')).difference(ee.Date(p1.get('system:time_start')), 'day');
    var diff23 = ee.Date(p3.get('system:time_start')).difference(ee.Date(p2.get('system:time_start')), 'day');
    
    var diff01nor = diff01.divide(diff12);
    var diff12nor = diff12.divide(diff12);
    var diff23nor = diff23.divide(diff12);
    
    var f0 = p1;
    var f1 = p2;
    var f0p = (p2.subtract(p0)).divide(diff01nor.add(diff12nor));
    var f1p = (p3.subtract(p1)).divide(diff12nor.add(diff23nor));
  
    var a = (f0.multiply(2)).subtract(f1.multiply(2)).add(f0p).add(f1p);
    var b = (f0.multiply(-3)).add(f1.multiply(3)).subtract(f0p.multiply(2)).subtract(f1p);
    var c = f0p;
    var d = f0;
    
  /
  var xValues = ee.List.sequence(0,diff12.subtract(1),step); !!!!!!!!!!!!!!!
  
  var xDates = ee.List.sequence(p1.get('system:time_start'),p2.get('system:time_start'),86400000);
  //print(xDates)
  
  var interp = (xValues.map(function(x){
    var im = ee.Image(ee.Number(x).divide(diff12));
    return (im.pow(3)).multiply(a).add((im.pow(2)).multiply(b)).add(im.multiply(c)).add(d)
        .set('system:time_start',ee.Number(xDates.get(x)));
    }));
    
   return interp 
  })
  
  var colInterp = ee.ImageCollection(colInterp.flatten());
  
  return colInterp
}
  • var cubicInterpolation = function(collection,step){ … }: 自定义函数
  • var listDekads = ee.List.sequence(1, collection.size().subtract(3), 1):使用 ee.List.sequence() 函数创建数列,参数主要为开始,结束,和步长(或者数量),其中**collection.size()**为影像集的大小
  • var colInterp = listDekads.map(function(ii){ … }: 通过map()实现循环
  • ee.Number(): 创建数字对象
  • collection.toList(10000)将数据集转为列表,数字参数为列表长度上限
  • var p0 = ee.Image(collection.toList(10000).get(ee.Number(ii).subtract(1))): 列表使用get() 为根据下标提取列表中的元素
  • ee.Date(p1.get(‘system:time_start’)).difference(ee.Date(p0.get(‘system:time_start’)), ‘day’)ee.Date() 创建一个日期对象p1.get(‘system:time_start’)获取影像的拍摄时间difference() 计算两个时间对象间的差,可以给定结果的单位(‘year’,'day’等)
  • diff01.divide(diff12)divide() 除法
  • (f0.multiply(-3)).add(f1.multiply(3)).subtract(f0p.multiply(2)).subtract(f1p)subtract() 减法add()加法multiply() 乘法pow() 乘方
  • var colInterp = ee.ImageCollection(colInterp.flatten())flatten() 讲多维数组转为一维,压平

第三部分,遥感影像预处理

//  Call Sentinel2 data.

var S2 = ee.ImageCollection("COPERNICUS/S2_SR")
  .filterDate(startDate,endDate)
  .filterBounds(roi)
  .filterMetadata('CLOUD_COVERAGE_ASSESSMENT','less_than',70)
  .filterMetadata('SNOW_ICE_PERCENTAGE','less_than',90);

// Mask non-valid observations and reclassify snow values
var S2 = S2.map(function(im){

    var SCL = im.select('SCL')
    var SCLmask = SCL.eq(1).or(SCL.eq(4)).or(SCL.eq(5)).or(SCL.eq(11)) // mask for non-valid observations
    var snowMask = SCL.eq(11) // snow mask
    
    var blue = im.select('B2').multiply(0.0001)
    var green = im.select('B3').multiply(0.0001)
    var red = im.select('B4').multiply(0.0001)
    var nir = im.select('B8').multiply(0.0001)
    var swir = im.select('B12').multiply(0.0001)
    
    // Generate VIs
    var ndvi = im.normalizedDifference(['B8','B4']).rename('ndvi')
    var evi = (ee.Image(2.5).multiply(nir.subtract(red))).divide(nir.add(red.multiply(6)).subtract(blue.multiply(7.5)).add(1)).rename('evi')
    var gcc = green.divide(green.add(red).add(blue)).rename('gcc')
    var alpha = ee.Image(0.51) // alpha parameter in NDPI formula
    var ndpi = (nir.subtract(alpha.multiply(red).add((ee.Image(1).subtract(alpha)).multiply(swir)))).divide(nir.add(alpha.multiply(red).add((ee.Image(1).subtract(alpha)).multiply(swir)))).rename('ndpi')
    
    // select VI of interest
    var bio = ndvi.addBands(evi).addBands(ndpi).addBands(gcc)
      .select(vegIndex).rename('bio') 

  return bio.where(bio.lt(threshMin),threshMin) // force low values to threshMin 
    .where(snowMask,threshMin) // force snow values to threshMin 
    .updateMask(SCLmask) // mask non-valid observations
    .set('system:time_start', im.get('system:time_start'))
});

  • var S2 = ee.ImageCollection(“COPERNICUS/S2_SR”)
    .filterDate(startDate,endDate)
    .filterBounds(roi)
    .filterMetadata(‘CLOUD_COVERAGE_ASSESSMENT’,‘less_than’,70)
    .filterMetadata(‘SNOW_ICE_PERCENTAGE’,‘less_than’,90);
    : 通过 ee.ImageCollection(“COPERNICUS/S2_SR”) 调用遥感影像集,其中’COPERNICUS/S2_SR’为sentinel-2影像的在数据库中的名称,数据集名称可以通过检索获得,
    filterDate() 根据日期范围筛选影像,filterBounds() 设置影像的空间范围,filterMetadata(‘CLOUD_COVERAGE_ASSESSMENT’,‘less_than’,70) 根据云量筛选, filterMetadata(‘SNOW_ICE_PERCENTAGE’,‘less_than’,90) 根据冰雪情况筛选

  • var SCL = im.select(‘SCL’) :选择影像波段

  • var SCLmask = SCL.eq(1).or(SCL.eq(4)).or(SCL.eq(5)).or(SCL.eq(11)): 根据条件创建掩模图层

  • var ndvi = im.normalizedDifference([‘B8’,‘B4’]).rename(‘ndvi’):使用 normalizedDifference() 函数计算ndvi,参数为波段的名称rename() 对波段进行重命名

  • bio = ndvi.addBands(evi).addBands(ndpi).addBands(gcc)addBands() 添加波段

  • bio.where(bio.lt(threshMin),threshMin)
    .where(snowMask,threshMin)
    .updateMask(SCLmask)
    .set(‘system:time_start’, im.get(‘system:time_start’))

    where()进行条件替换,参数为条件和用来替换的值updateMask() 更新掩膜set(‘system:time_start’, im.get(‘system:time_start’)) 设置时间参数

第四部分,构建时间序列

// Create the list of dates of the central day of the window
var listDates = ee.List.sequence(ee.Date(startDate).millis(), ee.Date(endDate).millis(), 86400000*lag)

// map the dates
var colDekadsRaw = ee.ImageCollection(listDates.map(function(dd){
  var date_window = ee.Date(ee.Number(dd)) // central day of the moving window

  var date_startW = date_window.advance(-lag/2, 'days') // first day of the moving window
  var date_endW = date_window.advance(lag/2, 'days') // last day of the moving window

  var col_window = S2.filterDate(date_startW,date_endW) // filter the S2 collection for a period equal to lag

  var out = col_window.reduce(ee.Reducer.mean()) // compute the average
  
return out
    .set('system:time_start',date_window.millis()) // set time property
    .set('empty', col_window.size().eq(0)) // flag dates without images
    // .set('nobs',col_window.filterBounds(point).size())
    // .set('date_start',date_start)
    // .set('date_end',date_end)
    // .set('date_window',ee.Date(date_window));
}).flatten())

// filter dates without images and fill them with the minimum NDVI value 
var colDekadsEmpty = colDekadsRaw.filterMetadata('empty', 'equals', 1).map(function(im){
 return ee.Image(threshMin).rename('bio_mean').copyProperties(im,['system:time_start'])
})
var colDekads = colDekadsRaw.filterMetadata('empty', 'equals', 0).merge(colDekadsEmpty)


// plot composite 
var chart1 = ui.Chart.image.series(colDekads.select('bio_mean'), point, ee.Reducer.first(), scale)
  .setOptions({title: 'Moving average every '+lag+' days', 
              lineWidth: 0,
              pointSize: 4})

print(chart1)

  • millis():将日期转化成自1970-01-01T00:00:00Z的毫秒值
  • var date_startW = date_window.advance(-lag/2, ‘days’)advance() 时间对象的加减
  • var out = col_window.reduce(ee.Reducer.mean())reduce(ee.Reducer.mean()) 计算均值, reduce()中可以给各种Reducer来完成各种运算
  • ee.Image(threshMin).rename(‘bio_mean’).copyProperties(im,[‘system:time_start’]): copyProperties() 复制属性
  • var colDekads = colDekadsRaw.filterMetadata(‘empty’, ‘equals’, 0).merge(colDekadsEmpty)merge() 合并影像集
  • var chart1 = ui.Chart.image.series(colDekads.select(‘bio_mean’), point, ee.Reducer.first(), scale)
    .setOptions({title: ‘Moving average every ‘+lag+’ days’,
    lineWidth: 0,
    pointSize: 4})
    print(chart1)

    ui.Chart.image.series() 根据影像集数据画图,主要参数为 所用影像集(波段),所选空间范围(点,roi), 所选择的 Reducer,用来计算y轴数值,空间尺度(单位为米)ee.Reducer.first() 选择输入中的第一个数值setOptions() 图标相关参数的设置,通常为一个字典
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Google earth engine学习笔记 2: 通过分析提取植被物候的代码学习gee 1 的相关文章

  • 10种简单的Java性能优化学习

    10种简单的Java性能优化学习 你是否正打算优化hashCode 方法 是否想要绕开正则表达式 Lukas Eder介绍了很多简单方便的性能优化小贴士以及扩展程序性能的技巧 最近 全网域 Web Scale 一词被炒得火热 人们也正在通过

随机推荐

  • 多层目录编译的makefile文件编写

    一直想自己做一个目录结构稍复杂一点的makefile 看make的manual上写的有点不好理解 再从网上搜搜也没有发现比较好的教程 我是个搞工程的 懂点计算 也没有受过专业编程训练 对于一些技术不是很懂 有时想使用也会不知到如何下手 找不
  • Mysql 管理

    目录 0 课程视频 1 系统数据库 gt 安装完mysql gt 自带四个数据库 2 常用工具 gt 写脚本用 2 1 mysql 客户端工具 2 2 mysqladmin 2 3 mysqlbinlog gt 二进制日志 gt 运维讲解
  • UI架构相关

  • 锐捷网管系统漏洞利用分析

    利用此漏洞可获取后台密码 现在复现 1 fofa搜索 title RG UAC登录页面 body admin 2 现在 查看源代码 向下拉看到这个 就是密码 3 MD5解密 登录成功
  • SpringBoot配置双数据源(一个项目同时连接操作两台数据库)

    前言 近期公司要上线3 0版本 需要将2 0的数据迁移到3 0中继续沿用 由于3 0的数据库相比2 0 的数据库改动很大 最主要的是2 0数据库的主键为自然数自增主键 而3 0数据库的主键为UUID2 所以只能使用程序动态迁移 声明 本教程
  • ROS中的Navigation

    ROS中的Navigation 1 Navigation Stack的核心就是move base 2 move base的三个功能 全局规划 静态 局部规划 动态 处理异常行为 有三个接口 3 costmap 代价地图 是move base
  • 第三次C语言课程设计作业

    上节课我们学习了文件型指针的运用 这节课我们则学习了变量型指针和链表的学习的使用 还了解了free函数 malloc函数的应用 指向结构体变量的指针变量的定义形式与一般指针变量的定义形式相同 只是将其指向类型定义为结构体类型即可 例如 st
  • Eclipse 常用快捷键

    常用的 编辑 Ctrl 1 快速修复 解决很多问题 比如import类 try catch包围等 Ctrl Shift F 格式化当前代码 Ctrl Shift M 添加类的import导入 Ctrl Shift O 组织类的import导
  • 时间序列分析之ARIMA模型预测__R篇

    相关文章 时间序列分析之ARIMA模型预测 SAS篇 之前一直用SAS做ARIMA模型预测 今天尝试用了一下R 发现灵活度更高 结果输出也更直观 现在记录一下如何用R分析ARIMA模型 1 处理数据 1 1 导入forecast包 fore
  • 使用Hutool的流方式读取Excel大文件

    官网介绍 在标准的ExcelReader中 如果数据量较大 读取Excel会非常缓慢 并有可能造成内存溢出 因此针对大数据量的Excel Hutool封装了Sax模式的读取方式 Excel07SaxReader支持Excel2007格式的S
  • Unity Notes之控制粒子系统的最大粒子数量

    Unity中的粒子系统使用起来还是比较方便的 不过在实际过程中遇到这样的一个问题 需要动态的来控制一个粒子系统组件所能产生的最大粒子数 看doc上说是有maxParticles来控制 但实际上却没有这个开放的参数 只能通过其它的方式来实现
  • STM32F103RBT6型号说明

    STM32系列专为要求高性能 低成本 低功耗的嵌入式应用设计的ARMCortex M0 M0 M3 M4和M7内核 主流产品 STM32F0 STM32F1 STM32F3 超低功耗产品 STM32L0 STM32L1 STM32L4 ST
  • 在Idea中使用控制台,显示文件

    在Idea中使用控制台 显示文件 前言 在IDEA创建项目时 IDEA会自动帮你生成一个存放 class文件的地方 就是在out目录下 而可执行的代码都在src目录下 可以在src目录下创建packet 包 可以把Java作业放在一个 Pr
  • Zookeeper学习笔记四之持久节点和临时节点

    持久节点和临时节点 znode节点可以是持久 persistent 节点 还可以是临时 ephemeral 节点 持久节点node 如 path 只能通过delete命令进行删除 而临时节点相反 当创建临时节点的客户端崩溃或者关闭了与Zoo
  • CAD导出DXF再导入PADS出现尺寸大小不一致的解决办法?

    如下错误 1 用CAD打开板框 删除板框多余部分 只留需要的部分 注意 从左边拖动鼠标选中 再删除 如果从右边拖动鼠标选中无法全选 2 设置原点 选中整个板框 输入命令m 点击最左下脚 输入坐标0 0设置为原点 此时板框完全不见了 双击滚轮
  • 制作Centos7自动安装镜像(三)

    文章总览 制作Centos7自动安装镜像 在这里说明一下 我们制作自动化安装镜像用的是linux的kickstart技术 这个技术的核心是制作一个ks cfg文件 将所有需要自动化安装的内容写成一个脚本 放置在镜像中 并在安装菜单中指定这个
  • 文件I/O和标准I/O的区别

    文件I O 文件I O是操作系统提供的操作文件的API 例如Linux中的open 和write 等 这些函数可以完成文件的操作 但是效率不一定很高 标准I O 标准I O是应用层提供的库函数 例如C语言提供的文件操作函数fopen fcl
  • Qt信息隐藏(Q_D/Q_Q)介绍

    目录 1 基本介绍与二进制兼容 2 二进制兼容的设计原则 3 常见c qt信息隐藏 4 Q Q Q D介绍 5 定制可编辑treewidget与如何访问基类的Private 6 总结 1 基本介绍与二进制兼容 作者虽然一直在linux做开发
  • Vue + Spring Boot 项目实战(分享)

    第一部分Vue Spring Boot 项目实战 一 项目简介Vue Spring Boot 项目实战 二 搭建 Vue js 项目Vue Spring Boot 项目实战 三 前后端结合测试 登录页面开发 Vue Spring Boot
  • Google earth engine学习笔记 2: 通过分析提取植被物候的代码学习gee 1

    Google earth engine学习笔记 2 通过分析提取植被物候的代码学习gee 1 通过一篇 根据 sentinel 2 影像计算植被指数并提取植被物候 的文章所附的代码学习gee 原作者的github 写这个东西是为了自己学习