Python计算温度植被干旱指数(TVDI)

简介: Python计算温度植被干旱指数(TVDI)

温度植被干旱指数TVDI(Temperature Vegetation Dryness Index)是一种基于光学与热红外遥感通道数据进行植被覆盖区域表层土壤水分反演的方法。


1、原理

LST-NDVI特征空间1

微信截图_20230111082342.png


温度植被干旱指数(TVDI)的计算方法为:

TVDI= LST max  −LST min  LST−LST min  

LSTmin=a+b×NDVI

LSTmax=c+d×NDVI

其中

a 、 b 、 c 、 d

为干、湿边拟合系数;


2、Python代码

import gdal
from gdalconst import *
import numpy as np
from glob import glob
from os import path as osp
import os, subprocess
import matplotlib.pyplot as plt
# 获取lst、ndvi数据
def get_data(file_ndvi,file_lst):
    ndvi_tif=gdal.Open(file_ndvi,GA_ReadOnly)
    lst_tif=gdal.Open(file_lst,GA_ReadOnly)
    ndvi_band=ndvi_tif.GetRasterBand(1)
    ndvi=ndvi_band.ReadAsArray()
    lst_band=lst_tif.GetRasterBand(1)
    lst=lst_band.ReadAsArray()    
    return ndvi,lst
# 获取投影等信息,用于保存TVDI结果
def get_info(file_ndvi):
    ndvi_tif=gdal.Open(file_ndvi,GA_ReadOnly)
    ndvi_band=ndvi_tif.GetRasterBand(1)
    gt = ndvi_tif.GetGeoTransform()
    proj = ndvi_tif.GetProjectionRef()
    dtype = ndvi_band.DataType
    return gt,proj,dtype
# 计算lst的最小值(湿边)和最大值(干边)
def get_min_max(ndvi,lst):
    MiniList = []
    MaxList = []
    # 创建ndvi向量(0到1,间距为0.01)
    ndvi_vector = np.round(np.arange(0.01, 1.01, 0.01), 2)
    # 首先找到相同ndvi的lst值
    for val in ndvi_vector:
        lst_lst_val = []
        row, col = np.where((ndvi >= val-0.001) & (ndvi <= val+0.001))
        # 根据这些ndvi的位置,我们取温度值对应这些位置(行和列)
        for i in range(len(row)):
            if np.isfinite(lst[row[i], col[i]]):
                lst_lst_val += [lst[row[i], col[i]]]
            # 如果所需的ndvi有lst值,则计算最大值和最小值
        if lst_lst_val != []:
            lst_min_val = np.min(lst_lst_val)
            lst_max_val = np.max(lst_lst_val)
        else:
            lst_min_val = np.nan
            lst_max_val = np.nan
        # 找到的值被添加到MiniList和MaxList列表中
        MiniList += [lst_min_val]
        MaxList  += [lst_max_val]
    return MiniList,MaxList
def fit(MiniList,MaxList):
    ndvi_vector = np.round(np.arange(0.01, 1.01, 0.01), 2)
    MiniList_fin = []
    ndvi_fin = []
    for i, val in enumerate(MiniList):
        if np.isfinite(val):
            MiniList_fin += [val]
            ndvi_fin += [ndvi_vector[i]]
    MinPfit = np.polyfit(ndvi_fin[14:89], MiniList_fin[14:89], 1)
    MaxList_fin = []
    ndvi_fin = []
    for i, val in enumerate(MaxList):
        if np.isfinite(val):
            MaxList_fin += [val]
            ndvi_fin += [ndvi_vector[i]]
    MaxPfit = np.polyfit(ndvi_fin[14:89], MaxList_fin[14:89], 1)
    return MinPfit,MaxPfit
def plot_scatter(ndvi,lst,MiniList,MaxList,MinPfit,MaxPfit,scatter_file=None):
    ndvi_vector = np.round(np.arange(0.01, 1.01, 0.01), 2)
    a1, b1 = MaxPfit
    a2, b2 = MinPfit
    linhamax = [b1 + (a1 * 0), b1 + (a1 * 1)]
    linhamin = [b2 + (a2 * 0), b2 + (a2 * 1)]
    plt.plot(ndvi.ravel(), lst.ravel(), "+", color='dimgray', markersize=4)
    plt.plot(ndvi_vector[14:89], MiniList[14:89], '+', color='b')
    plt.plot(ndvi_vector[14:89], MaxList[14:89], '+', color='r')
    if a1>0:
        plt.plot([0, 1], linhamax, color='r', markersize=8,\
                         label=f"Tsmax = {'%.1f'% b1} + {'%.1f' % abs(a1)} * ndvi")
    else:
        plt.plot([0, 1], linhamax, color='r', markersize=8,\
                         label=f"Tsmax = {'%.1f'% b1} - {'%.1f' % abs(a1)} * ndvi")
    if a2>0:
        plt.plot([0, 1], linhamin, color='b', markersize=8,\
                         label=f"Tsmin = {'%.1f' % b2} + {'%.1f' % abs(a2)} * ndvi")
    else:
        plt.plot([0, 1], linhamin, color='b', markersize=8,\
                         label=f"Tsmin = {'%.1f' % b2} - {'%.1f' % abs(a2)} * ndvi")
    plt.legend(loc='upper right', fontsize=12)
    plt.ylim(top=340,bottom=270)
    plt.xlabel("ndvi")
    plt.ylabel("lst (K)")
    plt.title("ndvi vs lst Scatterplot")
    if scatter_file is not None:
        plt.savefig(scatter_file)
    plt.show()
def show_tvdi(tvdi,fig_file=None):
    plt.imshow(tvdi,cmap= 'jet_r',vmax=1,vmin = 0)
    plt.axis('off')
    plt.colorbar()
    plt.title("tvdi")
    if fig_file is not None:
        plt.savefig(fig_file)
    plt.show()
def compute_tvdi(ndvi,lst,MinPfit,MaxPfit):
    a1, b1 = MaxPfit
    a2, b2 = MinPfit
    Ts_max = b1 + (a1 * ndvi)
    Ts_min = b2 + (a2 * ndvi)
    TVDI = (lst - Ts_min) / (Ts_max - Ts_min)
    return TVDI
def save_tvdi(TVDI,gt,proj,dtype,file_out):
    fname_out   = file_out
    driver      = gdal.GetDriverByName('GTiff')
    data_type   = dtype
    dset_output = driver.Create(fname_out, TVDI.shape[1], TVDI.shape[0], 1, gdal.GDT_Float32)
    dset_output.SetGeoTransform(gt)
    dset_output.SetProjection(proj)
    dset_output.GetRasterBand(1).WriteArray(TVDI)
    dset_output.FlushCache()
    dset_output = None
def main(ndvi_file,lst_file,tvdi_file,scatter_file=None,fig_file=None):
    '''
    Parameters
    ----------
    ndvi_file : the file of ndvi
    lst_file : the file of lst
    tvdi_file : the file use to save tvdi
    scatter_file : the file use to save scatter
    fig_file : the file use to save the figure of tvdi
    '''
    # 获取ndvi和lst数据
    ndvi,lst=get_data(ndvi_file,lst_file)
    ndvi[ndvi<0]=np.nan
    lst[lst<250]=np.nan
    # 获取lst的最小值(湿边)和最大值(干边)
    MiniList,MaxList=get_min_max(ndvi,lst)
    # 计算tvdi,并保存
    MinPfit,MaxPfit=fit(MiniList,MaxList)
    tvdi=compute_tvdi(ndvi,lst,MinPfit,MaxPfit)
    gt,proj,dtype=get_info(ndvi_file)
    save_tvdi(tvdi,gt,proj,dtype,tvdi_file)
    # 显示散点图
    plot_scatter(ndvi,lst,MiniList,MaxList,MinPfit,MaxPfit,scatter_file)
    # 展示tvdi结果
    show_tvdi(tvdi,fig_file)
if __name__ == '__main__':
    ndvi_file=r'*.tif'
    lst_file=r'*.tif'
    tvdi_file=r'*.tif'
    main(ndvi_file,lst_file,tvdi_file)


3、结果展示

LST-NDVI的散点图:

微信截图_20230111082354.png


TVDI展示:

微信截图_20230111082403.png

如果对您有用的话,别忘了给点个赞哦_ !


4、参考文献

[1] Du L, Song N, Liu K, et al. Comparison of Two Simulation Methods of the Temperature Vegetation Dryness Index (TVDI) for Drought Monitoring in Semi-Arid Regions of China[J]. Remote Sensing, 2017, 9(2): 177.

相关文章
|
18天前
|
数据挖掘 Python
【视频】随机波动率SV模型原理和Python对标普SP500股票指数预测|数据分享
【视频】随机波动率SV模型原理和Python对标普SP500股票指数预测|数据分享
|
13天前
|
算法 程序员 Python
年底工资总结,实例教你用Python计算个税 依法纳税做好公民(1)
年底工资总结,实例教你用Python计算个税 依法纳税做好公民(1)
|
16天前
|
数据采集 数据挖掘 关系型数据库
Excel计算函数(计算机二级)(1),2024年最新2024Python架构面试指南
Excel计算函数(计算机二级)(1),2024年最新2024Python架构面试指南
|
16天前
|
Python
【Python 百练成钢】高精度加法、阶乘计算、矩阵幂运算、矩阵面积交
【Python 百练成钢】高精度加法、阶乘计算、矩阵幂运算、矩阵面积交
|
16天前
|
存储 算法 Python
【Python 百练成钢】高精度加法、阶乘计算、矩阵幂运算、矩阵面积交(2)
【Python 百练成钢】高精度加法、阶乘计算、矩阵幂运算、矩阵面积交(2)
|
16天前
|
存储 算法 Python
【Python 百练成钢】高精度加法、阶乘计算、矩阵幂运算、矩阵面积交(1)
【Python 百练成钢】高精度加法、阶乘计算、矩阵幂运算、矩阵面积交(1)
|
18天前
|
Python
python计算线段角度
python计算线段角度
12 0
|
18天前
|
安全 数据安全/隐私保护 Python
Python的整型在计算中具有以下优势
【5月更文挑战第6天】Python整型提供任意精度整数计算,无溢出风险;支持多种算术运算,操作简便;作为不可变类型保证数据安全;能进行高级数学运算,并有NumPy等库加持,适合数值分析和科学计算。
24 0
|
18天前
|
Python
Python的整型在计算中的精度可以通过使用二进制或十进制表示来体现
【5月更文挑战第6天】Python整型支持十、二、八、十六进制表示,其中十进制默认,二进制(0b前缀)、八进制(0o前缀)、十六进制(0x前缀)。计算时以二进制精度处理,确保结果准确。例如:123的二进制是0b1111011,八进制是0o173,十六进制是0x7b。
19 0
|
18天前
|
资源调度 数据可视化 Python
Python随机波动模型Stochastic volatility,SV随机变分推断SVI分析标普500指数时间数据波动性可视化
Python随机波动模型Stochastic volatility,SV随机变分推断SVI分析标普500指数时间数据波动性可视化