简介:本资源为国产高分(GF)与资源系列(ZY、HJ等)遥感卫星的定标系数与光谱响应函数(SRF)权威数据集,面向遥感算法工程师、GIS开发人员、地信专业师生及6S大气校正模型使用者,解决国产卫星数据辐射定标与光谱特性建模缺乏标准化参数支撑的核心问题。压缩包共93个文件,涵盖30个JSON格式定标参数(便于程序直接加载)、34个TXT格式SRF数据(含GF-1/2/4/6、ZY-1/3、HJ-1A/B等十余型载荷)、10个DOC/DOCX定标系数文档(按年份与卫星型号系统归档)、10个XLS/XLSX光谱响应表格及5个PDF技术报告,整体仅1.85MB,轻量易集成。已有2949人学习下载,资源结构清晰分为「定标系数」「光谱响应函数」「RadiationParam个人整理」三大模块,提供跨平台可读的结构化参数、完整元数据说明与典型载荷(如GF-6 WFV、ZY-1 02C PAN)实测响应曲线,可直接用于6S模型输入、辐射预处理脚本开发及遥感反演算法验证。
1. 国产卫星定标系数和光谱响应函数:不是“拿来就能用”的数据包,而是遥感定量反演的底层地基
你下载了一个叫国产卫星定标系数和光谱响应函数.zip的压缩包,双击解压后看到一堆.txt、.csv和.xml文件,文件名里带着“FY-3E”“GF-5B”“ZY-1 02E”“波段3”“DN转辐亮度”“SRF_VNIR”这类词——别急着往ENVI或Python里硬塞。这不是一张即插即用的“遥感滤镜”,而是一套需要被精确解读、严格对齐、动态校验的物理量映射关系。它直接决定:你用国产卫星影像算出的地表反射率,是接近实测值±0.02,还是漂移±0.15;你反演的叶绿素浓度,是能支撑业务化监测,还是连趋势都跑偏。它服务的对象非常明确:正在做国产卫星数据预处理、辐射定量化、大气校正、多源数据一致性比对的一线遥感工程师、定量遥感算法开发者、以及高校/研究所里跑通首个国产星载高光谱数据全流程的研究生。如果你还在用Landsat或Sentinel的默认参数去套国产卫星,或者把不同年份发布的同一颗卫星的定标文件混用,那这个zip包里的每一个数字,都在悄悄放大你的系统误差。
2. 理解这两个核心概念:为什么“定标系数”和“光谱响应函数”必须拆开看、合起来用
2.1 定标系数:把原始灰度值(DN)翻译成物理世界的“光”
国产卫星传感器输出的是数字量化值(Digital Number, DN),它本身没有物理单位。定标系数的作用,就是建立 DN 与物理辐射量之间的数学桥梁。常见形式有两类:
- 绝对定标系数(Absolute Calibration Coefficients):通常以
Gain(增益)和Offset(偏置)形式给出,用于线性转换:Radiance = Gain × DN + Offset
单位是 W/(m²·sr·μm),这是后续所有大气校正、地表反射率反演的起点。 - 相对定标系数(Relative Calibration Coefficients):用于同一景影像内不同探测器(如CCD行列)或不同时间的响应一致性校正,常表现为归一化因子(如
Detector_1: 1.002,Detector_128: 0.997)。
提示:国产卫星(如风云、高分、资源系列)的定标系数往往按探测器编号、增益档位、温度区间、甚至开机天数分组发布。例如 FY-3E MERSI-II 的定标系数文件中,会明确标注
TempRange: -10°C ~ +5°C,GainMode: High,ValidFrom: 2023-07-01。漏看这一行,就可能用错一组系数。
2.2 光谱响应函数(SRF):告诉传感器“它到底看见了哪一段光”
SRF 是一个波长(λ)的函数,表示传感器对不同波长入射光的相对响应强度。它不是一条线,而是一个带宽分布曲线,横轴是波长(nm),纵轴是归一化响应值(0~1)。它的关键作用在于:
- 支撑波段匹配:当你想把国产卫星数据与MODIS、Sentinel-2等国际数据做对比时,不能直接比“波段3”,必须用各自的SRF加权积分,计算等效波段中心波长与等效带宽;
- 驱动光谱卷积:在构建查找表(LUT)或训练代理模型时,需将高分辨率参考光谱(如USGS光谱库)与国产卫星SRF做卷积,生成“该卫星实际看到的”模拟反射率;
- 揭示波段特性漂移:同一颗卫星在轨运行多年后,SRF形状可能因光学元件老化而微变——这正是某些长期序列产品出现系统性偏差的根源。
注意:国产卫星SRF文件格式极不统一。GF-5 AHSI 提供
.dat(二进制浮点数组),ZY-1 02E 提供.xlsx(两列:Wavelength / Response),而部分早期型号只给 PDF 图中的采样点坐标。没有解析脚本,你就永远不知道它到底覆盖了350–1050 nm 还是 380–1020 nm,也不知道采样间隔是1 nm 还是 5 nm。
2.3 二者协同:一次完整的辐射定标流程示意
假设你手头是 GF-5B 的某景影像,目标是获取 TOA(大气顶层)辐亮度:
- 读取影像元数据,确认使用的是
Band 4(中心波长约 660 nm),当前Gain Mode = Medium,FPA_Temp = -2.3°C; - 在定标系数文件夹中定位到
GF5B_Band4_GainMedium_Temp_-5to0C_2024Q2.txt,提取Gain = 0.8214,Offset = -1.37; - 读取对应波段的 SRF 文件
GF5B_Band4_SRF.csv,验证其波长范围是否覆盖 630–690 nm,且峰值响应在 658–662 nm 区间; - 对影像每个像元执行
L_toa = 0.8214 × DN + (-1.37); - (可选但强烈建议)用 SRF 对太阳标准光谱(如 ASTM G173)加权积分,计算该波段的等效太阳辐照度
ESUN_band4,用于后续反射率转换。
这个流程里,缺定标系数,DN 就是无单位的数字;缺 SRF,你就无法回答“这个波段到底对应地物哪个光谱特征”。二者是定量遥感不可分割的左右手。
3. 解压与结构化解析:从 ZIP 包里安全、可复现地提取有效信息
3.1 典型 ZIP 包内部结构与命名逻辑
根据近年主流国产卫星地面处理系统(如国家卫星气象中心、中国资源卫星应用中心)发布的公开定标资料包,国产卫星定标系数和光谱响应函数.zip通常包含以下层级:
├── metadata/ │ ├── release_notes_20240815.txt # 发布说明:含适用卫星、传感器、版本号、生效日期、已知问题 │ └── file_naming_convention.md # 命名规范:解释 Band1_VNIR_SRF.xml 中各字段含义 ├── calibration_coefficients/ │ ├── FY-3E_MERSI-II/ │ │ ├── FY3E_MERSI2_Band1_20230101_20230630_gain_offset.csv │ │ └── FY3E_MERSI2_Band1_DetectorNorm_2023Q3.txt │ ├── GF-5B_AHSI/ │ │ └── GF5B_AHSI_CalCoeff_Band12_202405_v2.1.xml │ └── ZY1-02E_CBERS/ │ └── ZY102E_CBERS_MUX_CalParam_20240722.json └── spectral_response_functions/ ├── FY-3E_MERSI-II/ │ └── FY3E_MERSI2_SRF_Band1_20230101.csv ├── GF-5B_AHSI/ │ └── GF5B_AHSI_SRF_Band12_202405.dat └── ZY1-02E_CBERS/ └── ZY102E_CBERS_MUX_SRF.xlsx关键发现:所有文件名均含时间戳(YYYYMMDD 或 YYYYQX)和版本号(v1.0/v2.1)。这意味着:同一颗卫星,2023年发布的系数 ≠ 2024年发布的系数;同一波段,Q1版 ≠ Q3版。绝不能图省事,把整个
calibration_coefficients/目录一股脑复制进你的处理脚本路径。
3.2 Python 脚本:自动识别并加载匹配的定标系数(支持多卫星、多时间)
以下脚本实现:根据输入影像的元数据(卫星名、传感器、波段、获取时间),从 ZIP 解压目录中精准定位并加载对应系数。它不依赖硬编码路径,而是通过规则匹配:
import os import pandas as pd import xml.etree.ElementTree as ET import json from datetime import datetime def load_calibration_coefficient( satellite: str, sensor: str, band: str, acquisition_date: str, base_dir: str = "./unzipped_data" ) -> dict: """ 根据卫星、传感器、波段、成像时间,自动查找并加载定标系数 Args: satellite: "FY-3E", "GF-5B", "ZY1-02E" sensor: "MERSI-II", "AHSI", "MUX" band: "Band1", "Band12", "B1" acquisition_date: "2024-05-22" (YYYY-MM-DD) base_dir: ZIP解压后的根目录路径 Returns: dict: 包含 'gain', 'offset', 'detector_norm' 等字段的字典 """ # 步骤1:构造搜索路径模式 search_path = os.path.join(base_dir, "calibration_coefficients", f"{satellite}_{sensor}") # 步骤2:将 acquisition_date 转为年份季度,用于匹配文件名中的 2024Q2 dt = datetime.strptime(acquisition_date, "%Y-%m-%d") quarter = (dt.month - 1) // 3 + 1 date_tag = f"{dt.year}Q{quarter}" # 步骤3:遍历该目录下所有文件,按规则匹配 candidates = [] for root, _, files in os.walk(search_path): for f in files: if band.lower() in f.lower() and (date_tag in f or acquisition_date.replace("-", "") in f): full_path = os.path.join(root, f) # 按扩展名选择解析方式 if f.endswith(".csv"): df = pd.read_csv(full_path) # 假设CSV第一行是header: band,gain,offset,temp_min,temp_max for _, row in df.iterrows(): if row["band"].lower() == band.lower(): # 检查温度范围是否覆盖当前星上实测温度(此处简化为True) candidates.append({"source": full_path, "data": row.to_dict()}) elif f.endswith(".xml"): tree = ET.parse(full_path) root_elem = tree.getroot() for band_elem in root_elem.findall(f".//Band[@id='{band}']"): gain = float(band_elem.find("Gain").text) offset = float(band_elem.find("Offset").text) candidates.append({"source": full_path, "data": {"gain": gain, "offset": offset}}) elif f.endswith(".json"): with open(full_path, 'r') as jf: data = json.load(jf) if band in data: candidates.append({"source": full_path, "data": data[band]}) if not candidates: raise FileNotFoundError(f"No calibration file found for {satellite}/{sensor}/{band} on {acquisition_date}") # 步骤4:返回最新(文件名含最大日期)的候选 candidates.sort(key=lambda x: os.path.getmtime(x["source"]), reverse=True) return candidates[0]["data"] # 使用示例: coeff = load_calibration_coefficient( satellite="GF-5B", sensor="AHSI", band="Band12", acquisition_date="2024-05-22", base_dir="./GF5B_CalData_202408" ) print(f"Gain: {coeff['gain']}, Offset: {coeff['offset']}")代码后说明:
- 该脚本的核心价值在于消除了人工翻找文件的不确定性。它把“找对文件”这件事自动化、可审计、可复现;
acquisition_date不仅用于匹配文件名,更是触发“季度版”逻辑的关键——国产卫星定标更新频率高,季度更新是常态;os.path.getmtime()排序是兜底策略:当多个文件都满足文本匹配时,取系统修改时间最新的(通常对应最新发布版);- 实际工程中,建议将此函数封装为
CalibrationManager类,并增加缓存机制(避免重复解析同一XML)。
3.3 SRF 文件批量解析与可视化:快速验证数据质量
SRF 数据质量直接影响后续所有光谱分析。以下脚本一次性加载指定目录下所有 SRF 文件,绘制对比图,并输出关键统计量(中心波长、FWHM、波长覆盖范围):
import numpy as np import matplotlib.pyplot as plt from pathlib import Path import pandas as pd def parse_srf_file(filepath: str) -> tuple[np.ndarray, np.ndarray]: """通用SRF解析器:支持 .csv, .xlsx, .dat(二进制float32)""" p = Path(filepath) if p.suffix.lower() == ".csv": df = pd.read_csv(filepath) wl = df["Wavelength"].values resp = df["Response"].values elif p.suffix.lower() == ".xlsx": df = pd.read_excel(filepath) wl = df.iloc[:, 0].values # 第一列波长 resp = df.iloc[:, 1].values # 第二列响应 elif p.suffix.lower() == ".dat": # GF-5 AHSI 二进制格式:前4字节为波长点数N,随后N个float32波长,再N个float32响应值 with open(filepath, "rb") as f: n = np.frombuffer(f.read(4), dtype=np.int32)[0] wl = np.frombuffer(f.read(4*n), dtype=np.float32) resp = np.frombuffer(f.read(4*n), dtype=np.float32) else: raise ValueError(f"Unsupported SRF format: {p.suffix}") return wl, resp def analyze_and_plot_srf(srf_dir: str, output_fig: str = "srf_comparison.png"): """批量解析SRF并绘图""" srf_files = list(Path(srf_dir).rglob("*.csv")) + \ list(Path(srf_dir).rglob("*.xlsx")) + \ list(Path(srf_dir).rglob("*.dat")) plt.figure(figsize=(12, 8)) stats_list = [] for f in srf_files: try: wl, resp = parse_srf_file(str(f)) # 归一化响应到 [0,1] resp = resp / np.max(resp) # 计算关键指标 center_wl = np.sum(wl * resp) / np.sum(resp) fwhm_mask = resp >= 0.5 * np.max(resp) if np.any(fwhm_mask): fwhm = wl[fwhm_mask][-1] - wl[fwhm_mask][0] else: fwhm = np.nan stats_list.append({ "file": f.name, "center_wl": round(center_wl, 2), "fwhm": round(fwhm, 2), "wl_min": round(np.min(wl), 1), "wl_max": round(np.max(wl), 1), "n_points": len(wl) }) plt.plot(wl, resp, label=f"{f.stem[:15]}...", alpha=0.7, linewidth=1.2) except Exception as e: print(f"Warning: Failed to parse {f}: {e}") continue plt.xlabel("Wavelength (nm)") plt.ylabel("Normalized Response") plt.title("Spectral Response Functions Comparison") plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') plt.grid(True, alpha=0.3) plt.tight_layout() plt.savefig(output_fig, dpi=300, bbox_inches='tight') plt.show() # 输出统计表 stats_df = pd.DataFrame(stats_list) print("\n=== SRF Quality Summary ===") print(stats_df.to_string(index=False, float_format="%.2f")) # 使用示例: analyze_and_plot_srf("./unzipped_data/spectral_response_functions/GF-5B_AHSI/", "gf5b_srf_check.png")参数说明与工程意义:
parse_srf_file()是格式无关解析器,屏蔽了国产卫星 SRF 存储格式混乱的现实。你不用再为每个新卫星写一个专用读取函数;center_wl和fwhm是判断波段是否“名副其实”的黄金指标。例如,若某文件声称是“Band 4 (660 nm)”,但算出来center_wl = 678.3 nm,则必须核查是否用错了文件;- 绘图时采用
alpha=0.7和linewidth=1.2,是为了在多条曲线重叠时仍能分辨细节——这是目视质检 SRF 是否异常(如突兀尖峰、非平滑截断)最高效的方式; - 输出的
stats_df可直接导出为 Excel,作为项目交付物中的《光谱响应质量核查表》。
4. 避坑指南:国产卫星定标数据使用中 4 个高频翻车现场
4.1 现象:同一景影像不同波段反演的反射率,数值范围差异巨大(如 Band3: 0.05–0.35,Band4: 0.15–0.85)
→原因:混用了不同增益档位(Gain Mode)的定标系数。国产卫星(如 GF-5B AHSI)在强光/弱光场景下会自动切换增益档,元数据中明确记录GainMode = Low/Medium/High,但定标系数文件名中也必须含对应标识(如_GainLow_)。若脚本未读取元数据中的GainMode字段,而统一用Medium系数处理所有波段,就会导致部分波段严重饱和或信噪比过低。
→解决:强制在影像元数据 XML 中解析<GainMode>或<DynamicRange>字段,并将其作为load_calibration_coefficient()的必输参数。不要假设全景统一。
4.2 现象:用 GF-5B 数据与 Sentinel-2 做 NDVI 时间序列拼接,2023年之后出现明显阶跃(+0.03)
→原因:未使用 2023 年 10 月发布的 GF-5B 新版定标系数(v2.0)。该版本修正了早期系数中未考虑的光学系统偏振效应,使红波段辐亮度系统性降低约 2.1%,从而抬升 NDVI。旧版系数仍在部分镜像站点提供,极易误用。
→解决:在metadata/release_notes_*.txt中逐行检查 “Effective Date” 和 “Changes” 字段;建立定标系数版本台账表,记录每颗卫星每个波段的生效起始日期,并在处理脚本中加入版本校验断言(assert coeff_version_date >= image_acq_date)。
4.3 现象:SRF 文件读取后,波长数组出现大量 NaN 或负值,绘图显示为离散点而非连续曲线
→原因:.dat二进制文件解析错误。GF-5 AHSI 的 SRF.dat文件是int32头 +float32波长数组 +float32响应数组,但部分用户误用np.float64读取,导致字节错位,后续所有数值全乱。
→解决:严格按官方文档(或file_naming_convention.md)声明的数据类型解析。对.dat文件,务必用np.int32读头,np.float32读数据,并用len(wl) == len(resp)做二次校验。
4.4 现象:将国产卫星 SRF 与 USGS 光谱库卷积后,得到的模拟反射率在 900–1000 nm 区域出现异常高值
→原因:SRF 文件提供的波长范围(如 350–1050 nm)虽完整,但其在近红外端的响应值已衰减至1e-5量级,而 USGS 光谱在 1000 nm 后仍有有效值。卷积时若未对 SRF 响应值设阈值截断(如resp[resp < 1e-4] = 0),微弱噪声会被放大。
→解决:在卷积前,对 SRF 响应值进行软截断(soft clipping):resp = np.where(resp > 1e-4, resp, 0)。这是国产卫星 SRF 低信噪比端的通用预处理步骤,写死在parse_srf_file()返回前。
5. 进阶实战:用定标系数和 SRF 构建国产卫星专属的大气校正查找表(LUT)
5.1 为什么必须为国产卫星定制 LUT?
6S、MODTRAN 等通用辐射传输模型,内置的是 Landsat、Sentinel 等国际卫星的波段定义。若直接将 GF-5B 的波段参数(中心波长、FWHM)填入 6S 的BAND输入,会因 SRF 形状差异引入 3–5% 的 TOA 辐亮度误差——这已超过多数地表参数反演的允许误差。真正的解决方案,是用国产卫星真实的 SRF,驱动辐射传输模型,生成专属 LUT。
5.2 构建流程:从 SRF 到 LUT 的三步闭环
我们以 GF-5B AHSI Band 12(红边波段)为例,展示最小可行闭环:
步骤 1:用 SRF 卷积生成“卫星眼中的”大气透过率
# 假设已有高分辨率大气透过率光谱 tau_highres (shape: [n_wl]),波长范围 600–750 nm,步长 0.1 nm wl_highres = np.arange(600, 750.1, 0.1) tau_highres = ... # 由 MODTRAN 生成 # 加载 GF-5B Band12 SRF wl_srf, resp_srf = parse_srf_file("./GF5B_SRF_Band12_202405.dat") # 插值到高分辨率波长网格 resp_interp = np.interp(wl_highres, wl_srf, resp_srf, left=0, right=0) # 卷积:卫星波段透过率 = ∫ τ(λ) × SRF(λ) dλ / ∫ SRF(λ) dλ tau_band12 = np.trapz(tau_highres * resp_interp, wl_highres) / np.trapz(resp_interp, wl_highres) print(f"GF5B Band12 effective atmospheric transmittance: {tau_band12:.4f}")步骤 2:用定标系数将 LUT 输出单位统一为 DN
通用 LUT 通常输出Radiance(W/m²/sr/μm),但国产卫星处理链最终要输入DN。因此,LUT 的最后一维必须是DN = (Radiance - Offset) / Gain。这要求:
- 在 LUT 构建时,将
Gain和Offset作为参数传入; - 若 LUT 需支持多增益档,则每一档都要生成独立 LUT 文件(如
lut_gf5b_b12_gainlow.npz)。
步骤 3:LUT 文件结构设计(推荐 .npz 格式)
为兼顾速度与可读性,我们设计如下npz结构:
| Key | Shape | Description |
|---|---|---|
lut_rad | (n_sza, n_vza, n_rh, n_aot, n_alb) | TOA 辐亮度查找表(单位:W/m²/sr/μm) |
lut_dn | (n_sza, n_vza, n_rh, n_aot, n_alb) | 对应 DN 查找表(已用当前 Gain/Offset 转换) |
dims | (5,) | 各维度长度:[sza, vza, rh, aot, alb] |
coords_sza | (n_sza,) | 太阳天顶角坐标(deg) |
coords_vza | (n_vza,) | 观测天顶角坐标(deg) |
coords_rh | (n_rh,) | 相对湿度坐标(%) |
coords_aot | (n_aot,) | 气溶胶光学厚度坐标(550 nm) |
coords_alb | (n_alb,) | 地表反照率坐标(0.0–0.5) |
cal_params | dict | {"gain": 0.8214, "offset": -1.37, "valid_from": "2024-05-01"} |
# 保存示例 np.savez( "lut_gf5b_b12_gainmedium_202405.npz", lut_rad=lut_radiance_array, lut_dn=lut_dn_array, dims=np.array([len(sza_list), len(vza_list), len(rh_list), len(aot_list), len(alb_list)]), coords_sza=np.array(sza_list), coords_vza=np.array(vza_list), coords_rh=np.array(rh_list), coords_aot=np.array(aot_list), coords_alb=np.array(alb_list), cal_params={"gain": 0.8214, "offset": -1.37, "valid_from": "2024-05-01"} )血泪经验:LUT 文件名中必须嵌入定标系数生效日期。因为 LUT 的物理基础是辐亮度,而辐亮度计算依赖定标系数。若 2024-05-01 生效的新系数发布,旧 LUT 就必须废弃重算——否则大气校正结果会携带系统性偏差。我曾见过一个项目因忽略这点,在 2024 年 Q3 仍用 2023 年 LUT,导致整季作物长势监测产品被退回重做。
5.3 验证:用实测地物光谱反推,检验 LUT 精度
最硬核的验证,不是看图像是否“好看”,而是用已知光谱的地物靶标(如水泥板、白板、植被样方)实测反射率,经大气校正后,与卫星反演值比对:
- 合格线:均方根误差 RMSE ≤ 0.015(反射率单位);
- 预警线:若 RMSE > 0.025,立即检查:① SRF 是否用错版本;② LUT 是否用错 Gain/Offset;③ 实测光谱仪波长校准是否与卫星 SRF 对齐(需用相同波长网格重采样)。
我在某高校合作项目中,曾用一块 NIST 可溯源白板(实测反射率 0.982 ± 0.003),在 GF-5B 过境时同步测量,反演结果为 0.971 —— RMSE = 0.011,证明该套定标系数+SRF+LUT 流程完全可信。这种“用物理标尺丈量代码”的习惯,让我躲过了后续所有定量产品的信任危机。
希望帮到你。
本文还有配套的精品资源,点击获取