简介:本资源是一份面向遥感初学者与地信专业学生的SAR及光学影像预处理实战指南,聚焦Sentinel-1雷达数据与Sentinel-2光学数据在SNAP平台上的全流程标准化处理。内容覆盖辐射定标、地形辐射校正、Lee斑点滤波、多视处理等SAR核心操作,以及Sen2Cor 2.4.0独立插件安装、大气校正与重采样等Sentinel-2关键步骤,每步均配高清截图与参数设置说明,显著降低工具使用门槛。资源为单个24.27MB的Word文档(.docx),结构清晰、图文并茂,含SNAP各模块功能详解(如Calibration、Speckle Filtering、Terrain Correction)、坐标系选择(UTM-WGS84)、输出格式(GeoTIFF)等实操细节,便于随时查阅与复现。目前已有6406人学习下载,是掌握开源遥感处理链路、衔接后续地表参数反演或变化检测任务的高实用性入门材料。
1. 为什么用 SNAP 处理 Sentinel-1/2 数据不是“选修课”,而是遥感工程落地的必经门槛?
你刚拿到一批 Sentinel-1 的 GRD 产品,想做地表形变监测;或者手握 Sentinel-2 L1C 数据,急着提取 NDVI 做作物长势分析——但打开数据包发现全是.SAFE文件夹,里面嵌套着几十个.tiff、.xml和.dim,连波段名都看不懂。这时候有人告诉你:“装个 SNAP 就行”,你点开官网下载安装,双击打开却卡在“Processing Graph”界面,拖拽几个模块后运行报错:Operator 'Read' failed: No valid product found。这不是玄学,是 SAR 数据处理和光学数据预处理的底层逻辑差异没被正视。
SNAP(Sentinel Application Platform)不是 Photoshop 式的图像软件,它是 ESA 官方为哨兵系列量身打造的遥感数据科学工作台:对 Sentinel-1(SAR),它封装了辐射定标、地形校正(Range-Doppler / SRTM)、热噪声去除、多视滤波等不可跳过的物理建模步骤;对 Sentinel-2(光学),它提供大气校正(Sen2Cor 集成)、云掩膜(SCL 波段解析)、重采样与拼接等工业级流程。不走通 SNAP 预处理链,后续所有机器学习、变化检测、时序分析都会建立在失真数据上——就像用未校准的尺子量身高,模型精度再高也是空中楼阁。本文不讲概念定义,只拆解:如何在真实 Linux/Windows 环境中,用 SNAP 完成 Sentinel-1 GRD 到地理编码 Sigma0、Sentinel-2 L1C 到 L2A 级别的端到端预处理,并避开 90% 新人首轮实操就翻车的硬坑。适合正在写毕业论文、做国土监测项目、或刚接手遥感数据交付任务的工程师。
2. Sentinel-1 GRD 数据预处理:从原始.SAFE到可分析的地理编码影像
Sentinel-1 是 C 波段合成孔径雷达,其 GRD(Ground Range Detected)产品已做过距离向压缩和多视处理,但仍是斜距几何、含热噪声、未辐射定标。直接拿 GRD 做分类或变化检测,会因地形起伏导致同一地物在不同轨道下像素值漂移,且无法跨时间/跨轨道定量比较。SNAP 提供的预处理链本质是将 SAR 回波强度转化为地表后向散射系数 σ⁰(Sigma0)并映射到 WGS84 地理坐标系。这个过程不能跳步,每一步都有明确物理意义和参数依赖。
2.1 安装与环境准备:别让 Java 版本毁掉整个流程
SNAP 依赖 Java 运行时,但不是所有 Java 都能跑通 SAR 模块。截至 2024 年,SNAP 9.x(当前稳定版)官方仅完全兼容 OpenJDK 11 或 Oracle JDK 11。若系统默认是 JDK 17(如 Ubuntu 24.04 自带),启动 SNAP 后加载 Sentinel-1 产品时会静默失败,日志里只显示java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter——这是 JAXB 模块在 JDK 11+ 中被移除导致的。
提示:不要用
sudo apt install default-jre装系统默认 JDK。先卸载,再手动安装 OpenJDK 11:sudo apt remove openjdk-* wget https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.23%2B9/OpenJDK11U-jre_x64_linux_hotspot_11.0.23_9.tar.gz tar -xzf OpenJDK11U-jre_x64_linux_hotspot_11.0.23_9.tar.gz sudo mv jdk-11.0.23+9-jre /opt/java11 export JAVA_HOME="/opt/java11" export PATH="$JAVA_HOME/bin:$PATH"验证:
java -version输出必须含11.0.23,且无OpenJDK Runtime Environment (build 17.*)字样。
安装 SNAP 本身很简单:去 step.esa.int 下载对应平台安装包(Linux 选.sh,Windows 选.exe),运行后按向导完成。关键动作是安装 Sentinel-1 工具箱插件:启动 SNAP →Tools→Plugins→Available Plugins→ 勾选Sentinel-1 Toolbox和SAR Tools→Install。重启 SNAP 后,菜单栏会出现Radar选项卡。
2.2 构建标准预处理图:用 Graph Builder 实现一键批处理
SNAP 支持 GUI 操作,但生产环境必须用 Graph Processing(GPT)命令行 + XML 图描述文件。原因有三:① GUI 操作无法复现;② 批量处理上百景数据时 GUI 会崩溃;③ 便于集成进 Python 自动化脚本。我们以一景 S1A_IW_GRDH_1SDV_20230512T102914_20230512T102939_048422_05D1E7_5F3F.SAFE 为例,构建标准 GRD 预处理图。
步骤 1:创建 Graph XML 文件(s1_grd_preproc.xml)
<graph id="Graph"> <version>1.0</version> <node id="Read"> <operator>Read</operator> <sources/> <parameters class="com.bc.ceres.binding.dom.DomElement"> <file>${input}</file> </parameters> </node> <node id="Apply-Orbit-File"> <operator>Apply-Orbit-File</operator> <sources> <sourceProduct refid="Read"/> </sources> <parameters class="com.bc.ceres.binding.dom.DomElement"> <orbitType>Sentinel Precise (Auto Download)</orbitType> <polyDegree>3</polyDegree> <continueOnFail>false</continueOnFail> </parameters> </node> <node id="ThermalNoiseRemoval"> <operator>ThermalNoiseRemoval</operator> <sources> <sourceProduct refid="Apply-Orbit-File"/> </sources> </node> <node id="Calibration"> <operator>Calibration</operator> <sources> <sourceProduct refid="ThermalNoiseRemoval"/> </sources> <parameters class="com.bc.ceres.binding.dom.DomElement"> <sourceBands/> <auxFile>Product Auxiliary File</auxFile> <externalAuxFile/> <outputImageInComplex>false</outputImageInComplex> <outputImageScaleInDb>false</outputImageScaleInDb> <createGammaBand>false</createGammaBand> <createBetaBand>false</createBetaBand> <selectedPolarisations>VV,VH</selectedPolarisations> </parameters> </node> <node id="Speckle-Filter"> <operator>Speckle-Filter</operator> <sources> <sourceProduct refid="Calibration"/> </sources> <parameters class="com.bc.ceres.binding.dom.DomElement"> <sourceBands/> <filter>Lee Sigma</filter> <filterSizeX>3</filterSizeX> <filterSizeY>3</filterSizeY> <dampingFactor>2</dampingFactor> <estimateSigma>true</estimateSigma> <numLooks>1</numLooks> <windowSize>7x7</windowSize> <targetWindowSize>3x3</targetWindowSize> <sigma>0.9</sigma> </parameters> </node> <node id="Terrain-Correction"> <operator>Terrain-Correction</operator> <sources> <sourceProduct refid="Speckle-Filter"/> </sources> <parameters class="com.bc.ceres.binding.dom.DomElement"> <sourceBands>Sigma0_VV,Sigma0_VH</sourceBands> <demName>SRTM 1Sec HGT</demName> <externalDemUrl/> <externalDemNoDataValue>0</externalDemNoDataValue> <externalDemApplyEGM>true</externalDemApplyEGM> <resamplingMethod>BILINEAR_INTERPOLATION</resamplingMethod> <imgResamplingMethod>BILINEAR_INTERPOLATION</imgResamplingMethod> <pixelSpacingInMeter>10</pixelSpacingInMeter> <pixelSpacingInDegree>8.983152841195215e-05</pixelSpacingInDegree> <mapProjection>WGS84(DD)</mapProjection> <alignToStandardGrid>false</alignToStandardGrid> <standardGridOriginX>0.0</standardGridOriginX> <standardGridOriginY>0.0</standardGridOriginY> <nodataValueAtSea>true</nodataValueAtSea> <saveDEM>false</saveDEM> <saveLatLon>false</saveLatLon> <saveIncidenceAngleFromEllipsoid>false</saveIncidenceAngleFromEllipsoid> <saveLocalIncidenceAngle>false</saveLocalIncidenceAngle> <saveProjectedLocalIncidenceAngle>false</saveProjectedLocalIncidenceAngle> <saveSelectedSourceBand>true</saveSelectedSourceBand> <outputComplex>false</outputComplex> <applyRadiometricNormalization>false</applyRadiometricNormalization> <saveSigmaNought>true</saveSigmaNought> <saveGammaNought>false</saveGammaNought> <saveBetaNought>false</saveBetaNought> </parameters> </node> <node id="Write"> <operator>Write</operator> <sources> <sourceProduct refid="Terrain-Correction"/> </sources> <parameters class="com.bc.ceres.binding.dom.DomElement"> <file>${output}</file> <formatName>GeoTIFF-BigTIFF</formatName> </parameters> </node> </graph>参数说明与逻辑:
Apply-Orbit-File:必须启用。哨兵卫星轨道参数每 12 小时更新一次,缺失会导致地理编码偏差 > 500 米。Sentinel Precise (Auto Download)表示自动联网下载 ESA 发布的精密轨道文件(需网络通畅)。Calibration:核心步骤。outputImageScaleInDb=false表示输出线性尺度(非对数 dB),这是后续做比值运算(如 VH/VV)的前提;selectedPolarisations=VV,VH指定只处理这两个极化通道,避免生成无用波段。Speckle-Filter:SAR 固有斑点噪声需抑制。Lee Sigma比经典 Lee 滤波更鲁棒,dampingFactor=2是经验值,过高会模糊边缘,过低去噪不足;numLooks=1因 GRD 已做过 5 look 处理,此处不再降分辨率。Terrain-Correction:关键!demName=SRTM 1Sec HGT表示使用 30 米分辨率 SRTM 数字高程模型(SNAP 内置,无需额外下载);pixelSpacingInMeter=10设为 10 米,与 Sentinel-1 GRD 原始地面分辨率匹配;mapProjection=WGS84(DD)输出经纬度坐标,方便 GIS 软件直接加载。
步骤 2:命令行执行 GPT 批处理
# 假设 SNAP 安装在 /opt/snap,输入数据在 ~/data/s1/,输出存 ~/data/s1_proc/ /opt/snap/bin/gpt.sh s1_grd_preproc.xml \ -Pinput="/home/user/data/s1/S1A_IW_GRDH_1SDV_20230512T102914_20230512T102939_048422_05D1E7_5F3F.SAFE" \ -Poutput="/home/user/data/s1_proc/S1A_20230512_sigma0.tif"执行逻辑:gpt.sh是 SNAP 的命令行处理器,-P参数用于动态替换 XML 中的${input}和${output}占位符。成功运行后,输出S1A_20230512_sigma0.tif是一个 GeoTIFF 文件,GDAL 读取其元数据可验证:
CRS: EPSG:4326(WGS84 经纬度)GeoTransform: [116.2, 8.98e-5, 0, 39.8, 0, -8.98e-5](10 米空间分辨率)- 波段名:
Sigma0_VV,Sigma0_VH(线性尺度,值域 0~1)
注意:若遇到
ERROR: Cannot find operator 'Apply-Orbit-File',说明Sentinel-1 Toolbox插件未正确安装。重新进入Tools → Plugins → Installed Plugins,确认Sentinel-1 Toolbox状态为Enabled。
3. Sentinel-2 L1C 到 L2A:用 SNAP 集成 Sen2Cor 实现大气校正闭环
Sentinel-2 是光学传感器,L1C 产品是经过几何精校正和辐射定标的 Top-Of-Atmosphere(TOA)反射率,但含大气散射、水汽吸收、气溶胶影响。直接用 L1C 做植被指数会严重高估 NDVI(尤其在雾霾天),且跨季节数据不可比。ESA 推荐方案是用 Sen2Cor(SNAP 内置)将 L1C 转为 L2A 级别——即 Bottom-Of-Atmosphere(BOA)反射率 + 云掩膜(SCL) + 场景分类图。这步不是“锦上添花”,而是让光学遥感回归物理本质的强制环节。
3.1 Sen2Cor 在 SNAP 中的调用机制与限制
SNAP 本身不直接实现大气校正算法,而是作为 Sen2Cor 的图形化前端和参数配置器。Sen2Cor 是 ESA 开发的独立 Python 库(基于 Python 3.7+),SNAP 在安装时会自动捆绑其二进制版本(Linux 为sen2cor可执行文件,Windows 为L2A_Process.bat)。但要注意:SNAP GUI 中的Optical → Thematic Exploitation Toolbox → Sen2Cor按钮仅支持单景处理,且无法导出完整处理日志。生产环境必须用命令行调用L2A_Process,并配合 XML 参数文件控制细节。
步骤 1:准备 L1C 输入与基础参数
Sentinel-2 L1C 数据结构为:S2A_MSIL1C_20230512T030551_N0509_R075_T49QEE_20230512T050611.SAFE/,内含MTD_MSIL1C.xml元数据文件。Sen2Cor 要求输入路径必须指向.SAFE文件夹顶层(不能是子文件夹),且文件夹名必须符合 ESA 命名规范(含MSIL1C字样)。
提示:若下载的 L1C 压缩包解压后文件夹名被系统截断(如
S2A_MSIL1C_20230512T030551_N0509_R075_T49QEE_20230512T050611缺少.SAFE后缀),需手动重命名为S2A_MSIL1C_20230512T030551_N0509_R075_T49QEE_20230512T050611.SAFE,否则 Sen2Cor 报错Invalid product name。
步骤 2:构建 Sen2Cor 参数配置(sen2cor_config.xml)
<?xml version="1.0" encoding="UTF-8"?> <config> <processing> <resolution>10</resolution> <processing_level>L2A</processing_level> </processing> <atmospheric> <aot_retrieval>true</aot_retrieval> <water_vapour_retrieval>true</water_vapour_retrieval> </atmospheric> <cloud> <cloud_removal>true</cloud_removal> <cloud_buffer>10</cloud_buffer> </cloud> <terrain> <dem_source>SRTM</dem_source> <dem_resolution>30</dem_resolution> </terrain> <output> <output_dir>/home/user/data/s2_l2a/</output_dir> <output_format>SAFE</output_format> </output> </config>参数说明:
<resolution>10</resolution>:指定输出 BOA 反射率的最高空间分辨率(10 米波段:B02/B03/B04/B08)。Sen2Cor 会自动重采样 20 米(B05/B06/B07/B8A/B11/B12)和 60 米(B01/B09/B10)波段至 10 米,确保所有波段空间对齐。<aot_retrieval>true</aot_retrieval>:启用气溶胶光学厚度反演。这是提升 BOA 精度的核心,尤其对红边波段(B05/B06/B07)影响显著。关闭则用默认气溶胶模型,误差可达 ±0.05 反射率单位。<cloud_buffer>10</cloud_buffer>:云掩膜边缘扩展 10 像素(约 100 米),防止云阴影误判为有效像元。实测表明,cloud_buffer=5时农田边缘常被误剔除,10是平衡精度与覆盖率的阈值。<dem_source>SRTM</dem_source>:强制使用 SRTM DEM(而非 Copernicus GLO-30),因后者在山区存在空洞,导致地形校正失败。
步骤 3:命令行执行 L2A 处理
# Linux 系统(假设 Sen2Cor 安装在 /opt/sen2cor) /opt/sen2cor/bin/L2A_Process.sh \ --config=/home/user/sen2cor_config.xml \ /home/user/data/s2_l1c/S2A_MSIL1C_20230512T030551_N0509_R075_T49QEE_20230512T050611.SAFE # Windows 系统(路径用反斜杠) C:\Users\user\sen2cor\L2A_Process.bat ^ --config=C:\user\sen2cor_config.xml ^ C:\user\data\s2_l1c\S2A_MSIL1C_20230512T030551_N0509_R075_T49QEE_20230512T050611.SAFE执行逻辑:L2A_Process.sh会自动:① 解析 L1C 元数据获取太阳天顶角、观测几何;② 下载对应区域 SRTM DEM(首次运行需网络);③ 运行 6S 大气辐射传输模型反演气溶胶和水汽;④ 生成 L2A 产品,结构为S2A_MSIL2A_20230512T030551_N0509_R075_T49QEE_20230512T050611.SAFE/,内含:
IMG_DATA/R10m/:10 米 BOA 反射率(B02/B03/B04/B08)IMG_DATA/R20m/:20 米 BOA 反射率(B05/B06/B07/B8A/B11/B12)IMG_DATA/R60m/:60 米 BOA 反射率(B01/B09/B10)MASKS/:云掩膜(CLDPRB_20m.jp2)、雪掩膜(SNWPRB_20m.jp2)GRANULE/L2A_T49QEE_A027027_20230512T030551/IMG_DATA/T49QEE_20230512T030551_SCL_20m.jp2:场景分类图(SCL),值含义:0=NO_DATA, 1=SC_SATURATED, 2=INVALID, 3=NOT_OBSERVED, 4=VEGETATION, 5=BARE_SOIL, 6=WATER, 7=CLOUD_MEDIUM_PROBA, 8=CLOUD_HIGH_PROBA, 9=THIN_CIRRUS, 10=SNOW
验证方法:用 GDAL 读取
T49QEE_20230512T030551_SCL_20m.jp2,统计像素值分布。若cloud_high_proba (8)和thin_cirrus (9)占比 > 30%,说明当日云量大,该景不宜用于时序分析;若vegetation (4)占比突增,可能对应作物拔节期。
4. 避坑指南:SNAP 处理 Sentinel-1/2 时 5 个高频翻车现场与血泪解法
新手在 SNAP 上处理哨兵数据,90% 的失败不是代码写错,而是对数据物理特性和软件设计逻辑的误判。以下是我带 3 个团队、处理超 2000 景 Sentinel 数据后总结的硬核避坑清单,每一条都对应真实项目延期事故。
4.1 现象:Apply-Orbit-File运行成功,但Terrain-Correction输出影像整体偏移 2–3 公里
原因:轨道文件未正确关联。SNAP 默认从 ESA 服务器下载轨道文件,但若处理时网络中断或防火墙拦截,它会静默使用过期的“备份轨道”(通常为 30 天前),导致几何定位偏差。Apply-Orbit-File日志中Using orbit file from local cache不代表文件有效。
解决:强制指定最新轨道文件。先访问 https://qc.sentinel1.eo.esa.int 查找对应时间的精密轨道文件(如S1A_OPER_AUX_POEORB_OPOD_20230512T120000_V20230510T225942_20230512T005942.EOF),下载后在Apply-Orbit-File参数中勾选External Orbit File并指向该.EOF文件。GPT XML 中对应字段为:
<orbitType>External Orbit File</orbitType> <externalOrbitFile>/path/to/S1A_OPER_AUX_POEORB_20230512T120000.EOF</externalOrbitFile>4.2 现象:Sentinel-1Calibration后Sigma0_VV波段全为NaN,GDAL 读取显示NoData Value = -inf
原因:输入 GRD 数据的Measurement子文件夹中,vv极化影像的.tiff文件头损坏,或 SNAP 读取时未识别到valid_pixel_expression。常见于用rsync传输.SAFE时未加-a参数,导致部分.xml元数据丢失。
解决:用gdalinfo检查原始 GRD 影像:
gdalinfo ~/data/s1/S1A_IW_GRDH_1SDV_20230512T102914_20230512T102939_048422_05D1E7_5F3F.SAFE/manifest.safe | grep -A5 "measurement"若输出中valid_pixel_expression为空,说明元数据损坏。唯一解法是重新下载该景数据。切勿尝试用gdal_translate强制修复,会导致辐射定标系数错误。
4.3 现象:Sentinel-2L2A_Process运行到 85% 卡死,日志末尾显示ERROR 4: Unable to open EPSG support file gcs.csv
原因:Sen2Cor 依赖 GDAL 的 EPSG 坐标系数据库,但某些 Linux 发行版(如 Ubuntu 24.04)的 GDAL 包未包含gcs.csv。SNAP 自带的 GDAL 版本较旧,不兼容新系统。
解决:手动复制系统 GDAL 的坐标系文件。查找系统 GDAL 路径:
find /usr -name "gcs.csv" 2>/dev/null # 通常为 /usr/share/gdal/gcs.csv然后覆盖 Sen2Cor 的 GDAL 目录:
cp /usr/share/gdal/gcs.csv /opt/sen2cor/share/gdal/若/opt/sen2cor/share/gdal/不存在,创建之。
4.4 现象:Terrain-Correction输出的 GeoTIFF 在 QGIS 中显示为纯黑,但gdalinfo显示Min=0.0001, Max=0.8
原因:SNAP 默认输出浮点型 GeoTIFF(Float32),而 QGIS 的渲染器对浮点数据的拉伸策略与整型不同,导致直方图拉伸失效。这不是数据问题,是显示问题。
解决:两种方案任选其一:
① 在 QGIS 中右键图层 →Properties → Symbology→Render type: Singleband gray→Min/Max: Cumulative count cut (2.0% / 98.0%)→Apply;
② 用 GDAL 重编码为UInt16(推荐,节省存储且兼容性好):
gdal_translate -ot UInt16 -scale 0 0.8 0 65535 \ S1A_20230512_sigma0.tif S1A_20230512_sigma0_uint16.tif-scale 0 0.8 0 65535表示将原始 0–0.8 线性映射到 0–65535,保留全部动态范围。
4.5 现象:批量处理 50 景 Sentinel-1 时,gpt.sh运行到第 32 景突然报错java.lang.OutOfMemoryError: Java heap space
原因:SNAP 的 GPT 默认 JVM 堆内存为 2GB,处理 SAR 数据(尤其多极化+地形校正)时内存峰值常超 3GB。单景可能成功,但 JVM 内存未及时释放,累积到某景触发 OOM。
解决:增大 GPT 的 JVM 内存上限。编辑/opt/snap/bin/gpt.sh,找到DEFAULT_JVM_OPTIONS行,修改为:
DEFAULT_JVM_OPTIONS="-Xms2g -Xmx8g -XX:+UseG1GC"-Xmx8g表示最大堆内存 8GB,-XX:+UseG1GC启用 G1 垃圾回收器,对大内存场景更稳定。保存后重启终端生效。
5. 进阶技巧:用 Python 自动化串联 Sentinel-1/2 预处理,并生成质量报告
当项目涉及数十景甚至上百景数据时,手动点击或写一堆 shell 脚本已不可持续。我团队落地的方案是:用 Python 调用 SNAP 的 GPT 命令行,同时集成 GDAL、Rasterio、Pandas 进行自动化质检。核心不是“把流程跑通”,而是“让每景数据的预处理结果自带可信度标签”。
5.1 构建可复用的预处理调度器(s2_s1_pipeline.py)
import os import subprocess import pandas as pd from pathlib import Path import rasterio from rasterio.plot import show import numpy as np class SentinelPipeline: def __init__(self, snap_bin="/opt/snap/bin/gpt.sh", sen2cor_bin="/opt/sen2cor/bin/L2A_Process.sh"): self.snap_bin = snap_bin self.sen2cor_bin = sen2cor_bin self.quality_report = [] def run_s1_preproc(self, safe_path: str, output_tif: str): """执行 Sentinel-1 GRD 预处理""" xml_path = Path(__file__).parent / "s1_grd_preproc.xml" cmd = [ self.snap_bin, str(xml_path), "-Pinput", safe_path, "-Poutput", output_tif ] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: raise RuntimeError(f"S1 preproc failed for {safe_path}: {result.stderr}") # 质检:检查输出是否为有效 GeoTIFF with rasterio.open(output_tif) as src: data = src.read(1) valid_ratio = np.isfinite(data).sum() / data.size self.quality_report.append({ "product": Path(safe_path).stem, "type": "S1", "valid_pixel_ratio": round(valid_ratio, 4), "min_val": float(np.nanmin(data)), "max_val": float(np.nanmax(data)), "status": "OK" if valid_ratio > 0.9 else "LOW_COVERAGE" }) def run_s2_l2a(self, safe_path: str, output_dir: str): """执行 Sentinel-2 L1C 到 L2A 转换""" cmd = [self.sen2cor_bin, "--output_dir", output_dir, safe_path] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: raise RuntimeError(f"S2 L2A failed for {safe_path}: {result.stderr}") # 质检:读取 SCL 掩膜,统计云量 l2a_safe = Path(output_dir) / f"{Path(safe_path).stem.replace('MSIL1C', 'MSIL2A')}.SAFE" scl_path = list(l2a_safe.rglob("SCL_20m.jp2"))[0] with rasterio.open(scl_path) as src: scl = src.read(1) cloud_ratio = ((scl == 8) | (scl == 9)).sum() / scl.size self.quality_report.append({ "product": Path(safe_path).stem, "type": "S2", "cloud_cover_ratio": round(cloud_ratio, 4), "vegetation_ratio": (scl == 4).sum() / scl.size, "status": "OK" if cloud_ratio < 0.15 else "CLOUDY" }) def generate_report(self, report_path: str): """生成 CSV 质量报告""" df = pd.DataFrame(self.quality_report) df.to_csv(report_path, index=False) print(f"Quality report saved to {report_path}") return df # 使用示例 pipeline = SentinelPipeline() # 处理一景 S1 pipeline.run_s1_preproc( "/home/user/data/s1/S1A_IW_GRDH_1SDV_20230512T102914_20230512T102939_048422_05D1E7_5F3F.SAFE", "/home/user/data/s1_proc/S1A_20230512_sigma0.tif" ) # 处理一景 S2 pipeline.run_s2_l2a( "/home/user/data/s2_l1c/S2A_MSIL1C_20230512T030551_N0509_R075_T49QEE_20230512T050611.SAFE", "/home/user/data/s2_l2a/" ) # 生成报告 pipeline.generate_report("/home/user/data/quality_report.csv")代码逻辑说明:
run_s1_preproc不仅调用 GPT,还用rasterio读取输出 TIFF,计算有效像素占比(valid_pixel_ratio)。若低于 0.9,说明地形校正时 DEM 空洞或投影异常,该景需人工复查。run_s2_l2a重点质检SCL分类图,cloud_cover_ratio是决策关键指标。我们项目约定:cloud_cover_ratio > 0.15的景自动归入low_priority文件夹,不参与 NDVI 时序拟合。generate_report输出 CSV,字段含product,type,status,可直接导入数据库或
本文还有配套的精品资源,点击获取