GEE17: 基于Theil-Sen Median斜率估计和Mann-Kendall趋势分析方法分析四川省2022年NDVI变化情况

news2024/11/24 20:35:45

Theil-Sen Median + Mann-Kendall

    • 1. Theil-Sen Median + Mann-Kendall 原理
      • 1.1 Theil-Sen Median
      • 1.2 Mann-Kendall
    • 2. GEE code

1. Theil-Sen Median + Mann-Kendall 原理

1.1 Theil-Sen Median

  Theil-Sen Median方法又称为Sen斜率估计,是一种稳健的非参数统计的趋势计算方法。该方法计算效率高,对于测量误差和利群数据不敏感,适用于长时间序列数据的趋势分析。其计算公式为:
在这里插入图片描述

  式中,n为研究图层数,即n=22; ρ为趋势度,当ρ<0时,表示NDVI随时间呈下降趋势,当ρ>0时,表示NDVI随时间呈上升趋势。

1.2 Mann-Kendall

  Mann-Kendall(MK) 检验是一种非参数的时间序列趋势性检验方法,其不需要测量值服从正太分布,不受缺失值和异常值的影响,适用于长时间序列数据的趋势显著检验。检验公式:
在这里插入图片描述
  式中,Q为检验统计量;Z为标准化后的检验统计量;Var(Q)为方差,在给定的α显著性水平下,若Z<Za/2,则表示通过了相应置信度的显著性检验。

  方差计算公式:
在这里插入图片描述

在这里插入图片描述

2. GEE code

var imageCollection = ee.ImageCollection("MODIS/006/MOD13Q1");
var table = ee.FeatureCollection("users/cduthes1991/boundry/China_province_2019");
var roi = table.filter(ee.Filter.eq('provinces','sichuan'));
Map.centerObject(roi,5.8)

var styling = {color:"red",fillColor:"00000000"}
Map.addLayer(roi.style(styling),{},"geometry")


var imgCol = ee.ImageCollection("MODIS/006/MOD13Q1")
                        .filterDate('2022-1-1','2022-12-31')
                        .filterBounds(roi)
                        .select('NDVI')
                        .map(function(image){
                          var imgsub = image;
                          return image.clip(roi)
                        });
var palette = ['red', 'yellow', 'green'];

// Theil-Sen Median斜率估计 + Mann-Kendall趋势分析
// 做一个筛选器,筛选出右边比左边小的部分
var afterFilter = ee.Filter.lessThan({
    leftField: 'system:index',
    rightField: 'system:index'
});

// 做一个连接,让primary中所有元素和secondary做对比
// 将secondary中的year大于当前primary元素的加入到primary的after属性中
var joined = ee.ImageCollection(ee.Join.saveAll('after').apply({
    primary: imgCol,
    secondary: imgCol,
    condition: afterFilter
})).aside(print);


// 1、实现Theil-Sen Median斜率估计
var sen_slop = function (i, j) {  // i和j均为图像
    return ee.Image(j).subtract(i)
        .divide(ee.Image(j).date().difference(ee.Image(i).date(), 'year'))
        .rename('slope')
        .float();
};

// 两个map实现双重循环,先取出当前ndvi(current)的after属性(也就是大于当前的日期),
// 然后利用sen_slop函数计算current和after的sen斜率
var sen = ee.ImageCollection(joined.map(function (current) {
    var afterCollection = ee.ImageCollection.fromImages(current.get("after"))
    return afterCollection.map(function (after) {
        return ee.Image(sen_slop(current, after));
    })
}).flatten());


var sensSlope = sen.reduce(ee.Reducer.median(), 2); // Set parallelScale.
Map.addLayer(sensSlope, {palette: palette}, 'sensSlope');

// 将sensSlope中的像素值进行修改,将正值改为2,负值改为1;
// 以便图像可视化、遥感图像分类或不同区域或特征的标记
var classify = sensSlope.where(sensSlope.gt(0), 2)  // 将原图像中所有正值的像素修改为2
    .where(sensSlope.lt(0), 1)                      // 将原图像中所有负值的像素修改为1
Map.addLayer(classify, { min: 1, max: 2, palette: ['red', 'green'] }, 'Image classify to 0 and 1')

// 图像导出
Export.image.toDrive({
        image:sensSlope,
        description:'Sen_Median',
		   region:roi,    
        scale:250,
        maxPixels:1e13,
        folder:'LUCC'      
      })


// 2、实现Mann-Kendall趋势分析
// 构建符号函数sgn
var sign = function (i, j) {
    return ee.Image(j).neq(i)
        .multiply(ee.Image(j).subtract(i).clamp(-1, 1)).int();
};

// 符号函数求和
var kendall = ee.ImageCollection(joined.map(function (current) {
    var afterCollection = ee.ImageCollection.fromImages(current.get('after'));
    return afterCollection.map(function (image) {
        return ee.Image(sign(current, image));
    });
	// Set parallelScale to avoid User memory limit exceeded.
}).flatten()
).sum();

Map.addLayer(kendall, {min:-200, max:200, palette: palette}, 'kendall');   // 根据需要拉伸


// Values that are in a group (ties). Set all else to zero.
// 找到那些至少在两个图像对中像素值相等的位置,并将这些位置的像素值保留,其他位置的像素值设为0
// 个人认为基本所有像元都能保留,像素值为0的像元很少
var groups = imgCol.map(function (i) {
    var matches = imgCol.map(function (j) {
        return i.eq(j);
    }).sum();                // 基于布尔类型的图像生成一个新的图像,其中像素值表示该像元上像素值相等图层数量
    return i.multiply(matches.gt(1)); // 创建一个新图像,只保留那些在至少两个图像对中像素值相等的位置,并将其他位置的像素值设为0。
});


// Compute tie group sizes in a sequence. The first group is discarded.
var group = function (array) {
    var length = array.arrayLength(0);     // 获取array的长度,通常是数组的第一个维度(行数或索引)的长度
    
	// Array of indices. These are 1-indexed.
	// 将包含一个多维数组,其中每个元素的值表示其在数组中的索引
	// 所有元素初始化为1,使用一系列数组操作来生成一个长度为length的一维数组,每个元素的值都是1。
    var indices = ee.Image([1])
        .arrayRepeat(0, length)           // 将现有数组在指定维度上复制多次,即第0维(行数或索引)上重复length次
        .arrayAccum(0, ee.Reducer.sum())  // 对数组中的值进行累积计算,
        .toArray(1);
	
    var sorted = array.arraySort();   // 升序排序
    var left = sorted.arraySlice(0, 1);
    var right = sorted.arraySlice(0, 0, -1);
    // Indices of the end of runs.
    var mask = left.neq(right)
        // Always keep the last index, the end of the sequence.
        .arrayCat(ee.Image(ee.Array([[1]])), 0);

    var runIndices = indices.arrayMask(mask);
    // Subtract the indices to get run lengths.

    var groupSizes = runIndices.arraySlice(0, 1)
        .subtract(runIndices.arraySlice(0, 0, -1));
    return groupSizes;

};

// var(s)计算
var factors = function (image) {
    return image.expression('b() * (b() - 1) * (b() * 2 + 5)');
};


var groupSizes = group(groups.toArray());

var groupFactors = factors(groupSizes);

var groupFactorSum = groupFactors.arrayReduce('sum', [0])
    .arrayGet([0, 0]);

var count = joined.count();

var kendallVariance = factors(count)
    .subtract(groupFactorSum)
    .divide(18)
    .float()
    .rename('kendallVariance');

//Map.addLayer(kendallVariance, {}, 'kendallVariance');


// Compute Z-statistics.
var zero = kendall.multiply(kendall.eq(0));
var pos = kendall.multiply(kendall.gt(0)).subtract(1);
var neg = kendall.multiply(kendall.lt(0)).add(1);

// Z values
var z = zero
    .add(pos.divide(kendallVariance.sqrt()))
    .add(neg.divide(kendallVariance.sqrt()))
    .rename('z');
//Map.addLayer(z, {min: -2, max: 2}, 'z');


var qs = z.where(z.lte(1.65).and(sensSlope.lt(0)), -1)
    .where(z.gt(1.65).and(z.lte(1.96)).and(sensSlope.lt(0)), -2)
    .where(z.gt(1.96).and(z.lte(2.58)).and(sensSlope.lt(0)), -3)
    .where(z.gt(2.58).and(sensSlope.lt(0)), -4)
    .where(z.lte(1.65).and(sensSlope.lt(0)), 1)
    .where(z.gt(1.65).and(z.lte(1.96)).and(sensSlope.gt(0)), 2)
    .where(z.gt(1.96).and(z.lte(2.58)).and(sensSlope.gt(0)), 3)
    .where(z.gt(2.58).and(sensSlope.gt(0)), 4)

// 红色、绿色、蓝色、黄色、青色、品红色
var palette_qs = ['FF0000', '00FF00', '0000FF', 'FFFF00', '00FFFF', 'FF00FF'];
Map.addLayer(qs, { min: -1, max: 4, palette: palette_qs}, 'QS')


// 图像导出
Export.image.toDrive({
    image: qs,
    description: 'QS_Values',
	region: roi,
    scale: 250,
    maxPixels: 1e13,
	folder: 'LUCC'
})

结果展示:

1、sensSlope斜率估计图层:绿色表示斜率增加,红色表示斜率降低
在这里插入图片描述

2、二值图像分类:
在这里插入图片描述

3、Kendall趋势检验:主要展示哪些像元发生了变化,颜色越深,数值越大,则变化越大
在这里插入图片描述

4、Z统计值图:
在这里插入图片描述

5、NDVI趋势变化图:通过Z统计值分类得到

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1067431.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeakyReLU激活函数

nn.LeakyReLU 是PyTorch中的Leaky Rectified Linear Unit&#xff08;ReLU&#xff09;激活函数的实现。Leaky ReLU是一种修正线性单元&#xff0c;它在非负数部分保持线性&#xff0c;而在负数部分引入一个小的斜率&#xff08;通常是一个小的正数&#xff09;&#xff0c;以防…

JVM(八股文)

目录 一、JVM简介 二、JVM中的内存区域划分 三、JVM加载 1.类加载 1.1 加载 1.2 验证 1.3 准备 1.4 解析 1.5 初始 1.6 总结 2.双亲委派模型 四、JVM 垃圾回收&#xff08;GC&#xff09; 1.确认垃圾 1.1 引用计数 1.2 可达性分析&#xff08;Java 采用的方案&a…

BI系统有哪些?新手怎么选?

从本土化服务以及契合中国企业使用习惯等方面来看&#xff0c;建议采用国产BI系统。国内比较知名的BI工具有很多&#xff0c;比如亿信华辰BI(亿信ABI)、思迈特BI(Smartbi)、奥威BI(OurwayBISpeedBI)、帆软BI(FineBI)等。 这些BI系统在操作上都比较简单&#xff0c;比如像奥威B…

Vue中...(扩展运算符)的作用

对数组和对象而言&#xff0c;就是将运算符后面的变量里东西每一项拆下来。 &#xff08;一&#xff09;操作数组 // 1.把数组中的元素孤立起来 let iArray [1, 2, 3]; console.log(...iArray); // 打印结果 1 2 3// 2.在数组中添加元素 let iArray [1, 2, 3]; console.log…

拉取公司前端项目本地运行结果Bug频出,看我是如何一步一步成功解决的

文章目录 前端项目运行Bug记录问题背景npm install 报错问题1&#xff1a;npm install 报错ERESOLVE could not resolve问题2&#xff1a;npm install 报错 Cannot read properties of null问题3&#xff1a;node安装了npm没安装问题4&#xff1a;npm和node不兼容问题5&#xf…

新文件覆盖旧文件还能复原吗,3个方法快速恢复覆盖文件!

iPhone在解压压缩文件时&#xff0c;不小心将同名文件进行了覆盖&#xff0c;怎么撤回&#xff1f; 在使用U盘转移文档时&#xff0c;意外将同名文档进行了替换&#xff0c;怎么恢复&#xff1f; 当误将重名文件进行了替换&#xff0c;如何找回这些被覆盖的旧文件&#xff1f;…

Vue中的数据绑定

一、v-bind单向数据绑定 单向数据绑定中&#xff0c;数据只能由data流向页面。 v-bind:属性名"data变量" 或简写为 :属性名"data变量" 我们修改data中的iptvalue值&#xff0c;页面input框中的value值改变。 而我们修改input框中的value值&#xff0…

【C++初阶(二)C——C++过渡必看】

文章目录 前言一、C关键字&#x1f34e;二、命名空间&#x1f345;1.命名空间的定义&#x1f352;2.命名空间使用&#x1f353; 三、C输入&输出&#x1f351;四、缺省参数&#x1fad1;1. 缺省参数概念&#x1f349;2. 缺省参数分类&#x1f95d; 五、函数重载&#x1f965…

【Vue面试题五】说说你对Vue生命周期的理解?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;请描述下你对vue生命周期…

八、互联网技术——物联网

文章目录 一、智慧物联案例分析二、M2M技术三、数据保护综合案例分析一、智慧物联案例分析 智能物流是一种典型的物联网应用。一个物流仓储管理系统架构如下图所示: [问题1] 图中的三层功能:仓库物品识别、网络接入、物流管理中心,分别可对应到物联网基本架构中的哪一层? …

金九银十,刷完这个笔记,17K不能再少了....

大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;得准备面试了&#xff0c;又不知道从何下手&#xff01;为了帮大家节约时间&#xff0c;特意准备了一份面试相关的资料&#xff0c;内容非常的全面&#xff0c;真的可以好好补一补&#xff0c;希望大家在都能拿到理想…

MybatisPlus01

MybatisPlus01 1.MybatisPlus初体验 1.1首先要引入MybatisPlus的依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency>1.2定义Mapp…

【论文极速读】EMT——评估多模态LLM中的灾难性遗忘问题

【论文极速读】EMT——评估多模态LLM中的灾难性遗忘问题 FesianXu 20231001 at Baidu Search Team 前言 论文[1]报告了多模态LLM中遇到的灾难性遗忘问题&#xff0c;并且提出了一种评估其程度的方法EMT&#xff0c;本文简要介绍&#xff0c;希望对读者有所帮助。如有谬误请见谅…

criu简单例子

CRIU&#xff08;Checkpoint/Restore In Userspace&#xff09;是运行在linux操作系统上的一个开源软件&#xff0c;其功能是在用户空间实现Checkpoint/Restore功能。 github地址如下&#xff1a;https://github.com/checkpoint-restore/criu 本人选取的版本是3.12&#xff0…

使用V-Ray for SketchUp 进行室外场景操作流程!

使用V-Ray for SketchUp 渲染时&#xff0c;可让大家轻松创建出色的渲染效果。如何使用V-Ray for SketchUp 进行室外场景操作呢&#xff1f; 对于一些新手朋友&#xff0c;可能是不知所措的&#xff0c;今天小编通过一个室外场景案例流程来给大家展示看看。 1、设置场景 可视化…

FPGA设计时序约束三、设置时钟组set_clock_groups

目录 一、背景 二、时钟间关系 2.1 时钟关系分类 2.2 时钟关系查看 三、异步时钟组 3.1 优先级 3.2 使用格式 3.3 asynchronous和exclusive 3.4 结果示例 四、参考资料 一、背景 Vivado中时序分析工具默认会分析设计中所有时钟相关的时序路径&#xff0c;除非时序约束…

Android子线程可以更新UI

目录 1 传统更新UI的七种方式1.1 new Handler()1.2 new Handler.Callback()1.3 new Handler().post(Runnable r)1.4 new Handler().postDelayed(Runnable r, long delayMillis)1.5 Activity.runOnUiThread(Runnable action)1.6 View.post(Runnable action)1.7 View.postDelayed…

科普丨如何让语言芯片保持稳定性能

一、勿长期高磁接触 虽然高质量的语音芯片的高声量范围相对较大&#xff0c;但是智能语音芯片一般分为不同情况使用&#xff0c;首先是内外不能混用&#xff0c;不仅如此在室内使用时也要防止长期的高磁接触&#xff0c;这样也会使语音芯片寿命折损。 二、定期清尘擦拭 专业…

计算机网络拓扑结构

什么是计算机网络拓扑结构&#xff1f; 计算机网络拓扑结构是指在网络中连接计算机和设备的方式或布局。它决定了如何在网络中传输数据&#xff0c;以及网络中的设备如何相互通信。不同的拓扑结构适用于不同的场景和需求&#xff0c;因此选择正确的拓扑结构对于网络性能和可用…

详解FreeRTOS:FreeRTOS任务恢复过程源码分析(进阶篇—4)

本篇博文讲解FreeRTOS中任务恢复过程的源代码,帮助各位更好理解恢复任务的原理和流程。 在详解FreeRTOS:FreeRTOS任务管理函数(基础篇—11)中,讲述了任务恢复函数有两个vTaskResume()和xTaskResumeFromISR(),一个是用在任务中的,一个是用在中断中的,但是基本的处理过程…