GEE学习笔记九十二:Sentinel-2 最新去云方法总结

news2024/10/2 3:15:06

下面使用例子的原始影像截图如下:

第一种方法:使用QA波段去云

    这是我们最常用的方法,具体原理就是利用QA60波段标记实现去云,具体代码如下:


var s2 = ee.ImageCollection("COPERNICUS/S2"),
 
    point = /* color: #98ff00 */ee.Geometry.Point([116.20553071765003, 39.404020061278715]);
 
/**
*
* remove cloud by QA bands
*
* */
 
function rmCloudByQA(image) {
 
  var qa = image.select('QA60');
 
  var cloudBitMask = 1 << 10;
 
  var cirrusBitMask = 1 << 11;
 
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
 
               .and(qa.bitwiseAnd(cirrusBitMask).eq(0));
 
  return image.updateMask(mask);
 
}
 
function main() {
 
  var startDate = "2019-4-4";
 
  var endDate = "2019-4-8";
 
  Map.centerObject(point, 8);
 
  var s2Imgs = s2.filterDate(startDate, endDate)
 
                 .filterBounds(point);
 
  Map.addLayer(s2Imgs.first(), {min:0, max:3000, bands:["B4", "B3", "B2"]}, "raw", false);
 
  s2Imgs = s2Imgs.map(rmCloudByQA);
 
  Map.addLayer(s2Imgs.first(), {min:0, max:3000, bands:["B4", "B3", "B2"]}, "cloud");
 
}
main();
 

去云的效果如下图:

编辑

代码分析:

    这段代码中去云的方法是:rmCloudByQA()其他的代码也都是基础代码,我就不在过多解释。

第二种方法:计算云量分数去云

    这种方法比较有意思,是一个国外的大牛利用波段组合以及NDSI指数计算得到当前像素是不是云,具体代码如下:var s2 = ee.ImageCollection("COPERNICUS/S2"),
 
    point = /* color: #98ff00 */ee.Geometry.Point([116.20553071765003, 39.404020061278715]);
 
var _cloudScore = function(img) {
 
  var rescale = function(img, exp, thresholds) {
 
    return img.expression(exp, {img: img})
 
        .subtract(thresholds[0]).divide(thresholds[1] - thresholds[0]);
 
  };
 
  var score = ee.Image.constant(1.0);
 
  score = score.min(rescale(img, 'img.blue', [0.1, 0.3]));
 
  score = score.min(rescale(img, 'img.red + img.green + img.blue', [0.2, 0.8]));
 
  score = score.min(rescale(img, 'img.nir + img.swir1 + img.swir2', [0.3, 0.8]));
 
  var ndsi = img.normalizedDifference(['green', 'swir1']);
 
  return score.min(rescale(ndsi, 'img', [0.8, 0.6]));
 
};
 
/**
*
* remove cloud by Score bands
*
* */
 
function rmCloudByScore(image, thread) {
 
  var preBands = ["B2","B3","B4","B8","B11","B12"];
 
  var newBands = ['blue','green','red','nir','swir1','swir2'];
 
  var score = _cloudScore(image.select(preBands, newBands));
 
  score = score.multiply(100).byte().rename('cloud');
 
  return image.addBands(score)
 
              .updateMask(score.lte(thread));
 
}
 
/**
*
* scale image
*
* */
 
function scaleImage(image) {
 
  var time_start = image.get("system:time_start");
 
  image = image.divide(10000);
 
  image = image.set("system:time_start", time_start);
 
  return image;
 
}
 
function main() {
 
  var startDate = "2019-4-4";
 
  var endDate = "2019-4-8";
 
  Map.centerObject(point, 8);
 
  var s2Imgs = s2.filterDate(startDate, endDate)
 
                 .filterBounds(point)
 
                 .map(scaleImage)
 
                 .map(function(image) {
 
                    return rmCloudByScore(image, 30);
 
                 });
 
  Map.addLayer(s2Imgs.first(), {min:0, max:0.3, bands:["B4", "B3", "B2"]}, "cloud");
 
}
 
main();
 

代码分析:

    观察这段代码,有一点需要注意的是:调用去云方法rmCloudByScore(image, threshold)需要传入两个参数,一个是影像另外一个是识别云的阈值(也就是大于多大的值就认为是云,范围是0-100)。还有就是调用这个方法之间首先需要将影像的波段做缩放和将波段名称重新命名为指定的名称,这是因为这个算法内部主要逻辑方法_cloudScore(xxx)它内部计算时候取的都是特殊值,具体参考上述代码。

第三种方法:使用s2cloudless算法去云

    这是目前最新的一种去云方法,s2cloudless算法是一种机器学习算法,Sentinel-2影像通过它可以计算得到云掩膜文件。这个算法是由SENTINEL Hub开源的一种算法,地址是:

GitHub - sentinel-hub/sentinel2-cloud-detector: Sentinel Hub Cloud Detector for Sentinel-2 images in Python

    在GEE上我们不需要自己去用这个算法来计算云掩膜,GEE官方目前正在利用这个算法来生成一个新的数据集,这个数据集就是Sentinel-2云掩膜数据集(“COPERNICUS/S2_CLOUD_PROBABILITY”)。需要注意的是由于目前这个数据集依然在生产中,所以不一定所有的地方和所有时间段都存在,我们在使用的时候一定要注意。

下面以具体的例子说明如何使用这个数据集:

var s2 = ee.ImageCollection("COPERNICUS/S2"),
 
    s2_cloud = ee.ImageCollection("COPERNICUS/S2_CLOUD_PROBABILITY"),
 
    point = /* color: #98ff00 */ee.Geometry.Point([116.20553071765003, 39.404020061278715]);
 
/**
*
* remove cloud by probability bands
*
* */
 
function rmCloudByProbability(image, thread) {
 
  var prob = image.select("probability");
 
  return image.updateMask(prob.lte(thread));
 
}
 
/**
*
* scale image
*
* */
 
function scaleImage(image) {
 
  var time_start = image.get("system:time_start");
 
  image = image.divide(10000);
 
  image = image.set("system:time_start", time_start);
 
  return image;
 
}
 
function getMergeImages(primary, secondary) {
 
  var join = ee.Join.inner();
 
  var filter = ee.Filter.equals({
 
    leftField: 'system:index',
 
    rightField: 'system:index'
 
  });
 
  var joinCol = join.apply(primary, secondary, filter);
 
  joinCol = joinCol.map(function(image) {
 
    var img1 = ee.Image(image.get("primary"));
 
    var img2 = ee.Image(image.get("secondary"));
 
    return img1.addBands(img2);
 
  });
 
  return ee.ImageCollection(joinCol);
 
}
function main() {
 
  var startDate = "2019-4-4";
 
  var endDate = "2019-4-8";
 
  Map.centerObject(point, 8);
 
  var s2Imgs1 = s2.filterDate(startDate, endDate)
 
                  .filterBounds(point)
 
                  .map(scaleImage);
 
  var s2Imgs2 = s2_cloud.filterDate(startDate, endDate)
 
                        .filterBounds(point);
 
  var s2Imgs = getMergeImages(s2Imgs1, s2Imgs2);
 
  s2Imgs = s2Imgs.map(function(image) {
 
    return rmCloudByProbability(image, 50);
 
  });
 
  Map.addLayer(s2Imgs.first(), {min:0, max:0.3, bands:["B4", "B3", "B2"]}, "cloud");
 
}
 
main();

运行效果:

代码分析:

    从上述代码可以看到,由于这是两个数据集,所以我们首先需要将筛选后的两个数据(s2Imgs1和s2Imgs2)利用join合并为一个数据集,具体方法参考getMergeImages(xxx)。合并后的影像中每一幅都包含一个叫做”probability“的波段,这个波段计算的就是云掩膜的信息(值范围是0-100)。程序中我们利用rmCloudByProbability(image, threshold)方法传入影像和云量阈值,就可以实现去云操作。


其实还有一种方法就是利用GEE封装好的模块算法来实现去云,具体的方法是:

编辑

但是这个方法有一定的缺陷,大家想要用的话可以自行研究一下。

    总结一下,这里面介绍了目前常用的哨兵2的去云方法,也展示了对于同一景影像不同去云方法最终实现的效果,大家可以通过对比来选择使用具体的方法来做,也可以同时结合多种算法来实现去云。需要说明的一点就是去云操作本身就没有完全完美的算法,每一种算法都有自己的缺陷和不足。以上面第三种最新的算法来说,它在大部分区域上计算云掩膜都比较不错,但是在某些特定的水体上却有问题,会把无云的地方计算的云量分数非常高。

来源请引用:地理遥感生态网科学数据注册与出版系统

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

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

相关文章

B树与B+树

B树 B树的定义 1970年&#xff0c;R.Bayer和E.mccreight提出了一种适用于外查找的树&#xff0c;它是一种平衡的多叉树&#xff0c;称为B树&#xff08;或B-树、B_树&#xff09;。我们描述一颗B树时需要指定它的阶数&#xff0c;阶数表示了一个结点最多有多少个孩子结点&…

[Android Studio]Android 数据存储--SQLite数据库存储

&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Android Debug&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Topic 发布安卓学习过程中遇到问题解决过程&#xff0c;希望我的解决方案可以对小伙伴们有帮助。 &#x1f4cb;笔记目…

Leetcode_part2

文章目录[406. 根据身高重建队列](https://leetcode.com/problems/queue-reconstruction-by-height/)Solution1 先排序 再插队[409. 最长回文串](https://leetcode.com/problems/longest-palindrome/)Solution1[415. 字符串相加](https://leetcode.com/problems/add-strings/)S…

上采样学习

最近邻 简单来说就是x方向和y方向分别复制 #!/usr/bin/env python # _*_ coding:utf-8 _*_ import numpy as np import torch from cv2 import cv2 from torch import nndef numpy2tensor(x: np.ndarray) -> torch.Tensor:"""(H,W) -> (1, 1, H, W)(H,W…

ShardingSphere-Proxy5按月分表

0、软件版本 ShardingSphere-Proxy&#xff1a; 5.2.0 MySQL&#xff1a; 8.0.30 系统&#xff1a; win10 1、ShardingSphere-Proxy下载 我们可以在 官网 找到最新版ShardingSphere-Proxy下载&#xff0c;也可以在ShardingSphere仓库中下载 2、ShardingSphere-Proxy配置 …

shell编程经典案例,建议收藏

1、编写hello world脚本 #!/bin/bash# 编写hello world脚本echo "Hello World!"2、通过位置变量创建 Linux 系统账户及密码 #!/bin/bash# 通过位置变量创建 Linux 系统账户及密码#$1 是执行脚本的第一个参数,$2 是执行脚本的第二个参数 useradd "$1" …

Linux C++ 200行完成线程池类

文章目录1、atomic使用2、volatile关键字3、条件变量4、成员函数指针使用5、线程池6、主线程先退出对子线程影响7、return、exit、pthread_exit区别8、进程和线程的区别1、atomic使用 原子操作&#xff0c;不可分割的操作&#xff0c;要么完整&#xff0c;要么不完整。 #includ…

vscode开发基于Vue的健身房管理系统node.js

该系统的基本功能包括管理员、会员、教练三个角色功能模块。 对于管理员可以使用的功能模块主要有首页、个人中心&#xff0c;系统公告管理、健身常识管理&#xff0c;会员管理、教练管理、教练考勤管理、会员咨询管理、商品信息管理、团课管理、团课预约管理、论坛管理、系统管…

十三、二叉排序树

1、先看一个需求 给你一个数列 {7, 3, 10, 12, 5, 1, 9} &#xff0c;要求能够高效的完成对数据的查询和添加 2、解决方案分析 使用数组 数组未排序&#xff0c;优点&#xff1a;直接在数组尾添加&#xff0c;速度快。缺点&#xff1a;查找速度慢 数组排序&#xff0c;优点&…

如何推出 NFT 游戏并获得收益?- 综合指南

NFT Gaming - 简介 - NFT 是代表独特内容所有权的数字资产&#xff0c;例如游戏中的一件艺术品或收藏品。它们建立在区块链解决方案之上&#xff0c;允许这些数字资产的真正所有权和稀缺性。 在游戏行业&#xff0c;NFT 用于创建玩家可以拥有和交易的独一无二的游戏内物品。这允…

政企服务机构如何进行数字化转型?

对于服务于政府和企业的产业机构来说&#xff0c;将政府政策和企业发展做完美匹配结合是其根本。在这个过程中&#xff0c;政策信息的准确性、前瞻性、核心价值是服务的基础&#xff0c;只有在政策下可行性高的解决方案才能为政府吸引更多的企业入驻。 那么该类产业机构该如何…

如何理解​session、cookie、token的区别与联系?

session、cookie、token。 相信学过接口的朋友都特别熟悉了。 但是对我一个刚接触接口测试的小白来说&#xff0c;属实有点分不清楚。 下文就是我通过查阅各种资料总结出来的一点理解&#xff0c;不准确的地方还请各位指正。 &#xff08;文末送洗浴中心流程指南&#xff09…

C语言(函数和递归)

函数是完成特定任务的独立程序代码单元。 目录 一.函数 1.创建一个简单的函数 2.定义带形式参数的函数 3.使用return从函数中返回值 二.递归 一.函数 1.创建一个简单的函数 #include <stdio.h> void print(void); //函数原型 int main(){ print(); //函…

Weblogic CVE之旅之T3协议浅学习

前言 这篇文章主要是学习Weblogic CVE漏洞中的过程中&#xff0c;对其中的一种利用方式T3协议反序列化漏洞进行分析。 前置 什么是T3协议&#xff1f; T3协议是一种Weblogic RMI 调用时的通信协议, 对于JAVA RMI(Remote Method Invocation) 来说&#xff0c;基础的通信协议…

Web前端:使用Angular CLI时的最佳实践和专业技巧

在web开发业务中&#xff0c;构建高性能的应用程序是首要因素。此外&#xff0c;用开发人员最流行的语言开发一个健壮的网站将始终为构建高功能的网站提供适当的基础网站。相比之下&#xff0c;不可否认&#xff0c;Angular CLI是建立得最好且正在成长的框架之一。Angular CLI简…

【蓝桥杯嵌入式】第十三届蓝桥杯嵌入式 国赛 程序设计试题以及详细题解

文章目录原题展示原题分析详细题解LED模块按键模块串口LCD模块模拟电压读取(ADC)脉冲输入输出文章福利原题展示 原题分析 本届国赛试题主要包含LCD、LED、按键、EEPROM、串口、模拟电压输入、脉冲输入输出七大部分&#xff0c;其中前面三个部分是蓝桥杯嵌入式的“亲儿子”(必考…

2023年妇女节是哪一天 妇女节是2023年几月几日?

2023年妇女节是哪一天是2023年几月几日&#xff1f; 2023年妇女节是2023年3月8日 三八妇女节是国家法定节假日吗&#xff1f; 妇女节不是国家法定节假日&#xff0c;而国家法定节假日包括&#xff1a;元旦、春节、清明节、劳动节、端午节、中秋节、国庆节&#xff1b; 关于三…

操作系统(day09) -- 连续分配管理方式

连续分配管理方式 单元连续分配 动态分区分配 1.系统要用什么样的数据结构记录内存的使用情况&#xff1f; 两种常用的数据结构 空闲分区表 每个空闲分区对应一个表项。表项中包含分区号、分区大小、分区起始地址等信息空闲分区链 每个分区的起始部分和末尾部分分别设置前向…

硬件学习 软件Cadence day02 画原理图的基本操作 (键盘快捷键 , 原理图设计流程 , 从开始到导出网表流程)

1. ORCAD Capture cls 界面的快捷键 键盘 按键对应的操作I放大 &#xff08;可以滚轮操作&#xff09;O缩小 &#xff08;可以滚轮操作&#xff09;W画线Esc退出现在的状态 &#xff08;画图界面 右键 End xxx&#xff09;N放置网络标号J放置节点 (控制…

花2个月面过华为测开岗,拿个30K不过分吧?

背景介绍 美本计算机专业&#xff0c;代码能力一般&#xff0c;之前有过两段实习以及一个学校项目经历。第一份实习是大二暑期在深圳的一家互联网公司做前端开发&#xff0c;第二份实习由于大三暑假回国的时间比较短&#xff08;小于两个月&#xff09;&#xff0c;于是找的实…