栅格的二元回归

30 篇文章 20 订阅
该博客介绍了如何使用Python的numpy和sklearn库进行二元线性回归分析,特别是在处理栅格数据时的应用。通过实例展示了如何计算植被覆盖度、气温和降水之间的回归系数,以及如何构建模型预测植被覆盖度,并通过残差分析来量化人类活动对植被的影响。最后提供了完整的Python代码示例。
摘要由CSDN通过智能技术生成

有时候我们会用到残差趋势法,例如以植被覆盖度为因变量 、以气温和降水为自变量,逐像元建立二元线性回归模型 ,逐像元得到回归方程的系数;其次,利用气温和降水数据以及回归模型的系数,建立模型模拟得到气候影响下的植被覆盖度的预测值;最后,基于遥感影像获得的植被覆盖度观测值与基于回归模型模拟得到气候影响下的预测值做差值计算,得到的结果即为植被覆盖度残差,表示了人类活动对植被覆盖的影响。今天分享一下栅格的二元回归系数计算方法。

1 二元回归系数计算

二元回归系数系数的计算公式网上书上有计算公式,这里不再赘述。这里介绍一下Python的numpy库计算相关系数,使用sklearn.linear_model.LinearRegression类,示例如下。 下面的示例中,首先构造一个x1和x2数组,每个数组有6个元素,其次构造y = a·x1 + b·x2 + c。其中a = 3.14,b = 2.78, c = 1.27,使用LinearRegression来反演a b c,与给定的的系数abc是一致的,验证了LinearRegression进行二元回归的可行性。

import numpy as np
import sklearn
from sklearn.linear_model import LinearRegression

x1 = np.array([1,2,3,4,5,6])
x2 = np.array([3,2,1,3,3,2])

# 让a = 3.14, b = 2.78, c = 1.27构造一个y

y = 3.14 * x1 + 2.78 * x2 + 1.27 
x = np.vstack([x1, x2]).T
regr = sklearn.linear_model.LinearRegression()
regr.fit(x, y)
a, b = regr.coef_
c = regr.intercept_
print(a,b,c)
# 3.1399999999999997 2.78 1.2699999999999996

2 计算栅格的二元回归

2.1 数据准备

以植被覆盖度、降水和温度的计算为例,首先准备植被覆盖度、气温和降水数据,例如10个月的植被覆盖度、10个月的气温和10个月的降水。回归计算需要多个数据,只用一期的影像无法计算。

待计算的数据需要有相同的行列数和相同的期数。
通常植被覆盖度、降水、温度的数据是单波段的,首先需要将单波段的影像按照相同的时间顺序合并成一个多波段的,例如一个月一个波段或一年一个波段,具体看使用的数据。这个可以使用envi的layer stacking来实现,也可以使用下面的代码实现。在这里的示例中,3月份为第1波段,4月份为第2波段。。12月份为第10波段。 气温和降水分别做成这样的数据。

from osgeo import gdal
import os
"""
多个单波段tif合并成一个tif文件
"""
#修改路径
tifDir = r"E:\data\一元回归\降水"  #tif路径 单波段
outtif = r"E:\data\一元回归\降水.tif"

NP2GDAL_CONVERSION = {
  "uint8": 1,
  "int8": 1,
  "uint16": 2,
  "int16": 3,
  "uint32": 4,
  "int32": 5,
  "float32": 6,
  "float64": 7,
  "complex64": 10,
  "complex128": 11,
}
tifs = [i for i in os.listdir(tifDir) if i.endswith(".tif")]
#获取投影波段数等信息
bandsNum = len(tifs)
dataset = gdal.Open(os.path.join(tifDir,tifs[0]))
projinfo = dataset.GetProjection()
geotransform = dataset.GetGeoTransform()
cols,rows=dataset.RasterXSize,dataset.RasterYSize
datatype=dataset.GetRasterBand(1).ReadAsArray(0,0,1,1).dtype.name
gdaltype=NP2GDAL_CONVERSION[datatype]
dataset=None
#创建目标文件
format = "GTiff" #tif格式
#format = "ENVI"  # ENVI格式
driver = gdal.GetDriverByName(format)
dst_ds = driver.Create(outtif,cols, rows,bandsNum, gdaltype,options=['COMPRESS=LZW'])
dst_ds.SetGeoTransform(geotransform)
dst_ds.SetProjection(projinfo)
#写入文件
info = set()
for k in range(bandsNum):
    ds = gdal.Open(os.path.join(tifDir,tifs[k]))
    X,Y = ds.RasterXSize,ds.RasterYSize
    info.add("%s,%s"%(X,Y))
    if(len(info) != 1):
        dst_ds = None
        ds = None
        print("%s 列数行数不一样:%s,%s"%(tifs[k],X,Y))
        raise Exception("有影像行列数不一致")
    data = ds.GetRasterBand(1).ReadAsArray()    ##读取第一波段
    ds = None
    dst_ds.GetRasterBand(k+1).WriteArray(data)
    dst_ds.GetRasterBand(k+1).SetDescription("hahha_%s"%k)
    print("波段 %s ==> 文件 %s"%(k+1,tifs[k]))
dst_ds = None

enter description here

2.2 计算

数据准备好后就可以使用Python写代码来计算了。需要使用numpy、gdal、sklearn等库来操作。代码在下面贴出,注释十分的丰富,很利于理解。只需要在最后的main函数中修改输入输出路径即可。结果tif有3个波段,分别是temp系数a、rain的系数b和常数项c。

import numpy as np
from osgeo import gdal
import os
import sklearn
from sklearn.linear_model import LinearRegression
from tqdm import tqdm


def regression(X, Y):
    '''
    X为n行2列的numpy数组,n为年份数,第一列为气温,第二列为降水
    Y为目标:n个元素的numpy数组,为fvc
    '''
    regr = sklearn.linear_model.LinearRegression()
    regr.fit(X, Y)
    a, b = regr.coef_
    c = regr.intercept_
    return a, b, c


def erhuigui(fvcpath, temppath, rainpath, outtif):
    dataset = gdal.Open(fvcpath)
    projinfo = dataset.GetProjection()
    geotransform = dataset.GetGeoTransform()

    format = "GTiff"
    driver = gdal.GetDriverByName(format)
    depth = dataset.RasterCount
    rows = int(dataset.RasterYSize)
    colmns = int(dataset.RasterXSize)

    fvc = dataset.ReadAsArray()
    src2 = gdal.Open(temppath)
    temp = src2.ReadAsArray()

    src3 = gdal.Open(rainpath)

    rain = src3.ReadAsArray()

    dst_ds1 = driver.Create(outtif, colmns, rows, 3,
                            gdal.GDT_Float32)
    dst_ds1.SetGeoTransform(geotransform)
    dst_ds1.SetProjection(projinfo)
    d0 = fvc[0]
    outA = d0 * 0 - 2222.0
    outB = d0 * 0 - 2222.0
    outC = d0 * 0 - 2222.0
    # 开始计算
    for row in tqdm(range(rows)):
        for col in range(colmns):
            if d0[row, col] != 0:
                y = fvc[:, row, col] * 1.0
                x1 = temp[:, row, col] * 1.0
                x2 = rain[:, row, col] * 1.0
                x = np.vstack([x1, x2]).T
                a, b, c = -2222, -2222, -2222
                try:
                    a, b, c = regression(x, y)
                except:
                    pass
                outA[row, col], outB[row, col], outC[row, col] = a, b, c
    print("a---------------")
    dst_ds1.GetRasterBand(1).WriteArray(outA)
    dst_ds1.GetRasterBand(2).WriteArray(outB)
    dst_ds1.GetRasterBand(3).WriteArray(outC)
	dst_ds1.GetRasterBand(1).SetNoDataValue(-2222)
    dst_ds1.GetRasterBand(2).SetNoDataValue(-2222)
    dst_ds1.GetRasterBand(3).SetNoDataValue(-2222)
    dst_ds1 = None


if __name__ == "__main__":
    # 修改路径
    fvcpath = r"R01.tif"  #植被覆盖度路径
    temppath = r"R02.tif"  #气温路径
    rainpath = r"R03.tif"  #降水路径
    outtif = r"out.tif"
    erhuigui(fvcpath, temppath, rainpath, outtif)

enter description here

2.3 结果示例

enter description here
enter description here

3 结束语

好朋友们,以上就是今天分享的全部内容了,如有疑问和错误欢迎批评指正。
公众号

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独孤尚亮dugushangliang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值