简介:这份资源面向遥感数据处理初学者与测绘、环境监测等领域的从业者,聚焦Sentinel-1与Sentinel-2影像的SNAP预处理流程,帮助读者解决SAR与光学数据从原始产品到可用影像的标准化处理问题。压缩包内仅含1个docx文档,体积约24.27MB,以图文并茂的指导书形式呈现,便于按步骤对照操作。内容覆盖Sentinel-1的辐射定标、地形辐射校正、几何校正投影、斑点滤波、多视处理与GeoTIFF导出,以及Sentinel-2的RGB读取、元数据查看、辐射定标、Sen2Cor 2.4.0大气校正与重采样,并附有Sen2Cor下载安装方法。每一步均配有界面截图与参数设置说明,读者可据此独立完成从数据导入到成果输出的完整链路,快速掌握SNAP核心工具的使用技巧。目前已有6422人学习下载,适合需要系统入门SAR与光学遥感预处理的读者参考。
1. 遥感 SAR 数据处理里,SNAP 到底替我们省掉了哪几步
哨兵一号(Sentinel-1)是 C 波段合成孔径雷达,哨兵二号(Sentinel-2)是多光谱光学载荷,两者数据在 SNAP 里的处理链路完全不是一回事。很多刚接触遥感 SAR 数据处理的人会把它们混在一个流程里跑,结果要么是 S1 的 GRD 产品被当成光学影像去大气校正,要么是 S2 的 L2A 数据硬塞进干涉流程,白白浪费几个小时。SNAP 是欧空局主导的开源遥感处理平台,它把哨兵系列产品的轨道校正、辐射定标、斑点滤波、地形校正、重采样这些步骤封装成了可批处理的算子图。这篇文章面向的是需要把 Sentinel-1 和 Sentinel-2 数据从原始产品处理到可分析栅格的从业者,不管你是做地表形变监测、作物分类还是水体提取,预处理这一步绕不过去。我会把 SNAP 里两条链路的参数怎么设、坑在哪、批处理脚本怎么写讲清楚,让你拿到数据就能照着跑。
2. Sentinel-1 预处理链路:从 GRD 到地形校正后后向散射系数
2.1 为什么 S1 的 GRD 不能直接拿来用
Sentinel-1 的 Ground Range Detected 产品已经做过多视和地距投影,但它仍然是斜距几何下的强度影像,像元值受入射角、天线增益和地形起伏影响极大。直接拿 GRD 做阈值分割或者分类,同一地物在不同轨道、不同入射角下的后向散射系数能差出 3 dB 以上,这个量级足以让水体和非水体的边界完全糊掉。所以标准链路是:应用精密轨道文件 → 辐射定标 → 斑点滤波 → 地形校正 → 分贝化。SNAP 里对应的是 Apply-Orbit-File、Radiometric-Calibration、Speckle-Filtering、Terrain-Correction 四个算子,顺序不能乱,尤其是地形校正必须在辐射定标之后,否则 DEM 重采样会引入额外的辐射畸变。
2.2 用 GPT 命令行跑通 S1 预处理的最小图
SNAP 的图形界面适合调参,但批量处理必须用 GPT(Graph Processing Tool)。下面是一个可复用的 XML 图定义,保存为 s1_preprocess.xml,然后通过命令行调用。
<graph id="s1_preprocess"> <version>1.0</version> <node id="Read"> <operator>Read</operator> <sources/> <parameters> <file>${source}</file> </parameters> </node> <node id="Apply-Orbit-File"> <operator>Apply-Orbit-File</operator> <sources><source>Read</source></sources> <parameters> <orbitType>Sentinel Precise (Auto Download)</orbitType> <polyDegree>3</polyDegree> <continueOnFail>true</continueOnFail> </parameters> </node> <node id="Radiometric-Calibration"> <operator>Radiometric-Calibration</operator> <sources><source>Apply-Orbit-File</source></sources> <parameters> <outputImageInComplex>false</outputImageInComplex> <outputImageScaleInDb>false</outputImageScaleInDb> </parameters> </node> <node id="Speckle-Filtering"> <operator>Speckle-Filtering</operator> <sources><source>Radiometric-Calibration</source></sources> <parameters> <filter>Lee</filter> <filterSizeX>5</filterSizeX> <filterSizeY>5</filterSizeY> <dampingFactor>2</dampingFactor> </parameters> </node> <node id="Terrain-Correction"> <operator>Terrain-Correction</operator> <sources><source>Speckle-Filtering</source></sources> <parameters> <demName>SRTM 1Sec HGT</demName> <pixelSpacingInMeter>10.0</pixelSpacingInMeter> <mapProjection>WGS84(DD)</mapProjection> <nodataValueAtSea>false</nodataValueAtSea> </parameters> </node> <node id="Write"> <operator>Write</operator> <sources><source>Terrain-Correction</source></sources> <parameters> <file>${target}</file> <formatName>GeoTIFF</formatName> </parameters> </node> </graph>这个图里几个参数值得单独说。orbitType 选 Sentinel Precise 会自动从 ESA 的轨道服务器拉取精密轨道文件,如果网络不通就退回到 Restituted,精度差几厘米但对大多数应用够用。polyDegree 设为 3 是轨道拟合多项式阶数,除非你的研究区跨越很大纬度范围,否则 3 阶足够。Speckle-Filtering 里 Lee 滤波的窗口 5x5 是经验值,窗口越大平滑越狠但空间细节丢得越多,做小尺度地块分类时建议降到 3x3。Terrain-Correction 的 pixelSpacingInMeter 设 10 米是 S1 IW 模式 GRD 的标称分辨率,设太小会插值出虚假细节,设太大又浪费信息。
命令行调用方式:
gpt s1_preprocess.xml -Psource=/data/S1A_IW_GRDH_1SDV_20240101T120000_20240101T120025_052000_064A1B_1A2C.zip -Ptarget=/output/s1_terrain_corrected.tif-P 后面跟的是图里用 ${} 引用的变量。GPT 默认使用 SNAP 安装目录下的 snappy 配置,如果报 Java 堆内存不足,在 gpt 命令前加-J-Xmx8G调大堆内存。处理一景 IW GRD 大约需要 3 到 5 分钟,取决于 DEM 缓存是否命中。
2.3 地形校正后为什么还要做分贝化和入射角归一化
地形校正输出的后向散射系数是线性功率值,动态范围极大,直接做统计或者可视化会很难看。分贝化就是 10*log10(sigma0),SNAP 里可以在 Write 之前加一个 BandMaths 算子,表达式写10*log10(band1)。但更隐蔽的问题是入射角效应:同一景影像里近距端和远距端的入射角能差 10 度以上,后向散射系数随入射角变化明显。做变化检测或者跨轨道比较时,常见做法是用余弦校正或者经验线性模型做入射角归一化。SNAP 没有现成的入射角归一化算子,我一般是在 BandMaths 里用sigma0 / cos(incident_angle)做粗略校正,或者导出到 Python 里用回归拟合。这一步不做,跨时相比较的误差可能比真实变化还大。
3. Sentinel-2 预处理链路:从 L1C 到 L2A 与重采样
3.1 L1C 和 L2A 的区别决定了你要不要跑 Sen2Cor
Sentinel-2 的 L1C 产品是大气顶层反射率,L2A 是大气底层反射率。如果你的应用是植被指数计算、水体提取或者土地覆盖分类,必须用 L2A,因为大气散射对蓝光和红光波段的影响能到 30% 以上,NDVI 会被严重压缩。SNAP 里集成了 Sen2Cor 插件,但 Sen2Cor 是独立的外部程序,SNAP 只是调用它。很多人卡在 Sen2Cor 的安装和配置上,其实最稳的方式是单独装 Sen2Cor,然后用命令行跑,SNAP 只负责后续的重采样和波段合成。
3.2 用 Sen2Cor 命令行生成 L2A 产品
Sen2Cor 的调用方式如下:
L2A_Process --resolution 10 /data/S2B_MSIL1C_20240101T100000_N0500_R122_T33TUG_20240101T120000.SAFE--resolution 参数指定输出分辨率,可选 10、20、60。设 10 会输出全部波段在 10 米分辨率下的重采样结果,文件体积最大但后续不用再重采样。如果只需要 20 米分辨率的红边波段做植被分析,设 20 能省一半磁盘。Sen2Cor 处理一景 L1C 大约 10 到 20 分钟,主要耗时在气溶胶反演和地表反射率计算。处理完成后会在同目录生成一个 _L2A 后缀的 SAFE 文件夹。
3.3 在 SNAP 里做波段重采样和裁剪
L2A 产品里不同波段的分辨率不同,10 米的有 B2、B3、B4、B8,20 米的有 B5、B6、B7、B8A、B11、B12,60 米的是 B1、B9、B10。做分类或者指数计算时通常需要统一分辨率。SNAP 里的 Resample 算子可以把所有波段重采样到指定分辨率,然后用 Subset 算子裁剪研究区。
<node id="Resample"> <operator>Resample</operator> <sources><source>Read</source></sources> <parameters> <targetResolution>10</targetResolution> <upsampling>Bilinear</upsampling> <downsampling>Mean</downsampling> <flagDownsampling>Mean</flagDownsampling> </parameters> </node> <node id="Subset"> <operator>Subset</operator> <sources><source>Resample</source></sources> <parameters> <geoRegion>POLYGON((116.0 39.0, 117.0 39.0, 117.0 40.0, 116.0 40.0, 116.0 39.0))</geoRegion> <copyMetadata>true</copyMetadata> </parameters> </node>targetResolution 设 10 表示所有波段都重采样到 10 米。upsampling 用 Bilinear 是上采样插值方法,downsampling 用 Mean 是下采样聚合方法,这两个参数在混合分辨率场景下都会用到。geoRegion 用 WKT 格式写多边形,注意坐标顺序是经度在前纬度在后,和有些 GIS 软件的习惯相反。裁剪能大幅减少后续处理的数据量,尤其是做时间序列分析时,裁剪到研究区能把单景数据从 1 GB 压到几十 MB。
4. 避坑与排查:SNAP 处理 Sentinel 数据时最容易翻车的五个地方
4.1 轨道文件下载失败导致辐射定标偏差
现象是 Apply-Orbit-File 算子报错或者静默跳过,输出影像的几何定位偏移几百米。原因是 SNAP 默认从网络下载精密轨道文件,内网环境或者防火墙策略会阻断。解决方式有两种:一是提前手动下载 AUX_POEORB 文件放到 SNAP 的 orbit 缓存目录,二是在算子参数里把 orbitType 改成 Restituted 并设置 continueOnFail 为 true。我一般会在批处理前先跑一遍轨道下载脚本,确认缓存里有对应日期的文件再开始正式处理。
4.2 地形校正后影像出现大面积 NoData
现象是 Terrain-Correction 输出在山区或者海岸线附近出现条带状或块状空洞。原因是 SRTM 1Sec HGT 在部分区域没有覆盖,尤其是高纬度地区和部分海岛。解决方式是把 demName 换成 SRTM 3Sec 或者外部 DEM,比如 Copernicus DEM 30 米。如果研究区在境外,SNAP 内置的 DEM 自动下载可能很慢,建议提前下载好 DEM 瓦片放到本地目录,然后在 Terrain-Correction 里指定 externalDEMFile 参数。
4.3 Sen2Cor 处理中途卡死或内存溢出
现象是 L2A_Process 跑到气溶胶反演步骤时进程无响应,日志里出现 OutOfMemoryError。原因是 Sen2Cor 默认堆内存只有 2 GB,处理大场景或者多景并行时不够。解决方式是修改 Sen2Cor 安装目录下的 L2A_Process 脚本,把 -Xmx 参数调到 8G 或 16G。另外注意 Sen2Cor 不支持多线程并行,同时跑多个实例会互相抢内存,建议串行处理或者用队列调度。
4.4 重采样后波段顺序和元数据错乱
现象是 Resample 之后用 snappy 读取波段,发现 B8 和 B8A 的顺序和预期不一致,或者波长信息丢失。原因是 SNAP 的 Resample 算子在某些版本里会改变波段索引顺序,尤其是当输入产品包含不同分辨率的波段组时。解决方式是在重采样后显式用 BandSelect 算子按名称选择波段,而不是依赖索引。另外导出 GeoTIFF 时勾选 copyMetadata,否则后续在 Python 里读不到波长和增益信息。
4.5 GPT 批处理时文件句柄泄漏
现象是批量处理几百景数据后,SNAP 报 “Too many open files” 或者处理速度越来越慢。原因是 GPT 每个图执行完不会自动释放所有文件句柄,尤其是当图里有多个 Read 节点或者循环调用时。解决方式是在批处理脚本里每处理完一景就重启一次 GPT 进程,或者用ulimit -n 65536提高系统文件句柄上限。我一般会在 shell 脚本里用 for 循环加 wait 控制并发数,不超过 CPU 核心数的一半。
5. 进阶技巧:用 snappy 在 Python 里做参数扫描和精度验证
SNAP 的图形界面和 GPT 适合固定流程的批处理,但如果你需要做参数敏感性分析,比如比较不同斑点滤波窗口对分类精度的影响,用 snappy 在 Python 里调参会灵活得多。snappy 是 SNAP 的 Python 接口,安装方式是在 SNAP 安装目录下运行snappy-conf脚本,然后把生成的路径加到 PYTHONPATH。
下面是一个用 snappy 做滤波窗口扫描的示例:
import snappy from snappy import ProductIO, GPF, HashMap def preprocess_with_filter(source_path, filter_size): params = HashMap() params.put('filter', 'Lee') params.put('filterSizeX', filter_size) params.put('filterSizeY', filter_size) product = ProductIO.readProduct(source_path) filtered = GPF.createProduct('Speckle-Filtering', params, product) return filtered # 对同一景数据跑 3x3、5x5、7x7 三种窗口 for size in [3, 5, 7]: result = preprocess_with_filter('/data/s1_calibrated.dim', size) target = f'/output/s1_filtered_{size}x{size}.tif' ProductIO.writeProduct(result, target, 'GeoTIFF') print(f'Filter size {size} done')这段代码的关键点是 GPF.createProduct 的第二个参数是 HashMap,键名必须和 SNAP 算子参数名完全一致,大小写敏感。ProductIO.readProduct 读入的是 SNAP 的 DIM 格式,如果是 GeoTIFF 需要先导入。writeProduct 的第三个参数指定输出格式,GeoTIFF 最通用,但会丢失 SNAP 的元数据,如果需要保留完整元数据就写 DIM 格式。
精度验证方面,我一般会拿地形校正后的 sigma0 和同区域的已知地物后向散射系数做对比。比如平静水面的 sigma0 在 C 波段 VV 极化下应该在 -20 dB 左右,如果算出来是 -10 dB 或者 -30 dB,说明辐射定标或者分贝化有问题。另一个验证点是几何精度,用 SNAP 的 Range-Doppler Terrain Correction 输出和 Google Earth 影像叠加,检查道路交叉口或者海岸线的偏移,一般在平坦地区偏移应该小于 1 个像元。
批处理脚本里还有一个容易忽略的点:SNAP 的临时目录默认在系统盘,处理大景数据时临时文件能到几十 GB,系统盘满了会导致处理失败。在 snappy 里可以通过snappy.SystemUtils.setUserDir()修改临时目录,或者在 GPT 命令行里加-Dsnap.userdir=/data/tmp。这个参数在批量处理前一定要设,不然跑到一半磁盘满了,前面的结果全白费。
我自己踩过最狠的一次坑是没检查轨道文件缓存,批处理跑了 200 景数据,结果发现前 50 景的轨道文件下载失败被静默跳过,几何定位全偏了,只能从头重跑。从那以后我养成了一个习惯:正式批处理前先拿一景数据跑完整链路,用 QGIS 叠加底图确认几何和辐射都正常,再开批量。这个前置检查花 10 分钟,能省掉后面几小时的返工。希望帮到你。
本文还有配套的精品资源,点击获取