【遥感时空融合】A new benchmark for spatiotemporal fusion of Sentinel-2 and Sentinel-3 OLCI images数据集处理方法
最近读了一篇新的数据集A new benchmark for spatiotemporal fusion of Sentinel-2 and Sentinel-3 OLCI images | Earth Science Informatics,提供了较新的Sentinel-2和Sentinel-3的数据,相较于之前一直在用的LGC和CIA数据集来说新多了,同时更具有研究价值。
数据下载地址:Evaluation of Spatiotemporal Fusion Methods Using Sentinel-2 And Sentinel-3: A New Benchmark Dataset And Comparison,注意论文里对比的是v1数据集,v2貌似里面有一部分数据是损坏的,v1的三个观测地区已经足够了。
第一个站点 Waterbank 位于澳大利亚东南部的新南威尔士地区,属于森林密布的温带区域。该区域在 2019–2020 年间经历了大规模森林火灾,地表植被变化剧烈,极端天气影响显著,为 STF 方法提供了一个复杂而具有挑战性的测试环境。数据集中从 Sentinel-2 和 Sentinel-3 获取了共 38 对图像配对,每对图像覆盖面积为 1800 × 1800 像素,涵盖多种时间间隔(如 5 天、10 天、35 天等),使模型能够在不同时间跨度上进行预测能力的比较。该站点特别用于验证模型对突变性变化(如火灾烧毁与重建过程)的敏感性与鲁棒性。
第二个站点 Neom City 是沙特阿拉伯正在建设中的智慧城市项目,地处该国西北部红海沿岸的极端干旱地带。该区域具有典型的人为干预特征,如新建城市结构、道路、工地以及裸露地表快速扩张等,因此非常适合评估 STF 模型对城市扩展与人类活动引发的地表变化的响应能力。在 2018–2021 年间,研究者共收集了 65 对 Sentinel-2 与 Sentinel-3 图像对,每对图像大小为 1200 × 1200 像素。这些图像具有较大的时间跨度与频繁的变化模式,为分析 STF 方法对城市化演进的建模能力提供了理想的数据支撑。
第三个站点 Maspalomas 位于西班牙加那利群岛的大加那利岛南部沿海,是一个典型的海岸-沙漠交界区。该区域包含沙丘、海滩、低矮丘陵与部分城市建成区,具有丰富的地形细节与复杂的地表组成。在 2019–2020 年间共构建了 36 对图像对,每幅图像的空间尺寸为 900 × 900 像素,覆盖了从夏季到冬季的多个时间段。Maspalomas 被用于评估 STF 方法在复杂微地形、沙丘移动、干湿变化频繁的自然场景下的细节恢复能力和建模精度。
下载的数据是配准后的原数据,我们一般验证就取6个通道处理就可以了(参照原论文),通道详情如图所示。
根据论文描述,我们需要从S2和S3选取对应的通道进行配对,行成粗细图像对。
那么代码就很好写了,考虑到S2(0~10000)和S3(0~5000)的取值范围不同,这里直接统一归一化成0~1方便后续处理。
import os import rasterio from rasterio.errors import RasterioIOError def extract_bands_by_date(input_root, output_root): os.makedirs(output_root, exist_ok=True) for date_folder in sorted(os.listdir(input_root)): folder_path = os.path.join(input_root, date_folder) if not os.path.isdir(folder_path): continue s2_file = os.path.join(folder_path, f"S2_{date_folder}.tif") s3_file = os.path.join(folder_path, f"S3_{date_folder}.tif") if not os.path.exists(s2_file) or not os.path.exists(s3_file): print(f"[跳过] {date_folder}: 缺少 S2 或 S3 文件") continue try: # 创建输出子目录 out_date_dir = os.path.join(output_root, date_folder) os.makedirs(out_date_dir, exist_ok=True) # 处理 S2 图像(B2, B3, B4, B5, B7, B8A) s2_indices = [0, 1, 2, 3, 5, 7] # 0-based index with rasterio.open(s2_file) as src: # 提前对S2做归一化 s2_data = src.read(indexes=[i + 1 for i in s2_indices]).astype('float32') / 10000.0 s2_meta = src.meta.copy() s2_meta.update(count=len(s2_indices), dtype='float32') out_s2 = os.path.join(out_date_dir, f"S2_{date_folder}_6bands.tif") with rasterio.open(out_s2, 'w', **s2_meta) as dst: dst.write(s2_data) print(f"[✓] 保存 S2: {out_s2}") # 处理 S3 图像(Oa4, Oa6, Oa8, Oa11, Oa16, Oa17) s3_indices = [3, 5, 7, 10, 12, 13] # 0-based index with rasterio.open(s3_file) as src: # 提前对S3做归一化 s3_data = src.read(indexes=[i + 1 for i in s3_indices]).astype('float32') / 5000.0 s3_meta = src.meta.copy() s3_meta.update(count=len(s3_indices), dtype='float32') out_s3 = os.path.join(out_date_dir, f"S3_{date_folder}_6bands.tif") with rasterio.open(out_s3, 'w', **s3_meta) as dst: dst.write(s3_data) print(f"[✓] 保存 S3: {out_s3}") except RasterioIOError as e: print(f"[错误] {date_folder}: 无法读取图像文件: {e}") except Exception as e: print(f"[异常] {date_folder}: 处理时发生错误: {e}") # === 示例使用 === if __name__ == "__main__": input_root = r"D:\迅雷下载\数据集\Maspaloma" # 原始输入目录 output_root = r"D:\迅雷下载\数据集\Maspaloma-processed" # 输出保存路径 extract_bands_by_date(input_root, output_root)