写在前面:找到了失效后官网更新的链接,现附上:
https://www.cresda.com/zgzywxyyzx/zlxz/article/20240416163618563132683.html
在使用Py6S对TOA影像进行逐波段大气校正时,需要设置传感器的光谱响应函数,哨兵系列、陆地卫星系列都有预定义参数,但是高分系列没有,因此需要自己写一个config文档。
本文参考资料:
https://py6s.readthedocs.io/en/latest/_modules/Py6S/Params/wavelength.html
http://zhihu.geoscene.cn/article/2378
https://blog.csdn.net/qq_40365996/article/details/135627211
https://zhuanlan.zhihu.com/p/364889134
#使用预定义光谱响应函数的波段设置
s.wavelength = spectralResponseFunction(PredefinedWavelengths.LANDSAT_OLI_B1) #这里以Landsat-8 band 1为例
s.run()
为了自定义可用于6S校正的GF-6 SRF,由于没有找到现成的资料,前人文章里提供的链接都失效了,所以这里用到ENVI自带的.sli波谱库文件。
在ENVI中提供了大部分卫星的波谱响应函数,以ENVI5.3为例,存放在:…\Exelis\ENVI53\resource\filterfuncs中。
但是ENVI提供的SRF是内置光谱格式的,我们要用python实现6S大气校正,那就需要得到提取出来的.txt文件作为校正的输入,因此这里接着用ENVI导出文本形式的光谱响应函数。
在ENVI中打开 Spectral Resampling Input File, 选择需要用到的.sli文件,我这里用PMS的MSS传感器,选择对应的就行。
在resampling parameter界面选择input ASCII File, 在下面的路径中给要输出的文件起好名字,点OK。
注意在这里会跳出Enter Containing Output Wavelength界面,让你选择定义输出波长的文件,即自定义的.CSV文件,我是自己根据GF-6的四波段范围,以2.5 nm为间隔制作的,分别制作四个csv文件(四个波段),类似这样(以B1为例):
选择这个文件,跳出窗口
在Wavelength units自己选择好输入的波长文件单位(micrometer),就可以正式输出重采样结果了。
这是原始的内置四波段光谱响应函数(.sli)文件画出来的样子:
这是重采样后的光谱响应函数画出来的样子(以B2为例):
点Export-ASCII导出,得到.txt文件,以同样的流程,分别生成B1-B4的文本文件,最后因为我们是需要在Py6S中作为config来导入使用,因此再手动整理到写有辐射校正所需gains和bias、大气校正所需SRF的config文本文档中。
这里的config文件格式参考了这份代码中的RadiometricCorrectionParameter.json ,源代码只有高分一和高分二的,这里手动添加高分六号的参数,就可以根据代码中的命令导入python进行6S大气校正了。
config_file = os.path.join('D:/GFdata/GF6/RadiometricCorrectionParameter.json')
config = json.load(open(config_file))
# 校正波段(根据波段名称)
if BandId == 1:
SRFband = config["Parameter"]["GF6"]["PMS"]["SRF"]["1"]
s.wavelength = Wavelength(0.450,0.520,SRFband)
elif BandId == 2:
SRFband = config["Parameter"]["GF6"]["PMS"]["SRF"]["2"]
s.wavelength = Wavelength(0.520,0.590,SRFband)
elif BandId == 3:
SRFband = config["Parameter"]["GF6"]["PMS"]["SRF"]["3"]
s.wavelength = Wavelength(0.630,0.690,SRFband)
elif BandId == 4:
SRFband = config["Parameter"]["GF6"]["PMS"]["SRF"]["4"]
s.wavelength = Wavelength(0.770,0.890,SRFband)
# 运行模型
s.run()