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.

相关文章
|
1月前
|
Python
【10月更文挑战第10天】「Mac上学Python 19」小学奥数篇5 - 圆和矩形的面积计算
本篇将通过 Python 和 Cangjie 双语解决简单的几何问题:计算圆的面积和矩形的面积。通过这道题,学生将掌握如何使用公式解决几何问题,并学会用编程实现数学公式。
160 60
|
1月前
|
Python
Datetime模块应用:Python计算上周周几对应的日期
Datetime模块应用:Python计算上周周几对应的日期
|
17天前
|
机器学习/深度学习 算法 编译器
Python程序到计算图一键转化,详解清华开源深度学习编译器MagPy
【10月更文挑战第26天】MagPy是一款由清华大学研发的开源深度学习编译器,可将Python程序一键转化为计算图,简化模型构建和优化过程。它支持多种深度学习框架,具备自动化、灵活性、优化性能好和易于扩展等特点,适用于模型构建、迁移、部署及教学研究。尽管MagPy具有诸多优势,但在算子支持、优化策略等方面仍面临挑战。
44 3
|
29天前
|
Python
【10月更文挑战第15天】「Mac上学Python 26」小学奥数篇12 - 图形变换与坐标计算
本篇将通过 Python 和 Cangjie 双语实现图形变换与坐标计算。这个题目帮助学生理解平面几何中的旋转、平移和对称变换,并学会用编程实现坐标变化。
64 1
|
1月前
|
机器学习/深度学习 移动开发 Python
【10月更文挑战第11天】「Mac上学Python 22」小学奥数篇8 - 排列组合计算
本篇将通过 Python 和 Cangjie 双语讲解如何计算排列与组合。这道题目旨在让学生学会使用排列组合公式解决实际问题,并加深对数学知识和编程逻辑的理解。
61 4
|
1月前
|
数据可视化 Python
【10月更文挑战第12天】「Mac上学Python 23」小学奥数篇9 - 基础概率计算
本篇将通过 Python 和 Cangjie 双语实现基础概率的计算,帮助学生学习如何解决简单的概率问题,并培养逻辑推理和编程思维。
48 1
|
1月前
|
存储 自然语言处理 数据处理
使用Python计算多个集合的交集详解
使用Python计算多个集合的交集详解
38 1
|
1月前
|
Python
使用python计算两个日期之前的相差天数,周数
使用python计算两个日期之前的相差天数,周数
35 0
|
1月前
|
索引 Python
Excel学习笔记(一):python读写excel,并完成计算平均成绩、成绩等级划分、每个同学分数大于70的次数、找最优成绩
这篇文章是关于如何使用Python读取Excel文件中的学生成绩数据,并进行计算平均成绩、成绩等级划分、统计分数大于70的次数以及找出最优成绩等操作的教程。
60 0
|
1月前
|
机器学习/深度学习 算法 数据挖掘
Python 中的计算与应用
Python 中的计算与应用