【GEE】Sentinel-2 数据 实现官方云概率数据集高效去云、NDVI指数计算、同期影像合并、批量导出操作
GEE官方提供了一个云概率数据集,利用该数据集可以实现细小云的去除,去除效果比QA60波段去云的效果要好很多。该数据较高的值更有可能是云或高反射表面(例如屋顶或雪)。
文章目录
一、前言
GEE官方提供了一个云概率数据集 【点击链接可跳转至详情网页】,该数据集中仅有一个波段

其中,针对该波段的官方描述是这样的:
S2 cloud probability 是使用 Sentinel2-cloud- detector 库(使用 LightGBM)创建的。在应用梯度增强基础算法之前,所有频段均使用双线性插值上采样至 10m 分辨率。生成的 0…1 浮点概率缩放为 0…100 并存储为 UINT8。缺少任何或所有条带的区域被遮盖掉。较高的值更有可能是云或高反射表面(例如屋顶或雪)。
二、GEE利用 云概率数据集 对哨兵影像进行去云
传统的 QA60 波段位运算去云函数
function maskS2clouds(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));
return image.updateMask(mask).divide(10000);
}
为了进一步去除细碎云、细小云可进一步利用 S2 cloud probability 数据集进行去云操作
//提取云概率波段的函数,并制作掩膜数据
function rmcloudByProbability(image,thread){
var prob = image.select("probability");
return image.updateMask(prob.lte(thread));
}
//数据集合并函数
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);
}
//设定时间间隔
var dates=['2023-01-11','2023-01-30'];
var startDate = ee.Date(dates[0]);
var endDate = ee.Date(dates[1]);
var S2_images1 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
.filterDate(startDate,endDate)
.filterBounds(roi);
var S2_images2 = ee.ImageCollection("COPERNICUS/S2_CLOUD_PROBABILITY")
.filterDate(startDate,endDate)
.filterBounds(roi);
var S2_datasets = getMergeImages(S2_images1,S2_images2);
S2_datasets = S2_datasets.map(function(image){
return rmcloudByProbability(image,20);//数字越小越严格
})
根据我的具体需求,在撰写过程中,我在数据集的操作中添加了指数计算。主函数的操作逻辑如下:
-
先利用 (‘CLOUDY_PIXEL_PERCENTAGE’,20) 操作对不超过20%云量的数据进行初筛,并进行批量裁剪
-
然后在进行完一系列指数计算后,利用 云概率数据集 S2 cloud probability 进行第二次掩膜去云
//针对影像集中的每一张影像裁剪ROI区域、计算NDVI、导出相应波段
var image_collection = ee.ImageCollection(S2_datasets)
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',20))//数字越小越严格
.map(clip)
.map(get_NDWI)
.map(get_NDBI)
.map(get_NDVI)
.map(function(image){
return rmcloudByProbability(image,20);//数字越小越严格
});
三、GEE批量导出函数 实现对Sentinel-2数据 相同日期影像 合并成一张的操作
在研究区域过大时,同一天内包含不同块大小的影像,可直接进行合并操作
在具体的实现逻辑中,我们首先要解决 如何识别是同一天的影像。GEE中哨兵数据的文件结构中 属性 system:index 的前31位完全相同时,则判定他们是同一天的
-
先将数据集合中所有的文件属性存储起来,并按照属性 system:index 前缀31个字符来进行进行 if 判定操作
-
判定后的影像序列 存放在一个影像集合中,利用最大值合成进行合并(
因为哨兵是对同一天的影像进行切割分块存储的,所以这里合成方式并不影响实际存储的数值) -
最后利用导出函数进行导出
详细代码如下:
function exportImageCollection(imageCol) {
var indexList = imageCol.reduceColumns(ee.Reducer.toList(), ["system:index"]).get("list");
indexList.evaluate(function(indexs) {
// 使用一个对象存储同一天的影像
var groupedImages = {};
// 遍历索引列表,将影像按日期分组
for (var i = 0; i < indexs.length; i++) {
var prefix = indexs[i].slice(0, 31);
if (!groupedImages[prefix]) {
groupedImages[prefix] = [];
}
groupedImages[prefix].push(indexs[i]);
}
// 遍历分组影像,导出最大影像
for (var key in groupedImages) {
var imagesToExport = imageCol.filter(ee.Filter.stringStartsWith('system:index', key));
var image = imagesToExport.max();
image = image.divide(10000).toFloat();
Export.image.toDrive({
image: image.clip(roi), //clip()可要可不要,没有影响
description: key,
fileNamePrefix: "S2_" + key,
folder: 'S2_daily_image ',
region: roi,
scale: 10,
crs: "EPSG:4326",
maxPixels: 1e13
});
}
});
}
细节解释
四、GEE完整代码 (可直接复制运行)
提示:在GEE中运行时,需设置自己所需的 roi 研究区范围
Map.centerObject(roi, 10);
//这里设置了clip的函数操作,通过map操作实现对所有影像的裁剪
function clip(image){
var clipimage = image.clip(roi);
return clipimage;
}
//NDVI计算函数 sentinel used B8 and B4
function get_NDWI(image) {
var NDWI = image.normalizedDifference(['B3', 'B8']).rename(['NDWI']);
return image.addBands(NDWI);
}
//NDVI计算函数 sentinel used B8 and B4
function get_NDBI(image) {
var NDBI = image.normalizedDifference(['B11', 'B8']).rename(['NDBI']);
return image.addBands(NDBI);
}
//NDVI计算函数 sentinel used B8 and B4
function get_NDVI(image) {
var NDVI = image.normalizedDifference(['B8','B4']).rename(['NDVI']);
return image.addBands(NDVI);
}
//提取云概率波段的函数,并制作掩膜数据
function rmcloudByProbability(image,thread){
var prob = image.select("probability");
return image.updateMask(prob.lte(thread));
}
//数据集合并函数
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);
}
//设定时间间隔
var dates=['2023-01-11','2023-01-30'];
var startDate = ee.Date(dates[0]);
var endDate = ee.Date(dates[1]);
var S2_images1 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
.filterDate(startDate,endDate)
.filterBounds(roi);
var S2_images2 = ee.ImageCollection("COPERNICUS/S2_CLOUD_PROBABILITY")
.filterDate(startDate,endDate)
.filterBounds(roi);
//数据集的合并操作
var S2_datasets = getMergeImages(S2_images1,S2_images2);
print("数据集合",S2_datasets)
//针对影像集中的每一张影像裁剪ROI区域、计算NDVI等指数、并进行去云操作
var image_collection = ee.ImageCollection(S2_datasets)
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',20))//数字越小越严格
.map(clip)
.map(get_NDWI)
.map(get_NDBI)
.map(get_NDVI)
.map(function(image){
return rmcloudByProbability(image,20);//数字越小越严格
});
print('Sentinel2_Image_Collection',image_collection)
//真彩色合成显示
var visualization1 = {
min: 0,
max: 3000,
bands: ['B4', 'B3', 'B2'],
};
Map.addLayer(image_collection.median(), visualization1, 'RGB')
// 使用下列波段作为特征
var bands = ['B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8','B11','B12','NDWI','NDBI','NDVI'];
var data_bands = ee.ImageCollection(image_collection).select(bands);
print("dataset_bands",data_bands)
var visParam = {
min: -0.2,
max: 1.0,
palette: [
'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
'66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
'012E01', '011D01', '011301'
],
};
Map.addLayer(data_bands.select("NDVI"), visParam, "ndvi_data");
//单张数据的下载和导出
Export.image.toDrive({
image:data_bands,
description: '2024_03',
folder: '2024_images',
scale: 10,
region:roi
});
function exportImageCollection(imageCol) {
var indexList = imageCol.reduceColumns(ee.Reducer.toList(), ["system:index"]).get("list");
indexList.evaluate(function(indexs) {
// 使用一个对象存储同一天的影像
var groupedImages = {};
// 遍历索引列表,将影像按日期分组
for (var i = 0; i < indexs.length; i++) {
var prefix = indexs[i].slice(0, 31);
if (!groupedImages[prefix]) {
groupedImages[prefix] = [];
}
groupedImages[prefix].push(indexs[i]);
}
// 遍历分组影像,导出最大影像
for (var key in groupedImages) {
var imagesToExport = imageCol.filter(ee.Filter.stringStartsWith('system:index', key));
var image = imagesToExport.max();
image = image.divide(10000).toFloat();
Export.image.toDrive({
image: image.clip(roi),
description: key,
fileNamePrefix: "S2_" + key,
folder: 'S2_daily_image ',
region: roi,
scale: 10,
crs: "EPSG:4326",
maxPixels: 1e13
});
}
});
}
exportImageCollection(data_bands);
五、其他推荐文章
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)