GEE23:基于植被物候实现农作物分类

news2024/12/24 2:35:05

地物分类

  • 1. 写在前面
  • 2. 北京作物分类

1. 写在前面

  今天分享一个有意思的文章,用于进行农作物分类。文章提出了一个灵活的物候辅助监督水稻(PSPR)制图框架。主要是通过提取植被物候,并自动对物候数据进行采样,获得足够多的样本点,再使用随机森林等机器学习方法进行分类。这种方法有效解决了样本量不足或者样本位置不够精确的问题,并且分类结构相较于之前的方法更高。我认为这是一种比较有意思的文章,当然这种方法还可以用到其他植被类型分类中。

灵活的物候辅助监督水稻(PSPR)制图框架:
在这里插入图片描述

2. 北京作物分类

   首先,使用Landsat5、7、8数据获取植被物候信息,再提取随机采样点。
  各植被类型的物候:
在这里插入图片描述

/**************************使用PSPR方法生成随机采样点*************************/
// PSPR: 灵活的物候辅助监督水稻制图框架
//设置研究区位置: 北京
var table = ee.FeatureCollection("users/cduthes1991/boundry/China_province_2019");
var BJGrid4 = table.filter(ee.Filter.eq('provinces','beijing'));
var roi = BJGrid4;
Map.addLayer(roi,{'color':'grey'},'roi',false);
Map.centerObject(roi,7);

var GridTest = GridRegion(BJGrid4.geometry(),6,6).filterBounds(roi);
print("GridTest size:",GridTest.size());
var color = {'color':'0000FF','fillColor':'FF000000'};
Map.addLayer(GridTest.style(color),null,'GridTest');

/********* cropland mask**************************************************/
//这个数据为中科院的30LUCC数据,其中11和12分别表示水田和旱地
var CAS_LULC_2018 = ee.Image("users/chengkangmk/Global-LULC-China/LULC_CAS/CAS_LULC_30m_2018");
var cropland = CAS_LULC_2018.eq(11).or(CAS_LULC_2018.eq(12)).clip(roi);
Map.addLayer(cropland.randomVisualizer(),null,'cropland',false);

/*******************************自定义函数*********************************/
// Landsat 4, 5 and 7 去云
function rmL457Cloud(image) {
  var qa = image.select('pixel_qa');
  // If the cloud bit (5) is set and the cloud confidence (7) is high
  // or the cloud shadow bit is set (3), then it's a bad pixel.
  var cloud = qa.bitwiseAnd(1 << 5)
                  .and(qa.bitwiseAnd(1 << 7))
                  .or(qa.bitwiseAnd(1 << 3));
  // Remove edge pixels that don't occur in all bands
  var mask2 = image.mask().reduce(ee.Reducer.min());
  var mask3 = image.select("B1").gt(2000);
  return image.updateMask(cloud.not()).updateMask(mask2).updateMask(mask3.not())
              .toDouble().divide(1e4)
              .copyProperties(image)
              .copyProperties(image, ["system:time_start",'system:time_end']);
}

// Landsat-8 去云
function rmL8Cloud(image) { 
  var cloudShadowBitMask = (1 << 3); 
  var cloudsBitMask = (1 << 5); 
  var qa = image.select('pixel_qa'); 
  var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0) 
                 .and(qa.bitwiseAnd(cloudsBitMask).eq(0)); 
  var mask2 = image.select("B2").gt(2000);                 
  return image.updateMask(mask).updateMask(mask2.not()).toDouble().divide(1e4)
              .copyProperties(image)
              .copyProperties(image, ["system:time_start",'system:time_end']);
}

// Sentinel-2 去云
function rmS2cloud(image) {
  var qa = image.select('QA60');
  // Bits 10 and 11 are clouds and cirrus, respectively.
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;
  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));
  var mask2 = image.select("B2").lte(2000);
  return image.updateMask(mask).updateMask(mask2).toDouble().divide(1e4)
              .copyProperties(image)
              .copyProperties(image, ["system:time_start", "system:time_end"]);
}

// 计算相关指数,包括NDVI、LSWI(植被水分含量指数)、EVI
function addIndex(image){
  // original bands
  var blue = image.select('blue'); 
  var red = image.select('red');
  var green  = image.select('green');
  var nir = image.select('nir');
  var swir1 = image.select('swir1');
  var ndvi = image.normalizedDifference(["nir", "red"]).rename("NDVI").toDouble();
  var lswi = image.normalizedDifference(["nir", "swir1"]).rename("LSWI").toDouble();
  var lswi2ndvi = lswi.subtract(ndvi).rename("LSWI2NDVI").toDouble();
  var evi = image.expression(
    '2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
      'NIR': nir,
      'RED': red,
      'BLUE':blue
  }).rename("EVI");
  return image.addBands(ndvi).addBands(lswi).addBands(lswi2ndvi).addBands(evi);
}

// 为影像的特定波段指定名称
var LC8_BANDS = ['B2',   'B3',    'B4',  'B5',  'B6',    'B7']; //Landsat 8
var LC7_BANDS = ['B1',   'B2',    'B3',  'B4',  'B5',    'B7']; //Landsat 7
var LC5_BANDS = ['B1',   'B2',    'B3',  'B4',  'B5',    'B7']; //Llandsat 5
var S2_BANDS  = ['B2',   'B3',    'B4',  'B8',  'B11',   'B12']; // Sentinel-2
var STD_NAMES = ['blue', 'green', 'red', 'nir', 'swir1', 'swir2'];

// 定义时间变量、LSWI阈值、采样点数量
var year = '2015';
var th_lswi2NDVI = 0;
var pointNum = 1000;

// 导入数据
// landsat 8
var l8Col = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
           .map(rmL8Cloud)
           .filterBounds(roi)
           .filterDate(year+'-04-01',year+'-11-01')
            // .filter(ee.Filter.lte('CLOUD_COVER',10))
            .select(LC8_BANDS, STD_NAMES); 
// landsat 7 
var l7Col = ee.ImageCollection('LANDSAT/LE07/C01/T1_SR')
           .map(rmL457Cloud)
           .filterBounds(roi)
           .filterDate(year+'-04-01',year+'-11-01')
           .select(LC7_BANDS, STD_NAMES); 
// landsat 5  
var l5Col = ee.ImageCollection('LANDSAT/LT05/C01/T1_SR')
           .map(rmL457Cloud)
           .filterBounds(roi)
           .filterDate(year+'-04-01',year+'-11-01')
           .select(LC5_BANDS, STD_NAMES); 

var L578COl = ee.ImageCollection(l8Col.merge(l7Col).merge(l5Col))
                .sort("system:time_start")
                .map(addIndex);
print("L578COl: ", L578COl);


//****************************************************************************
//***************************** 基于LSWI的水稻制图****************************
//****************************************************************************
var palette1 = {min: 0, max: 1.0, palette: ['000000', '00FF00']};

// 1.水淹阶段,定义植被的时间窗口
var imgCol_flood = L578COl.filterDate(year+'-05-01',year+'-06-30') 
                          .filterBounds(roi);
                          
// 使用 LSWI-NDVI 提取水稻
// "rice_0_lswi": 表示初步产生水稻的时间
var rice_0_lswi =  imgCol_flood.select("LSWI2NDVI").map(function(image){
    return image.select("LSWI2NDVI").gt(th_lswi2NDVI);  
});

// 从rice_0_lswi图像集合中获取每个像素位置上的LSWI指数最大值(找到最大的 LSWI 值)。
// LSWI是一种用于检测土地表面水体的指数,其数值通常与水体的存在程度成正比。在稻田中,LSWI 的最大值对应于稻田灌溉时水体充足的情况。因此这样可以最大程度的保证水稻位置的获取。
var rice_0_lswi = rice_0_lswi.reduce(ee.Reducer.max()).clip(roi).updateMask(cropland);
Map.addLayer(rice_0_lswi, palette1, "rice_0_lswi candidates",false);

//2.生长阶段,水稻幼苗被移植到稻田中,直到水稻成熟
var imgCol_growth =  L578COl.filterDate(year+'-07-01',year+'-10-31')
                            .filterBounds(roi);

// 不同阶段图像
var PalettePanel = {bands:["swir1","nir","red"],min:0,max:0.3};

var imgCol_flood_qmosaic = imgCol_flood.qualityMosaic('LSWI2NDVI').clip(roi);
Map.addLayer(imgCol_flood_qmosaic, PalettePanel, 'imgCol_flood_qmosaic');

var imgCol_growth_qmosaic = imgCol_growth.qualityMosaic('NDVI').clip(roi);
Map.addLayer(imgCol_growth_qmosaic, PalettePanel, 'imgCol_growth_qmosaic', false);

// 使用 0 值来填充rice_0_lswi的区域
var rice_0_map = rice_0_lswi.unmask(0).clip(roi);
Map.addLayer(rice_0_map.selfMask(), {"palette":'#FF0000'}, "rice_0_map",false);


//****************************************************************************
//*********************基于CCVS 方法提取水稻物候******************************
//****************************************************************************
var visParam = {
 min: -0.2,
 max: 0.8,
 palette: 'FFFFFF, CE7E45, DF923D, F1B555, FCD163, 99B718, 74A901, 66A000, 529400,' +
   '3E8601, 207401, 056201, 004C00, 023B01, 012E01, 011D01, 011301'
};

// 使用LSWI_max, LSWI_min, NDVI_max, NDVI_min来推导RCLN,其中RCLN表示LSWI相对于与NDVI的变化幅度
var RCLE = imgCol_growth_qmosaic.select("LSWI").subtract(imgCol_flood_qmosaic.select('LSWI')).abs()
           .divide(imgCol_growth_qmosaic.select("EVI").subtract(imgCol_flood_qmosaic.select('EVI')).abs())
           .rename("RCLE");
Map.addLayer(RCLE, visParam,'RCLE', false);

// 创建一个布尔类型的图像,其中大于 0.1 的像素被设置为 true,小于或等于 0.1 的像素被设置为 false
var LSIW_min = imgCol_flood.select('LSWI').min().gt(0.1)
                           .clip(roi).updateMask(cropland);
Map.addLayer(LSIW_min.selfMask(), {"palette":'#FF0000'}, "LSIW_min",false);

// 
var RCLE_rice = RCLE.updateMask(RCLE.gt(0))
                    .updateMask(LSIW_min)
                    .lt(0.6)
                    .unmask(0)
                    .clip(roi); 
Map.addLayer(RCLE_rice.selfMask(), {palette: 'green'}, "CCVS_rice",false);

var riceCombine = RCLE_rice.add(rice_0_map);

// 将以上两种方法得到的数据图像进行合并求交
var stableMask = riceCombine.eq(0).or(riceCombine.eq(2));
var LULU_mutual = riceCombine.updateMask(stableMask)
                             .where(riceCombine.eq(2),1)
                             .rename("RiceMap").updateMask(cropland);
Map.addLayer(LULU_mutual,palette1,'LULU_mutual',false);

var riceMapCol = GridTest.toList(GridTest.size()).map(function(ROIFea){
  // set study area
  var roi = ee.FeatureCollection([ROIFea]);
  var ricemap = riceTrainData(roi);
  return ee.FeatureCollection(ricemap);
});
var samplePoint = ee.FeatureCollection(riceMapCol).flatten();
Map.addLayer(samplePoint,null,'samplePoint',false);

// check the generated sample data
print("samplePoint:",samplePoint.limit(10));

var ricePoint_1 = samplePoint.filter(ee.Filter.eq('landcover',1));
Map.addLayer(ricePoint_1,{'color':'#FFA500'},'ricePoint_1');
print("ricePoint_1 size",ricePoint_1.size());

var NonricePoint_1 = samplePoint.filter(ee.Filter.eq('landcover',0));
print("NonricePoint_1 size",NonricePoint_1.size());

Export.table.toAsset(samplePoint,"PSPRSampleGeneration"+year,"PSPRSampleGeneration"+year)

function riceTrainData(roiRegion){
  
  var roi = roiRegion;
  var LULU_mutual2 = LULU_mutual.clip(roi);
  /**********************************************************************
  *Define neighboor function
  * and generate the samples
  ***********************************************************************/
  function neighFun(img,kernalRadius,roi){
    var kernel = ee.Kernel.square(kernalRadius,'pixels',false);
    var kernelArea = (ee.Number(kernalRadius).multiply(2).add(1)).pow(2);
    var imgNeibor = ee.Image(img).convolve(kernel)
                      .eq(kernelArea)
                      .set("system:footprint",roi.geometry());
    return img.updateMask(imgNeibor);
  }
  var samplePoint = ee.List([]);
  for(var i=0;i<=1;i++){
    var class_Num = i;
    var class_i_mask = neighFun(LULU_mutual2.eq(class_Num),1,roi);
    var class_i = LULU_mutual2.updateMask(class_i_mask);
    samplePoint = samplePoint.add(class_i);
  }
  var samplePoint = ee.ImageCollection(samplePoint).mosaic().rename("landcover").updateMask(cropland);
  
  var pointSample =  samplePoint.stratifiedSample({
      numPoints:pointNum,
      classBand:"landcover",
      region:roi.geometry(),
      scale:30,
      seed:0,
      // tileScale:8,
      geometries:true
    });
    return pointSample;
}

/**************************************************************************
generate the grid
***************************************************************************/
function generateGrid(xmin, ymin, xmax, ymax, dx, dy) {

  var xx = ee.List.sequence(xmin, ee.Number(xmax).subtract(0.0001), dx);
  var yy = ee.List.sequence(ymin, ee.Number(ymax).subtract(0.0001), dy);
  
  var cells = xx.map(function(x) {
    return yy.map(function(y) {
      var x1 = ee.Number(x);
      var x2 = ee.Number(x).add(ee.Number(dx));
      var y1 = ee.Number(y);
      var y2 = ee.Number(y).add(ee.Number(dy));
      var coords = ee.List([x1, y1, x2, y2]);
      var rect = ee.Algorithms.GeometryConstructors.Rectangle(coords); 
      return ee.Feature(rect);
    });
  }).flatten(); 

  return ee.FeatureCollection(cells);
}

function GridRegion(roiRegion,xBlock,yBlock){
  //roiRegion: area of interest in the form of geometry
  // compute the coordinates
  var bounds = roiRegion.bounds();
  var coords = ee.List(bounds.coordinates().get(0));
  var xmin = ee.List(coords.get(0)).get(0);
  var ymin = ee.List(coords.get(0)).get(1);
  var xmax = ee.List(coords.get(2)).get(0);
  var ymax = ee.List(coords.get(2)).get(1);
  
  var dx = (ee.Number(xmax).subtract(xmin)).divide(xBlock); //4
  var dy = (ee.Number(ymax).subtract(ymin)).divide(yBlock);
  
  var grid = generateGrid(xmin, ymin, xmax, ymax, dx, dy);  
  grid = grid.filterBounds(roiRegion); 
  
  return grid;
}

植被水分含量指数(LSWI) 在其公式中使用了NIR和SWIR通道,SWIR波段对植被含水量的变化较敏感:
在这里插入图片描述
在这里插入图片描述

结果展示:
在这里插入图片描述

属性框展示:

在这里插入图片描述

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

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

相关文章

LLM--提示词Propmt的概念、作用及如何设计提示词

文章目录 1. 什么是提示词&#xff1f;2. 提示词的作用3. 如何设计提示词&#xff1f;3.1. 提供详细的信息3.2. 指定角色3.3. 使用分隔符和特殊符号3.4. 提供示例3.5. 少量示例的思维链&#xff08;COT&#xff09;模型3.6. 思维树&#xff08;TOT&#xff09;模型3.7. 自洽性 …

牛角工具箱源码 轻松打造个性化在线工具箱

&#x1f389; Whats this&#xff1f; 这是一款在线工具箱程序&#xff0c;您可以通过安装扩展增强她的功能 通过插件模板的功能&#xff0c;您也可以把她当做网页导航来使用~ 觉得该项目不错的可以给个Star~ &#x1f63a; 演示地址 https://tool.aoaostar.com &#x1f…

京东云免费服务器申请入口,2024年最新免费云主机

京东云服务器免费6月申请入口 jdyfwq.com 在京东云免费云主机申请页面&#xff0c;免费云服务器配置为云主机2核4G5M和轻量云主机2C2G可以申请免费使用&#xff0c;目前京东云免费云服务器申请时长从之前的6个月缩短到1个月&#xff0c;如下图&#xff1a; 京东云免费云主机 云…

如何通过cookie来区分这是瑞数反爬的几代

一、以下仅个人观点&#xff0c;可能有误 1、瑞数反爬了解 瑞数反爬&#xff1a;大多数首次不带cookie的请求&#xff0c;响应状态码是202/412瑞数的cookie &#xff1a; 我们看PPT结尾的Cookie的来定位是几代&#xff0c;PT的是js生成的&#xff1b; 不看OS的&#xff0c;OS…

C语言使用STM32开发板手搓高端家居洗衣机

目录 概要 成品效果 背景概述 1.开发环境 2.主要传感器。 技术细节 1. 用户如何知道选择了何种功能 2.启动后如何进行洗衣 3.如何将洗衣机状态上传至服务器并通过APP查看 4.洗衣过程、可燃气检测、OLED屏显示、服务器通信如何并发进行 小结 概要 本文章主要是讲解如…

物联网学习1、什么是 MQTT?

MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级、基于发布-订阅模式的消息传输协议&#xff0c;适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境。它在物联网应用中广受欢迎&#xff0c;能够实现传感器、执行器和其它设备之间的高效通…

【Monero】Wallet RPC | Wallet CLI | 门罗币命令行查询余额、种子、地址等命令方法教程

ubuntu22.04 首先在运行daemon&#xff0c;详细安装运行教程可参考&#xff1a;The Monero daemon (monerod) ./monerodWallet CLI run ./monero-wallet-cli如果还没有钱包就根据提示创建钱包即可 输入密码 查询余额 balance查询种子 seed其他可执行命令操作&#xff1…

Linux:查看系统各个组件性能的方法

查看cpu top 还有更为直观的 htop 可以同时看到&#xff0c;内存占用&#xff0c;cpu占用&#xff0c;交换内存的占用 vmstat 是比较综合的可以看到内存&#xff0c;交换内存&#xff0c;io吞吐&#xff0c;系统&#xff0c;cpu 查看内存 free -h 可以看懂内存的使用情况 …

企业知识库搭建不再是难题,靠这几个软件就可以了

在当今知识为王的时代&#xff0c;具备一套强大且实用的企业知识库&#xff08;Knowledge Base&#xff09;已成为提升工作效率、促进团队合作不可或缺的工具。那么&#xff0c;问题来了&#xff0c;我们该如何搭建一套属于自己的知识库呢&#xff1f;今天&#xff0c;我就给大…

Spring IoCDI(3)

DI详解 接下来学习一下依赖注入DI的细节. 依赖注入是一个过程, 是指IoC容器在创建Bean时, 去提供运行时所依赖的资源, 而资源指的就是对象. 在之前的案例中, 使用了Autowired这个注解, 完成了依赖注入这个操作. 简单来说, 就是把对象取出来放到某个类的属性中. 在一些文章中…

C++学习随笔(8)——模板初阶

本章我们来学习一下C的模版部分&#xff01; 目录 1. 泛型编程 2. 函数模板 2.1 函数模板概念 2.1 函数模板格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 3. 类模板 3.1 类模板的定义格式 3.2 类模板的实例化 1. 泛型编程 如何实现一个通…

【C++】为什么能实现函数重载

从C语言一路学到C的途中&#xff0c;C语言C语言相比&#xff0c;多了个函数重载&#xff0c;那么函数重载是如何实现的呢&#xff0c;为什么C语言无法支持&#xff0c;在本篇博客中&#xff0c;将会讲解C为何能实现函数重载。 一.编译过程 C能实现函数重载&#xff0c;而C语言不…

CloudFlare WARP+ 无限流量

Cloudflare WARP 是一种由 Cloudflare 提供的虚拟专用网络&#xff08;VPN&#xff09;服务&#xff0c;旨在提供更安全、更快速的互联网连接。WARP 的目标是通过使用 Cloudflare 的全球网络基础设施来加密和保护用户的互联网流量&#xff0c;并且通过优化路由和连接&#xff0…

012_control_flow_in_Matlab中的控制流

Matlab中的控制流 虽然&#xff0c;我们说Matlab中的计算是向量化的&#xff0c;但是在某些情况下&#xff0c;作为一个“程序设计语言”&#xff0c;Matlab也提供了一些控制流结构&#xff0c;来帮助我们实现一些复杂的逻辑。 我会在介绍控制流的时候&#xff0c;提醒如何用…

Spark源码(二)-Netty简介

一、Netty简介 Netty 是一个异步事件驱动的网络通信应用框架&#xff0c;用于快速开发可维护的高性能服务器和客户端。简单地说Netty封装了JDK的NIO&#xff0c;不用再写一大堆复杂的代码&#xff0c;从NIO各种繁复的细节中脱离出来&#xff0c;让开发者重点关心业务逻辑。 二…

新书速递——《可解释AI实战(PyTorch版)》

本书旨在帮助你实施最新的可解释AI技术&#xff0c;以构建公平且可解释的AI系统。可解释AI是当今AI研究中的热门话题&#xff0c;但只有少数资源和指南涵盖了所有重要技术&#xff0c;这些技术对实践者来说非常有价值。本书旨在填补这一空白。 本书读者对象 本书既适合那些有兴…

阿里云2核4G云服务器支持多少人同时在线?并发数计算?

阿里云2核4G服务器多少钱一年&#xff1f;2核4G配置1个月多少钱&#xff1f;2核4G服务器30元3个月、轻量应用服务器2核4G4M带宽165元一年、企业用户2核4G5M带宽199元一年。可以在阿里云CLUB中心查看 aliyun.club 当前最新2核4G服务器精准报价、优惠券和活动信息。 阿里云官方2…

04 | Swoole 源码分析之 epoll 多路复用模块

首发原文链接&#xff1a;Swoole 源码分析之 epoll 多路复用模块 大家好&#xff0c;我是码农先森。 引言 在传统的IO模型中&#xff0c;每个IO操作都需要创建一个单独的线程或进程来处理&#xff0c;这样的操作会导致系统资源的大量消耗和管理开销。 而IO多路复用技术通过…

第十四届蓝桥杯JavaA组省赛真题 - 棋盘

解题思路&#xff1a; 暴力 棋盘类题目取反操作&#xff1a; f[a][b]^1; 或者f[a][b] 1 - f[a][b]; import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scan new Scanner(System.in);int n scan.nextInt();int m scan.nex…

(南京观海微电子)——GOA介绍

GOA是Gate on Array的简写&#xff0c;简单可以理解为gate IC集成在玻璃上了&#xff0c;面板就可以不用gate ic了&#xff0c;是一种低成本的设计&#xff0c;窄边框面板大多数都用了GOA技术。还有一些公司叫GIP&#xff08;Gate in Panel&#xff09;&#xff0c;GDM等等。 …