Sentinel-3 OLCI数据下载、解析与批量预处理全流程实战 前两周我帮一个做内陆水体遥感的朋友处理了一批 Sentinel-3 影像他前面折腾了两天卡在“数据下不下来”和“下下来不知道怎么打开”这两个环节上最后我也跟着踩了一遍坑才发现这套数据跟常用的哨兵2号在结构、格式、处理思路上差别还是很大的。这篇文章就把下载、解析、预处理和排错这几个环节完整串一遍直接照着操作就能用。Sentinel-3 的应用面比哨兵2号更偏向“大尺度 水色/温度/地形”这类业务像海面温度、叶绿素浓度、内陆湖泊水质、地表温度、海冰监测都会用到它。它跟哨兵2号最大的区别是数据不是按“景”打包的整幅影像而是按“轨道”切片的产品每个包体积很大目录结构又是.SEN3格式里面还不是一个 GeoTIFF 文件而是嵌套的 NetCDF 和 XML。很多人第一次拿到就懵了其实搞清楚之后就一句话下载靠官网处理靠 SNAP批量靠 snappy。1. 项目背景与数据产品选型1.1 Sentinel-3 到底算哪一路卫星先把它归个类。Sentinel-3 属于极轨光学遥感卫星但它不只有一个光学传感器而是带了三类核心载荷这个跟哨兵2号“单一多光谱成像仪”的区别很大。它上面主要搭载了OLCI海洋与陆地彩色仪专门做水色和陆地植被观测最高分辨率大约 300 米但是有 21 个波段从 400nm 一直覆盖到 1020nm包含多个窄波段特别适合叶绿素、悬浮物、有色溶解有机物这些水质参数的反演。SLSTR海陆表面温度辐射计做海面温度和陆地表面温度有可见光、短波红外和热红外波段分辨率在 500 米到 1 公里左右。SRAL合成孔径雷达高度计测高载荷配合微波辐射计做海平面高度、海浪有效波高、内陆水位变化数据不是影像而是沿轨的剖面数据处理方式完全另一套。我这次处理的偏重 OLCI 的 L1 级辐射率数据和 L2 级水色产品这也是大多数人最大的需求点。重点说清楚 OLCI 就够了SLSTR 的热红外大家以后遇到也可以套用SRAL 则完全是另一种思路先不展开。1.2 常见产品类型怎么选在下载之前最关键的决策是选择产品类型。我见到太多人直接搜 Sentinel-3 然后下了一堆 L0 原始数据打开连波段都看不到就是因为没搞清楚层级。数据产品的基本规律是产品级别含义典型用途Level-0原始压缩数据包基本不能直接用需要解包Level-1B/1C辐射定标后的辐亮度或反射率做大气校正、自定义反演Level-2地球物理参数产品直接得到叶绿素、悬浮物、温度等数值具体到 OLCI 的命名里OL_1_EFR是 1 级亮度产品OL_2_WFR是水色全分辨率产品OL_2_LRR是降分辨率产品。SLSTR 那边则是SL_1_RBT辐射亮度、SL_2_LST地表温度、SL_2_SST海面温度。所以下载之前先问自己三个问题我关心的是水体参数还是陆地参数我要不要自己控制大气校正过程我需要的空间分辨率是 300 米还是可以接受 1 公里左右这三个问题的答案决定了你选哪类产品。提示如果是第一次接触建议直接下载 Level-2 水色产品如OL_2_WFR先跑通全流程它已经做了大气校正省掉最麻烦的一个环节。等流程熟了再回到 Level-1 自己跑预处理。2. 数据下载实操从注册到批量下载2.1 账号注册与权限配置Sentinel-3 数据不在常见的遥感影像地图服务上而是通过官方的数据分发平台获取。首先要注册账号这一步有个容易卡住的点注册后激活邮件可能被丢到垃圾箱而且部分平台的账号激活是人工审核机制短则几分钟长则一两天。我建议注册完就去垃圾邮件里找找不到再用同一邮箱重新发送激活链接。注册成功后不需要申请高级权限默认账号就可以下载哨兵系列光学数据。真正要花点心思的是设置一个“应用”凭据因为后来如果用编程方式调用查询接口需要用到 API Key 或者 Token这个在个人资料页面里生成一次就好别反复生成会导致旧 key 失效。下载有图形页面和 API 两种方式。图形页面简单直观直接在网页地图上画框、选时间、筛产品然后打包下载。但有一个实际操作中特别恼人的点网页方式下多个文件是一个一个跳出来的并不是自动合并成一个压缩包几十个文件会保存到手忙脚乱。而且网页下载经常断线没有断点续传很不友好。我的建议是单景、少量小于 5 个文件用浏览器下载批量数据直接用命令行工具做断点续传省心很多。2.2 查询与筛选产品的关键参数无论用网页还是 API产品筛选都要掌握同样的参数逻辑。下载之前需要确定以下内容时间范围要具体到小时还是全天直接决定返回结果数量。空间范围用经纬度矩形框选而不是画圆形API 只支持矩形查询。卫星编号Sentinel-3A 和 Sentinel-3B 两颗星轨道时间差约半天如果要做同一天密集观测考虑同时抓两颗星的数据。产品类型前面说的OL_1_EFR、OL_2_WFR等。云量OLCI 的云掩膜在 Level-2 里已经给出来但下载筛选接口有时不直接支持需要把候选影像下下来看了才知道云量这个要注意。在网页上按下搜索之后列表里会显示一串像这样的产品名S3A_OL_2_WFR____20240615T031500_20240615T034900_20240615T080144_...很多人一看到这串字符就头大这里解释一下第一个下划线前是卫星然后是产品类型接着是数据采集开始和结束时间再后面是处理时间和内部编号。下载时直接认产品类型和时间两个关键信息就够了。2.3 批量下载与断点续传批量下载我一般写一个简单脚本效果比网页点按好太多。核心是利用命令行工具的断点续传能力这样哪怕中途断网重新启动命令会接着下不会从头再来。文件 URL 从数据平台查询接口里拿到然后逐个下载。为了方便管理我会建一个数据清单文件记录每景的下载链接。# 示例流程先准备好 links.txt每行一个下载直链 while read url; do wget -c -t 5 --timeout180 --user用户名 --password密码 -P ./Sentinel3 $url done links.txt关键点是-c参数也就是断点续传。刚开始我忘了加一个 5GB 的包下了 80% 断开后重下了一遍非常崩溃。另外-t 5是失败重试次数网络波动时很有用。下载过程中建议留意一下磁盘空间一景 OLCI L2 产品解压前可能接近 1GB 到数 GB批量下载之前要确保磁盘有足够空间。如果数据平台提供 Python SDK也可以直接用 Python 脚本做查询和下载一体化原理一样只是把查询接口封装更友好。这个方法适合每天定时拉数据的自动化任务。3. 数据解析与预处理全流程3.1 .SEN3 目录结构长什么样下载下来的文件通常是一个压缩包解压后得到一个.SEN3文件夹。它长这样S3A_OL_2_WFR____20240615T031500_.../ ├── manifest.safe ├── xfdumanifest.xml ├── OLCI_L2_water_full_res/ │ ├── OLCI_L2_water_full_res.nc │ └── ... ├── OLCI_L2_ancillary/ ├── OLCI_L2_quality/ ├── geo_coordinates/ │ ├── geo_coordinates.nc ├── tie_metadata/ │ ├── tie_metadata.nc ├── instrument_data/ ├── time_stamps/第一次打开我会跟你们一样没看到“底图影像”只看到一堆.nc文件和一个xml文件夹第一反应就是怀疑自己是不是下错了。这里必须解释一下Sentinel-3 的影像不是一张经地理编码的 GeoTIFF而是原始的“扫描条带 地理坐标”分开存储结构。geo_coordinates.nc记录每个像素的经纬度tie_metadata.nc记录辅助的大气参数气压、臭氧、水汽等实际辐亮度在一个单独的 NetCDF 文件里。这种格式的好处是保留了原始观测的完整性坏处是必须先把它们合并处理才能得到正常的图像。使用通用图像软件直接打开.nc文件往往只看到一堆乱数据正确做法是使用专门支持SAFE格式的遥感处理软件或者先把波段提取出来做地理编码再输出成 GeoTIFF。开源的 SNAP 是首选因为它是专门为哨兵系列设计的可以完整识别.SEN3结构。3.2 用 SNAP 做几何校正与重采样拿到.SEN3文件夹后第一步是把整个文件夹拖进 SNAP 界面。SNAP 会自动解析 manifest 并把 OLCI 波段加载进来。这时候数据看起来还是“歪的”——因为影像本身没有投影经纬度信息是独立的变量。你必须经过“重采样”操作也就是把每个像素根据其经纬度重新放置到常规地图格网上这个过程在遥感里叫地理编码也叫几何校正。这部分的操作步骤是打开产品后右键选择“Reprojection”工具。在投影参数里选 WGS84 地理坐标系或者按研究区选 UTM 投影。分辨率这里要重点看OLCI 全分辨率产品原生分辨率约 300 米但如果算上扫描角度边缘像素实际更粗所以我一般直接设定输出分辨率 300 米。重采样算法我强烈建议选择 Bilinear 或 Cubic不选 Nearest。因为光谱数据做水体反演时最近邻会让边缘出现锯齿数值跳跃明显。输出格式选 GeoTIFF波段可以选全部也可以只选目标波段。重采样这一步的真正作用是生成一个可以放进 GIS 的图像但 Batch 处理多个文件时不能全靠手工点击必须用命令行批处理工具。先写一个简单的图形处理命令示例场景是把OL_2_WFR中的几个波段重采样投影到 WGS84gpt Reprojection -Poutout.tif -PbandsOa17_reflectance,Oa21_reflectance -PcrsEPSG:4326 -PtargetResolution300 input.SEN3这里gpt是 SNAP 的命令行工具8GB 内存的电脑跑一景大概需要 5 到 15 分钟。真实业务场景我会更推荐用脚本批量处理因为它省去人工介入也因为 SNAP 的图形界面连续开很多景时内存会持续增长容易卡死。3.3 基于 snappy 脚本化批量处理如果说 SNAP 界面是“手动挡”那 snappy 就是“自动挡”。snappy 是 SNAP 提供给 Python 的接口安装 SNAP 后单独配置Python 就能直接打开 .SEN3、读取波段、调用重采样、保存结果。我常年在服务器上用这个做批处理因为服务器没有图形界面脚本化是唯一选择。配置 snappy 的步骤通常包括# 进入 SNAP 安装目录下的 bin 目录 ./snappy-conf /usr/bin/python3配置完成后在 Python 里就可以写这样的代码批量打开、重采样、导出import os import glob from snappy import ProductIO, Product, HashMap input_dir ./Sentinel3 output_dir ./out_tif for path in glob.glob(os.path.join(input_dir, *.SEN3)): product ProductIO.readProduct(path) params HashMap() params.put(crs, EPSG:4326) params.put(targetResolution, 300.0) params.put(resampling, Bilinear) params.put(outputFormat, GeoTIFF) params.put(file, os.path.join(output_dir, os.path.basename(path) .tif)) from snappy import GPF result GPF.createProduct(Reprojection, params, product) ProductIO.writeProduct(result, os.path.join(output_dir, os.path.basename(path)), GeoTIFF) product.dispose()这段代码看起来不复杂但实操中有一堆细节每处理完一景必须调用dispose()否则内存不释放连续处理十景后程序直接 OOM。另外HashMap的键名必须跟 SNAP 内部参数名完全一致大小写都不行第一次我写错了所以一直报错。实用技巧是我会在处理前先打印产品里的波段列表band_names [product.getBandAt(i).getName() for i in range(product.getNumBands())] print(band_names)这一步能极大减少你猜波段名的成本。不同产品版本的波段名可能略有差异先打印再选择比我之前照着旧教程一个名字都不差地抄要可靠得多。如果嫌 SNAP 重采样这一步算得慢还有一个替代方案用 Python 的 xarray 打开 NetCDF 文件自己根据经纬度组合重采样。这个方法更轻量但需要自己实现真值坐标映射代码量不小。对大多数应用SNAP 的重采样已经足够不建议重复造轮子。3.4 数据裁剪与云掩膜处理地理编码完成之后影像带了正确的投影接下来就能进行区域裁剪和云掩膜。很多时候你的研究区只是影像里很小一块直接把整个轨道影像拿去反演纯属浪费计算资源也容易引入远处噪声。我一般先裁剪一遍再分析。裁剪分两种一种按矢量边界裁剪SNAP 里直接支持读取 GeoJSON 或 Shapefile操作时就是右键选择“Spatial Subset”选择“Use Map Projection”再加载矢量文件。另一种是规则矩形裁剪这个用脚本更顺手直接在Reprojection前加一个SubsetOp就行。云掩膜是水体遥感绕不开的环节。OLCI 的 L2 产品里自带质量标记波段通常会有一个类似cloud_flags或quality_flags的变量每一位代表一种质量状态。为了把有云像元剔除不能只看某一个阈值建议把“云标识 高空冰云 耀光”这些标志一起做位运算一次性把坏像元挑出来。实际处理中我发现内陆湖泊周边常有薄云或气溶胶污染L2 自带的云掩膜也经常漏判最好再用可见光反射率阈值法补一层掩膜。一个常见的做法是先读取质量标记波段然后用反射率阈值筛选具体阈值可以定在蓝光波段反射率大于某个值就认为是疑似云但这个值跟季节、太阳高度角有关。我曾经在海边处理一张图时浪花区域被误判成云后来加了“相邻像元一致性”的判断才改善。遇到这种问题没有万能参数必须结合研究区实际情况多次目测。注意深度学习或传统阈值方法各有优劣但在实际做水质反演之前我个人的习惯是先做一次全影像的直方图统计看看波段数值范围是否合理。如果出现异常尖峰大概率是云或太阳耀光没剔除干净。3.5 大气校正的执行策略在做水色参数反演时Level-1 辐射亮度产品必须进行大气校正。OLCI 有自己的官方大气校正处理链SNAP 里也内置了相应的模块可以直接把OL_1_EFR转换成类似OL_2_WFR那样的大气校正产品。但官方产品已经用了固定的辅助气象数据和臭氧数据难道就不需要自己校正了吗不一定。如果你研究区是离岸近、气溶胶复杂的浑浊水体官方 L2 产品在全球算法下结果可能偏差明显这时候就需要用 L1 自己做区域优化。SNAP 里 OLCI 大气校正一般是基于“暗像元 查找表”的算法需要输入高程信息。在沿海区域高程用 SRTM 3 秒数据就行SNAP 会在处理时自动下载或读取本地 DEM。这个模块里选择气溶胶类型大陆型、海洋型、沙漠型等特别重要。内陆湖泊我一般选大陆型近岸海洋水体选海洋型。这个选择不是随便定的它会显著影响蓝光和绿光波段的校正结果进而影响叶绿素反演精度。在输出产品里反射率波段名通常是OaX_reflectance这些值可以进一步用来反演叶绿素 a 浓度。常用做法是波段比值算法比如蓝绿比值法Chl-a 指数 (Oa8_reflectance - Oa5_reflectance) / (Oa8_reflectance Oa5_reflectance)也可以直接用官方 L2 里的chl_nn波段那个是基于神经网络反演的叶绿素浓度产品对大范围水体比较稳但局部异常也多。先做波段组合目视检查再决定用哪个这个环节切勿省。4. 常见问题与排查技巧实录4.1 下载阶段最容易踩的坑数据下载阶段遇到的问题咨询频率最高的无非这么几类注册激活邮件找不到、批量下载断线、查询结果太多不知道选哪个、下载的数据无法解压。注册激活邮件这个问题我见过有人等了一星期没动静后来发现是邮件提供商把激活链接当垃圾邮件过滤掉了。建议注册后立刻把官方域名加入白名单然后再看垃圾箱。如果是人工审核机制超过两天没反应就在查询单里提交一次工单通常一天内就能过。批量下载断线这个问题在下载大文件时高发。有些文件平台是多个下载节点轮询的一旦断线重连后拿到的临时地址变了断点续传就没有意义。我实测的其中一个解决办法是优先请求大文件并且尽量避开服务器高峰时段比如北京时间凌晨到早上成功率明显更高。如果脚本报 403基本是临时链接过期重新生成链接再下。查询结果太多选不过来时我建议先下载一景到本地用 SNAP 打开看一眼再做决定。很多研究区存在大量重复轨道数据完全没必要全下。4.2 处理阶段的数据异常排查使用 SNAP 打开 .SEN3 时最常见的异常包括现象可能原因解决办法打开后一片黑或灰显示拉伸范围不匹配双击波段名重新设置显示最小值/最大值波段数值全部为 -999数据本身是有效值掩码需要对无效值做掩膜不参与显示和统计重采样后图像变形明显使用了最近邻或投影参数不当改用双线性重采样检查投影坐标系设置处理到一半内存溢出同时加载了多个 5GB 产品逐个处理调用 dispose() 释放产品裁剪后影像偏移数百米矢量边界与产品投影不一致把矢量边界转换成产品坐标系再裁剪处理到一半内存溢出这个问题太常见了。SNAP 图形界面默认内存上限可能不足在安装目录里可以调高-Xmx参数比如设置成-Xmx8g至少在 8GB RAM 的机器上会顺畅很多。脚本处理同样有这个问题除了调大虚拟机内存还要注意一景处理完马上释放。还有一个经常被忽略的现象geo_coordinates.nc里的三维数组和处理波段分辨率不一致。OLCI 有“全分辨率”和“降分辨率”两套坐标如果你的产品类型选的是OL_1_ERR降分辨率但代码里按全分辨率的坐标去读就会出现错位。下载前看清楚产品是 “full resolution” 还是 “reduced resolution”处理时别混用。4.3 一次实际处理经验虚构但很有代表性上次我处理某水源地水库的影像选择的是S3B_OL_2_WFR一共三天影像。第一天下载时手滑把所有候选影像都下了结果磁盘空间直接爆满只好删掉了一部分重新筛。处理时发现一个问题其中一景的内陆水体区域反射率明显偏高看起来像“雾霾”。检查质量标志后发现那一片区域有很薄的云但云掩膜没标出来。我后来用近红外波段反射率阈值把可疑像元标记出来又结合邻域一致性过滤才把云区压下去。这个经验说明官方算法在全球范围是可靠的但局部区域性场景一定要人工介入质控。别拿全球产品平均值盲目出结论尤其是面对湖泊这种小尺度水色异常时。5. 实操心得与后续扩展5.1 我的几个习惯接触 Sentinel-3 这么久我沉淀了几个操作习惯对减少无意义的返工很有帮助。第一个习惯是“先看结构再跑流程”。任何新拿到的 .SEN3 目录我都会先用 Python 或者 SNAP 把波段列表、坐标分辨率、质量标志位全部打印出来。确认无误后才进入批量流程。很多批量处理跑到一半才发现波段名不对全盘重来就是因为缺了这一句。第二个习惯是“定量输出质量报告”。我批量处理完所有影像后会生成一个 CSV里面记录每景影像的云覆盖比例、有效像元比例、处理耗时、输出文件大小。这个报告看似简单但在最终写论文或者交成果时非常重要你可以明确说出“有效数据占比多少排除哪些数据为什么排除”也方便向合作方解释。第三个习惯是“异步下载同步处理”。下载大文件期间不要干等着同时开始处理已经下载的一部分。特别是在多个文件需要下载时用队列思想下载一个、处理一个、归档一个会明显缩短整体流程时间。提示如果研究区是多期时间序列建议把每期的数据分目录存放文件名不要乱改保留原始产品名加上自己加的日期后缀这样后面溯源时能直接对应到官方产品。5.2 可以继续做的延伸应用Sentinel-3 的 OLCI 数据在真正用起来之后可以做的时间序列分析很多。常见延伸方向包括利用长时间序列的反射率反演叶绿素和透明度用来监控蓝藻水华的暴发把 OLCI 多波段数据和原位水质站点数据结合做机器学习模型估算总磷、溶解性有机碳也可以把 SLSTR 数据和 OLCI 结合做湖泊表面温度和叶绿素的相关性分析。我最近在用的一套流程是“OLCI 13 波段以上组合 随机森林”做悬浮物浓度反演。由于 300 米分辨率对小型水库来说只有一个到几个像元必须非常谨慎地做云掩膜和邻近陆地像元清除。于是笔者延伸到另一个关键操作把内陆水体像元周围 1 公里内的陆地像元都标记出来避免混合像元对水色信号污染。这个处理步骤虽然没有在官方文档里专门说明但实际做水质反演时影响出奇地大。最后再分享一个脚本小技巧批量处理时在输出目录里放一个processing.log每成功处理一景就写一行记录程序崩了也能知道跑到哪里了下次断点续跑非常方便。这个习惯让我少了很多不必要的重复操作也算是我个人最推荐的一点经验吧。