一、前言


去年我写了一篇关于 利用GEE云概率数据集 去云的一篇文章,现在我发现了一个新的去云方法,也是官方推荐的,利用 Cloud Score+数据集 来进行去云,最终效果 经个人的实验发现,应该是最好的 !!!

现在什么chatgpt、gemini 有一个算一个都变笨了,感觉需要喂给它能用的代码才行,不然给我乱写!!!

在这里插入图片描述
其中,针对该数据集中的波段,官方描述是这样的:

Cloud Score+ 是一种质量评估 (QA) 处理器,适用于中高分辨率光学卫星图像。Cloud Score+ S2_HARMONIZED 数据集正基于协调版 Sentinel-2 L1C 集合进行业务化生产,Cloud Score+ 输出可用于识别相对清晰的像素点,并有效去除 L1C(大气层顶部)或 L2A(地表反射率)图像中的云层及云影。这个数据集据说是根据 TOA(大气表观反射率) 的数据进行生产的

Cloud Score+ S2_HARMONIZED 数据集包含两个 QA 波段,即 cscs_cdf,两者均基于地表能见度,对单个像素点的可用性进行 0 到 1 之间的连续量化评分:0 表示观测结果“不清晰”(存在遮挡),1 则表示“清晰”(无遮挡)通俗来说:值越大,云越少,筛选越严格。 cs 波段的 QA 评分取决于观测像素点与(理论上的)清晰参考观测值之间的光谱距离,而 cs_cdf 波段则代表观测像素点为“清晰”的可能性,该可能性基于特定位置随时间推移的评分估算累积分布得出。换句话说,cs 可以被视为一种更具瞬时性的大气相似度评分(即:该像素点与我们预期的完美清晰参考值有多相似),而 cs_cdf 捕捉的则是基于时间推移的估算评分期望(即:如果我们拥有该像素点随时间变化的所有评分,当前这个评分的排名如何?)。

Cloud Score+ S2_HARMONIZED 集合中的图像保留了源 Sentinel-2 L1C 资产的 ID 和 system:index 属性。这意味着,用户可以根据共享的 system:index,将 Cloud Score+ 波段与原始图像连接起来。


二、GEE利用 Cloud Score+ 对哨兵影像进行去云


官方给出的代码和这个是差不多的,写在这里主要是用来增进自己的理解的

// 加载Harmonized Sentinel-2 L2A数据
var s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
          .filterDate(startDate, endDate)
          .filterBounds(roi);

// 加载Cloud Score+数据集 (独立数据集)
var csPlus = ee.ImageCollection('GOOGLE/CLOUD_SCORE_PLUS/V1/S2_HARMONIZED');

// 链接两个数据集(官方推荐方法)
var qaBand = 'cs_cdf'; // 可选'cs'或'cs_cdf',时序分析推荐更稳定的'cs_cdf'
var CLEAR_THRESHOLD = 0.50; // 清晰度阈值,0.50-0.65是常用范围,值越高去云越严
var linkedCollection = s2.linkCollection(csPlus, [qaBand]);

print('链接后的影像集数量:', linkedCollection.size());

// 影像处理流程 (关键优化:移除.map(clip),云掩膜逻辑更新)
var image_collection = linkedCollection
                      // 预过滤掉云量过高的影像
                      .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 80))
                      // 应用Cloud Score+云掩膜
                      .map(function(img) {
                        // 使用动态链接过来的QA波段进行掩膜
                        // 注意: Cloud Score+分数越高表示像素越清晰
                        return img.updateMask(img.select(qaBand).gte(CLEAR_THRESHOLD));
                      })
// Sentinel-2 visualization parameters.
var s2Viz = {bands: ['B4', 'B3', 'B2'], min: 0, max: 2500};

Map.addLayer(image_collection.median(), s2Viz, 'median result');

三、GEE完整代码 (可直接复制运行)


与之前的版本一样,增加了常用的NDVI、NDBI、NDWI、MNDWI指数计算;因为我的研究区比较大,所以选择了分逐个波段进行导出。

我发现:GEE分给普通用户的计算资源越来越少了,原本人家论文里能够运行的代码,我现在点击去就是内存超限,不知道是不是我的错觉!

提示:在GEE中运行时,需设置自己所需的 roi 研究区范围


// ==================================================
// 长时序Sentinel-2影像采集与导出脚本 (使用Cloud Score+)
// 优化点: 
// 1. 使用Cloud Score+ (cs波段) 进行云掩膜
// 2. 移除了上一个版本中常用的.map(clip),避免计算超限
// 3. 仅在导出时对结果影像进行裁剪
// 4. 为了避免超限,进行了逐个波段的导出,并且对 B*原始波段 进行了缩放
// ==================================================

Map.centerObject(roi, 10);

// 1. 指数计算函数集 (保持不变)
function get_NDWI(image) {
  var NDWI = image.normalizedDifference(['B3', 'B8']).rename(['NDWI']);
  return image.addBands(NDWI);
}
function get_NDBI(image) {
  var NDBI = image.normalizedDifference(['B11', 'B8']).rename(['NDBI']);
  return image.addBands(NDBI);
}
function get_NDVI(image) {
  var NDVI = image.normalizedDifference(['B8','B4']).rename(['NDVI']);
  return image.addBands(NDVI);
}
function get_MNDWI(image) {
  var MNDWI = image.normalizedDifference(['B3', 'B11']).rename(['MNDWI']);
  return image.addBands(MNDWI);
}

// 2. 设置时间范围
var dates = ['2021-08-25', '2021-08-30']; // 请修改为您的日期范围
var startDate = ee.Date(dates[0]);
var endDate = ee.Date(dates[1]);

// 3. 加载数据集 (关键修正)
// 3.1 加载Harmonized Sentinel-2 L2A数据
var s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
          .filterDate(startDate, endDate)
          .filterBounds(roi);

// 3.2 加载Cloud Score+数据集 (独立数据集)
var csPlus = ee.ImageCollection('GOOGLE/CLOUD_SCORE_PLUS/V1/S2_HARMONIZED');

// 3.3 链接两个数据集(官方推荐方法)
var qaBand = 'cs_cdf'; // 可选'cs'或'cs_cdf',时序分析推荐更稳定的'cs_cdf'
var CLEAR_THRESHOLD = 0.50; // 清晰度阈值,0.50-0.65是常用范围,值越高去云越严

var linkedCollection = s2.linkCollection(csPlus, [qaBand]);

print('链接后的影像集数量:', linkedCollection.size());

// 4. 影像处理流程 (关键优化:移除.map(clip),云掩膜逻辑更新)
var image_collection = linkedCollection
                      // 预过滤掉云量过高的影像
                      .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 80))
                      // 应用Cloud Score+云掩膜
                      .map(function(img) {
                        // 使用动态链接过来的QA波段进行掩膜
                        // 注意: Cloud Score+分数越高表示像素越清晰
                        return img.updateMask(img.select(qaBand).gte(CLEAR_THRESHOLD));
                      })
                      // 在完整影像上计算指数 (高效)
                      .map(get_NDWI)
                      .map(get_NDBI)
                      .map(get_NDVI)
                      .map(get_MNDWI);

print('处理后影像集:', image_collection);

//真彩色合成显示
var visualization1 = {
  min: 0,
  max: 3000,
  bands: ['B4', 'B3', 'B2'],
};

Map.addLayer(image_collection.median().clip(roi), visualization1, 'RGB');

// 5. 选择需要导出的波段
var bands = [
  'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B11', 'B12',
  'NDWI', 'NDBI', 'NDVI', 'MNDWI'
];
var data_bands = image_collection.select(bands);

// 6. 可视化 (可选)
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'
  ],
};
// 注意:可视化时对最终合成结果进行clip
Map.addLayer(data_bands.select('NDVI').median().clip(roi), visParam, 'NDVI中值 (Cloud Score+)');

// 7. 导出函数 (优化点:仅在最终导出时clip单张影像)
function exportImageCollectionByBand(imageCol, bandList) {
  // 需要做缩放的原始反射率波段
  var rawBands = ['B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B8A', 'B11', 'B12'];
  
  // 为每景影像添加日期字符串属性,用于按日分组
  var colWithDate = imageCol.map(function(img) {
    var dateStr = img.date().format('YYYYMMdd');
    return img.set('dateStr', dateStr);
  });
  
  // 获取唯一的日期列表
  var dateList = ee.List(colWithDate.aggregate_array('dateStr')).distinct();
  
  // 评估日期列表并在客户端执行循环导出任务
  dateList.evaluate(function(dates) {
    if (!dates || dates.length === 0) {
      print('没有找到可导出的数据。');
      return;
    }
    
    print('开始创建导出任务,共', dates.length, '个日期');
    
    dates.forEach(function(dateStr) {
      // 对同一天的影像进行合成 (取最大值合成法)
      var dailyImage = colWithDate
                        .filter(ee.Filter.eq('dateStr', dateStr))
                        .max();
      
      // 逐个波段导出
      bandList.forEach(function(bandName) {
        // 关键优化:先选择波段,再裁剪单张合成影像
        var singleBand = dailyImage.select(bandName).clip(roi);
        
        // 对原始反射率波段进行缩放 (除以10000),指数波段保持不变
        if (rawBands.indexOf(bandName) > -1) {
          singleBand = singleBand.divide(10000).toFloat();
        } else {
          singleBand = singleBand.toFloat();
        }
        
        // 配置导出任务
        Export.image.toDrive({
          image: singleBand,
          description: dateStr + '_' + bandName,
          fileNamePrefix: 'CS_' + dateStr + '_' + bandName,
          folder: 'GEE_S2_CloudScore_Exports',
          region: roi,
          scale: 10,
          crs: 'EPSG:4326',
          maxPixels: 1e13,
          fileFormat: 'GeoTIFF'
        });
      });
    });
  });
}

// 8. 调用导出函数
exportImageCollectionByBand(data_bands, bands);


四、其他推荐文章


【GEE】针对单张影像的单波段批量导出(解决大范围影像所有波段集体导出数据量太大的方法之一)
【GEE】Sentinel-2 数据 实现官方云概率数据集高效去云、NDVI指数计算、同期影像合并、批量导出操作

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐