Landsat系列卫星地表温度批量反演代码(大气校正法)

针对Landsat5、Landsat7、Landsat8的热红外波段反演地表温度的代码,可以批量进行温度的反演,但需要有前期的一些准备,包括大气校正参数的获取、可见光波段的大气校正等,以及文件夹的准备、文件的规范命名等。

1、大气校正法的主要过程参考文档:ENVI下Landsat8大气校正法反演地表温度
2、可见光波段参照以上文档进行大气校正(但是根据覃志豪老师的论文,可见光波段不进行大气校正也可直接用于温度反演,因此在文件命名中有所区别)
3、文件夹准备及文件命名:
在这里插入图片描述
(1)近红外波段文件夹
注意如果是Landsat8的数据,开头必须是"LC08";Landsat7对应"LE07";Landsat5对应"LT05"
如果近红外波段通过ENVI做了大气校正,则最后的命名必须是"flaash",如果没有进行大气校正,则结尾不能是"flaash"
注意:如果不做大气校正,则直接把原始图像复制过来即可,不需要用ENVI做辐射定标,代码中会进行辐射定标
在这里插入图片描述
(2)红波段文件夹
注意如果是Landsat8的数据,开头必须是"LC08";Landsat7对应"LE07";Landsat5对应"LT05"
如果红波段通过ENVI做了大气校正,则最后的命名必须是"flaash",如果没有进行大气校正,则结尾不能是"flaash"
注意:如果不做大气校正,则直接把原始图像复制过来即可,不需要用ENVI做辐射定标,代码中会进行辐射定标
在这里插入图片描述
(3)热红外波段文件夹
USGS下载的Landsat系列数据,解压后,将热红外波段直接复制过来,不需要重命名
在这里插入图片描述
(4)热红外波段大气校正参数的EXCEL文件
注意TIR这一列,需要跟热红外文件夹中热红外波段的命名一致(不需要尾缀)
在这里插入图片描述
4、具体代码

import numpy as np
from osgeo import gdal
import matplotlib.ticker as tic
import matplotlib.pyplot as plt
import imageio
import pandas as pd
import os
import copy
import datetime
# 程序开始运行时的时间
start_time = datetime.datetime.now()
# gdal库读取遥感影像数据
def image_open(img):
    data = gdal.Open(img)
    if data == 'None':
        print("图像无法读取")
    return data
FilePath = r"D:/file/novel coronavirus/Infrared remote sensing/python_temperature"
SavePath = FilePath + '/' + 'Temperature'
if not os.path.exists(SavePath):
    os.makedirs(SavePath)
# 将三个文件夹中的文件名称存入内存中,并按字符串顺序进行排序
Red_image = sorted(os.listdir(FilePath + "/" + "RED"))  # 红波段影像位置
NIR_image = sorted(os.listdir(FilePath + "/" + "NIR"))  # 近红波段影像位置
TIR_image = sorted(os.listdir(FilePath + "/" + "TIR"))  # 热红外波段影像位置
# 读取大气校正文件
# 将列的名称重命名
# 并用TIR这一列作为索引列
# excel中,TIR列为热红外波段的文件名(不含有.tif)
ATM = pd.read_excel("D:/file/novel coronavirus/Infrared remote sensing/python_temperature/ATM.xlsx",
                    names=['TIR', '大气上行辐射', '大气下行辐射', '大气透过率'], index_col='TIR')
ATM.head()
# 用来验证大气校正参数的读取
# a = ATM.at['LC08_L1TP_123039_20131120_20170428_01_T1_B10', '大气上行辐射']
# print(a)
# 判断语句来验证文件尾是不是tif文件,尽量保证每个文件夹里面除了tif文件之外没有其它文件,保证三个文件夹数据量一致
for i in range(len(TIR_image)):
    # 将红波段的影像文件名称存入第一列
    Red_for = os.path.splitext(Red_image[i])[0]
    # 文件尾缀存入第二列
    Red_end = os.path.splitext(Red_image[i])[1]
    NIR_for = os.path.splitext(NIR_image[i])[0]
    NIR_end = os.path.splitext(NIR_image[i])[1]
    TIR_for = os.path.splitext(TIR_image[i])[0]
    TIR_end = os.path.splitext(TIR_image[i])[1]
    # 获取Landsat数据名
    landsat_name = TIR_for.split('_')[0]
    # print(landsat_name)
    # 获取影像拍摄时间点,用来作为文件保存的命名
    savename = "/" + landsat_name + "_" + TIR_for.split('_')[3]
    # print(savename)
    if (Red_end.lower() == ".tif" and NIR_end.lower() == ".tif" and TIR_end.lower() == ".tif"):  # 注意影像的尾缀是大小写的问题
        RedImgPath = FilePath + "/" + "RED" + "/" + Red_image[i]
        NIRImgPath = FilePath + "/" + "NIR" + "/" + NIR_image[i]
        TIRImgPath = FilePath + "/" + "TIR" + "/" + TIR_image[i]
        # 读取数据
        # 先调用image_open函数打开影像
        # 然后用GetRasterBand()来获取波段
        # 然后用ReadAsArray()读取像素值,用此函数之前必须先获取波段
        # 可用ReadAsArray()函数设置读取像素值的数量及位置,将读取数据存放入矩阵中
        Reddata = image_open(RedImgPath)
        Redimg = Reddata.GetRasterBand(1).ReadAsArray().astype(np.float32)
        NIRdata = image_open(NIRImgPath)
        NIRimg = NIRdata.GetRasterBand(1).ReadAsArray().astype(np.float32)
        TIRdata = image_open(TIRImgPath)
        TIRimg = TIRdata.GetRasterBand(1).ReadAsArray().astype(np.float32)
        # 热红外波段辐射校正
        # landsat8有两个热红外波段,一般用第10波段,两个波段定标参数一样
        if landsat_name == 'LC08':
            # Landsat8红波段辐射定标参数
            gainRed = 0.010233
            offsetRed = -51.16713
            # Landsat8近红波段辐射定标参数
            gainNIR = 0.0062623
            offsetNIR = -31.31173
            # Landsat8热红外波段辐射定标参数
            gainTIR = 0.0003342
            offsetTIR = 0.1
            landsat8_end = TIR_for.split('_')[7]
            # Landsat8的两个热红外波段有效波长不同
            if landsat8_end == 'B10':
                # Landsat8第10波段有效波长
                lda = 10.904
            if landsat8_end == 'B11':
                # Landsat8第11波段有效波长
                lda = 12.003
        # Landsat7分为高增益与低增益波段,'1'为低增益波段,用于高温环境;'2'为高增益波段,用于常规条件
        if landsat_name == 'LE07':
            # Landsat7红波段辐射定标参数
            gainRed = 0.62165
            offsetRed = -5.62165
            # Landsat7近红波段辐射定标参数
            gainNIR = 0.63976
            offsetNIR = -5.73976
            # Landsat7热红外波段有效波长
            lda = 11.269
            # Landsat7热红外波段定标参数
            # 波段号保存在文件名称的第9个参数中
            landsat7_end = TIR_for.split('_')[-1]
            # Landsat7低增益波段辐射定标参数
            # 低增益波段适用于沙漠等温度较高的环境
            if landsat7_end == '1':
                gainTIR = 0.067087
                offsetTIR = -0.06709
            # Landsat7高增益波段辐射定标参数
            # 高增益波段适用于常规环境
            if landsat7_end == '2':
                gainTIR = 0.037205
                offsetTIR = 3.1628
        # Landsat5只有一个热红外波段
        if landsat_name == 'LT05':
            # Landsat5热红外波段有效波长
            lda = 11.457
            # Landsat5红波段辐射定标参数
            gainRed = 1.044
            offsetRed = -2.21398
            # Landsat5近红波段辐射定标参数
            gainNIR = 0.87602
            offsetNIR = -2.38602
            # Landsat5热红外波段辐射定标参数
            gainTIR = 0.055376
            offsetTIR = 1.18
        # print(gain)
        # print(offset)
        # 红波段辐射定标
        # 判断红波段是不是经过了ENVI的大气校正,因为红波段与近红外波段的处理过程应该一致,所以只用判断红波段即可
        red1 = Red_for.split('_')[-1]
        # 如果红波段与近红波段已经经过了ENVI的大气校正,则直接使用大气校正的结果作为处理的输入值,如果没有进行大气校正,则需要先用公式做辐射定标
        # 需要注意的是,ENVI大气校正处理结果的命名方式,应该以flaash结尾
        if ('flaash' in red1):
            Red_radiance = Redimg
            NIR_radiance = NIRimg
        elif not('flaash' in red1):
            Red_radiance = gainRed * Redimg + offsetRed
            # 近红波段辐射定标
            NIR_radiance = gainNIR * NIRimg + offsetNIR

        # 热红外波段辐射定标
        TIR_radiance = gainTIR * TIRimg + offsetTIR
        # 计算NDVI值
        # 忽略分母为0的情况
        np.seterr(divide='ignore', invalid='ignore')
        NDVI = (NIR_radiance - Red_radiance) / (NIR_radiance + Red_radiance)
        NDVI = NDVI.astype(np.float32)
        # 计算FVC值
        # 利用NDVI值来判断FVC值的计算方式
        # NDVI值大于0.7时认为是纯植被像元
        # NDVI值小于0.05时判断为裸土像元
        # NDVI值在0.05与0.7之间时判断为城市地表像元
        # 需要用深拷贝,不然会改变原来的数组内容
        FVC = copy.deepcopy(NDVI)
        FVC = (FVC - 0.05) / (0.7 - 0.05)
        FVC[NDVI > 0.7] = 1
        FVC[NDVI < 0.05] = 0
        # 计算地表比辐射率
        emissivity = copy.deepcopy(NDVI)
        # 注意在等号后面的式子中也加上条件,不然会出现维度问题
        # 同样用NDVI值进行判断
        # NDVI值大于等于0.7时为纯植被
        # NDVI值小于等于0时为水体
        # NDVI值在0到0.7之间时为城市地表
        emissivity[NDVI >= 0.7] = 0.9625 + 0.0614 * FVC[NDVI >= 0.7] - 0.0461 * (FVC[NDVI >= 0.7]) ** 2
        emissivity[NDVI < 0.7] = 0.9589 + 0.086 * FVC[NDVI < 0.7] - 0.0671 * (FVC[NDVI < 0.7]) ** 2
        emissivity[NDVI <= 0] = 0.995
        # 温度反演
        # 先做大气校正,从ATM表中提取出相应的参数,计算得到地表亮度温度
        up = ATM.at[TIR_for, '大气上行辐射']
        down = ATM.at[TIR_for, '大气下行辐射']
        trans = ATM.at[TIR_for, '大气透过率']
        # 计算出地表亮度温度
        BT = (TIR_radiance - up - trans * (1 - emissivity) * down) / (emissivity * trans)
        # 求出地表温度,并将单位转化为摄氏度
        Temperature = 14387.7 / (lda * np.log(119104000 / (BT * (lda ** 5)) + 1)) - 273.15
        Temperature = Temperature.astype(np.float32)
        # 输出数据
        gtiff_driver = gdal.GetDriverByName("GTiff")
        out_ds = gtiff_driver.Create(SavePath + savename + "T.tif",
                                     Temperature.shape[1], Temperature.shape[0], 1, gdal.GDT_Float32)
        # 设置输出数据坐标投影为原始影像的坐标投影
        out_ds.SetProjection(TIRdata.GetProjection())
        out_ds.SetGeoTransform(TIRdata.GetGeoTransform())
        out_band = out_ds.GetRasterBand(1)
        out_band.WriteArray(Temperature)
        out_band.FlushCache()
        # 输出比辐射率
        # emissivity_driver = gdal.GetDriverByName("GTiff")
        # out_e = emissivity_driver.Create(SavePath + savename + "E.tif",
        #                              emissivity.shape[1], emissivity.shape[0], 1, gdal.GDT_Float32)
        # out_e.SetProjection(TIRdata.GetProjection())
        # out_e.SetGeoTransform(TIRdata.GetGeoTransform())
        # out_band_e = out_e.GetRasterBand(1)
        # out_band_e.WriteArray(emissivity)
        # out_band_e.FlushCache()
        # 输出辐射亮度图
        # BT_driver = gdal.GetDriverByName("GTiff")
        # out_BT = BT_driver.Create(SavePath + savename + "BT.tif",
        #                              BT.shape[1], BT.shape[0], 1, gdal.GDT_Float32)
        # out_BT.SetProjection(TIRdata.GetProjection())
        # out_BT.SetGeoTransform(TIRdata.GetGeoTransform())
        # out_band_BT = out_BT.GetRasterBand(1)
        # out_band_BT.WriteArray(BT)
        # out_band_BT.FlushCache()
        # 处理完一张后显示
        print('Temperature Retrieval: {}, {}'.format(i+1, landsat_name + "_" + TIR_for.split('_')[3]))
# 程序结束运行时的时间
end_time = datetime.datetime.now()
# # 计算温度反演所用的时间运行的时间
# print('Temperature Retrieval Time: {}'.format(end_time - start_time))
  • 23
    点赞
  • 119
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
### 回答1: 基于大气校正Landsat 8 TIRS(地球资源卫星8号热红外传感器)可以用于反演地表温度。该方主要是通过消除大气扰动,得到准确的地表温度值。 首先,大气校正的基本原理是根据大气辐射传输模型,将测量的卫星辐射值和经验参数输入,计算出大气辐射和散射的影响。然后,根据传感器观测值和实际观测情况之间的比较,进行反演校正操作,得到准确的地表温度。 具体地,Landsat 8 TIRS传感器可以获取大气顶部和地表辐射值。首先,需要将大气辐射值从总辐射中分离出来,得到地表辐射值。然后,使用大气透过率和大气温度等参数,根据大气辐射传输模型计算出大气辐射的影响。最后,通过与地理标准物体的比较,利用反射率和辐亮度温标进行校正,最后得到准确的地表温度。 需要注意的是,大气校正地表温度反演过程中需要准确的大气参数和标定物体的反射率,这会影响准确性。同时,地表的特殊情况(如云、水体、植被覆盖等)也会造成一定的误差。因此,在实际应用中,需要结合其他观测数据和先验知识综合分析,以提高地表温度反演结果的可靠性和准确性。 总之,基于大气校正Landsat 8 TIRS可以反演地表温度,通过消除大气扰动,得到高质量的地表温度数据,可广泛应用于地表热环境、城市规划、农业监测等领域。 ### 回答2: 基于大气校正Landsat 8 TIRS(Thermal Infrared Sensor)反演地表温度是通过对遥感数据进行处理和校正,消除大气和其他干扰因素的影响,得到反映真实地表温度的结果。这种方是通过利用Landsat 8 TIRS传感器测量的地表辐射温度(LST)和大气温度、湿度、气溶胶等参数之间的关系,建立数学模型,从而实现地表温度反演。 首先,利用TIRS传感器获取的原始地表辐射温度数据,根据辐射定律进行辐射校准,将原始数据转换为辐射亮度温度(Lλ)。然后,借助大气透过率模型,将Lλ转换为地表亮度温度(LST)。 接下来,通过大气校正校正LST,其中主要考虑的是大气遥感和大气参数。大气遥感是通过红外窗口的多波段数据推导大气廓线,包括大气温度、湿度等参数。通过将大气廓线输入辐射传输模型,可以计算出大气响应函数。然后,将大气响应函数应用于LST数据,消除大气的影响,得到最终的地表温度。 在进行大气校正时,还需要考虑其他干扰因素,如云、阴影和气溶胶的影响。通过使用云、阴影检测算和气溶胶模型,可以在大气校正的过程中对这些干扰因素进行修正,进一步提高反演地表温度的精度。 总之,基于大气校正Landsat 8 TIRS反演地表温度是一种通过校正和消除大气和其他干扰因素的影响,利用TIRS传感器数据和大气参数模型,推导出反映真实地表温度的结果的方。它在研究气候变化、土地利用监测等领域具有重要的应用价值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值