GDAL(Geospatial Data Abstraction Library)是一个在X/MIT许可协议下的开源栅格空间数据转换库。它利用抽象数据模型来表达所支持的各种文件格式。它还有一系列命令行工具来进行数据转换和处理。

        Python的GDAL库作为栅格数据的处理转换库,其支持几百种栅格数据格式,如常见的TIFF、ENVI、HFA、HDF4等。因为遥感影像大部分都是栅格数据,所以GDAL库非常适合处理遥感影像、如光谱指数计算、波段合成、批量下载等。

一、GDAL库的安装

  因为博主的GDAL库的安装有些时候了,所以pip install 的方法能不能安装需要自己尝试。这里推荐大家下载对应包,使用本地安装。

1.打开GDAL库的下载链接,选择自己电脑Python对应的版本,别下载错了哦!

2.然后按住Win+R,输入cmd进入命令行。在cmd终端中,使用cd跳转至下载GDAL包的目录。如 cd /d G:\try\,G:\try\是你狭窄GDAL包的文件夹目录。然后在命令行里输入pip GDAL-3.4.3-cp38-cp38-win_amd64.whl,这是你下载的GDAL包的名称,每个人不一样,别傻乎乎地用我的!

 3.可以在编译器里查看是否安装成功,博主使用的是PyCharm,在设置中可以看到是否安装成功。当然你也可以先编写程序,如果没安装成功,程序会报错=。=

 

二、编写程序

1.导入计算所需库

numpy是数组处理的库,GDAL是我们安装的栅格数据处理库。遥感影像本质上是多维数组,如果这都不知道,建议先百度。

import numpy as np
from osgeo import gdal

2.查看栅格数据信息,如宽度、高度、波段数、投影等

当然这一步和我们的光谱指数计算没有太大的关系,但后续计算时需要这里面的相关参数,所以大家可以先了解一下。

ds = gdal.Open(filepath)  # 打开数据集dataset
ds_width = ds.RasterXSize # 获取数据宽度
ds_height = ds.RasterYSize # 获取数据高度
ds_bands = ds.RasterCount # 获取波段数
ds_geo = ds.GetGeoTransform() # 获取仿射地理变换参数
ds_prj = ds.GetProjection() # 获取投影信息
print("影像的宽度为:" + str(ds_width))
print("影像的高度为:" + str(ds_height))
print("仿射地理变换参数为:" + str(ds_geo))
print("投影坐标系为:" + str(ds_prj))

3.以数组的形式打开红波段、近红外波段

每种卫星对应的红波段和近红外波段都不一样、博主这里red是3,nir是4。

ds = gdal.Open(filepath)  # 打开数据集dataset
ds_width = ds.RasterXSize # 获取数据宽度
ds_height = ds.RasterYSize # 获取数据高度
ds_geo = ds.GetGeoTransform() # 获取仿射地理变换参数
ds_prj = ds.GetProjection() # 获取投影信息
array_red = ds.GetRasterBand(red).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float)
# red是红波段对应的波段数
array_nir = ds.GetRasterBand(nir).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float)
# nir是近红波段对应的波段数
# 以数组的形式读取红波段和近红外波段

4.计算NDVI(归一化植被指数)

其他光谱指数类似,指数更换red、nir对应的波段即可。

b1 = array_nir-array_red
b2 = array_nir+array_red
NDVI_data = np.divide(b1, b2, out=np.zeros_like(b1), where=b2 != 0) # 计算NDVI

5.保存计算好的NDVI

这里需要先创建一个数据驱动,用于存储数组,类型可以替换(如可以保存为TIFF、ENVI、HFA等不同格式),这里我保存的TIFF格式,但需要注意的是GDAL中的类型命名不同,TIFF格式不能直接写TIFF,而是GTIFF,具体格式要求大家可以参考Python与开源GIS

driver = gdal.GetDriverByName('GTiff')  # 载入数据驱动,用于存储内存中的数组

随后我们需要创建一个空数组,给这个数组写入各类属性,如高度、宽度、波段数、投影等,一般我们都使用原始输入数据的属性。

s_result = driver.Create(out_path, ds_width, ds_height, bands=1, eType=gdal.GDT_Float64)
# 创建一个数组,宽高为原始尺寸
ds_result.SetGeoTransform(ds_geo) # 导入仿射地理变换参数
ds_result.SetProjection(ds_prj) # 导入投影信息
ds_result.GetRasterBand(1).SetNoDataValue(9999) # 将无效值设为9999

最后,我们再将计算好的NDVI写入数组,删除缓存即可。注意缓存一定要删除,不然NDVI不会写入数组。

ds_result.GetRasterBand(1).WriteArray(NDVI_data)  # 将NDVI的计算结果写入数组
del ds_result
# 删除内存中的结果,否则结果不会写入图像中

三、完整程序

# -*- coding: utf-8 -*-
"""
@Time : 2023/3/30 9:11
@Auth : RS迷途小书童
@File :NDVI计算.py
@IDE :PyCharm
"""
import numpy as np
from osgeo import gdal def Get_data(filepath):
ds = gdal.Open(filepath) # 打开数据集dataset
ds_width = ds.RasterXSize # 获取数据宽度
ds_height = ds.RasterYSize # 获取数据高度
ds_bands = ds.RasterCount # 获取波段数
ds_geo = ds.GetGeoTransform() # 获取仿射地理变换参数
ds_prj = ds.GetProjection() # 获取投影信息
print("影像的宽度为:" + str(ds_width))
print("影像的高度为:" + str(ds_height))
print("仿射地理变换参数为:" + str(ds_geo))
print("投影坐标系为:" + str(ds_prj))
# data = ds.ReadAsArray(0, 0, ds_width, ds_height) # 以数组的形式读取整个数据集 def Write_NDVI(filepath, out_path, red, nir):
print("-----正在进行归一化植被指数NDVI计算-----")
ds = gdal.Open(filepath) # 打开数据集dataset
ds_width = ds.RasterXSize # 获取数据宽度
ds_height = ds.RasterYSize # 获取数据高度
ds_geo = ds.GetGeoTransform() # 获取仿射地理变换参数
ds_prj = ds.GetProjection() # 获取投影信息
array_red = ds.GetRasterBand(red).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float)
# red是红波段对应的波段数
array_nir = ds.GetRasterBand(nir).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float)
# nir是近红波段对应的波段数
# 以数组的形式读取红波段和近红外波段
b1 = array_nir-array_red
b2 = array_nir+array_red
NDVI_data = np.divide(b1, b2, out=np.zeros_like(b1), where=b2 != 0) # 计算NDVI
driver = gdal.GetDriverByName('GTiff') # 载入数据驱动,用于存储内存中的数组
ds_result = driver.Create(out_path, ds_width, ds_height, bands=1, eType=gdal.GDT_Float64)
# 创建一个数组,宽高为原始尺寸
ds_result.SetGeoTransform(ds_geo) # 导入仿射地理变换参数
ds_result.SetProjection(ds_prj) # 导入投影信息
ds_result.GetRasterBand(1).SetNoDataValue(9999) # 将无效值设为9999
ds_result.GetRasterBand(1).WriteArray(NDVI_data) # 将NDVI的计算结果写入数组
del ds_result
# 删除内存中的结果,否则结果不会写入图像中
print("计算完成") if __name__ == "__main__":
file_path = r"G:/Shanghai_TreeClassicfication/Sen2Cor_Shanghai/Shanghai.dat"
# 输入的栅格数据路径
out_path1 = r"G:/GDAL_try/Shanghai-1.tif"
# 导出的文件路径
Get_data(file_path) # 执行函数,获取影像基本信息
print("\n")
print("--------------NDVI计算--------------")
red1 = int(input("请输入红波段:"))
nir1 = int(input("请输入近红外波段:"))
Write_NDVI(file_path, out_path1, red1, nir1) # 执行函数,计算NDVI

        使用Python去处理遥感影像可以大大减少我们的工作时间,提升工作效率。可能在一幅遥感影像处理时感觉还没有ENVI计算NDVI的速度快,但实际上如果你需要研究长时间序列的NDVI或者大量卫星影像,你就会发现编程给你带来的便利不是一点半点。针对上面分享的程序,只需加入os.listdir和for循环即可遍历文件夹中所有的栅格数据,成百上千幅影像在后台一会就处理好了。同时如果有需要,还可以直接将程序作为函数调用,用在完整的遥感影像预处理、定量分析中。本文章仅作为学习使用,如有侵权请联系作者删除。

如果大家在学习Python或者RS时有什么问题,可以随时留言交流!如果大家对批量处理有兴趣同样可以留言给博主,博主会分享相关代码以供学习!

【Python&RS】GDAL计算遥感影像光谱指数(如NDVI、NDWI、EVI等)的更多相关文章

  1. 基于GDAL的遥感影像显示(C#版)

    基于GDAL的遥感影像显示(C#版) - 菜菜的专栏 - 博客频道 - CSDN.NET  http://blog.csdn.net/RSyaoxin/article/details/9220735

  2. Python ArcPy批量计算多时相遥感影像的各项元平均值

      本文介绍基于Python中ArcPy模块,对大量长时间序列栅格遥感影像文件的每一个像元进行多时序平均值的求取.   在遥感应用中,我们经常需要对某一景遥感影像中的全部像元的像素值进行平均值求取-- ...

  3. Python gdal读取MODIS遥感影像并结合质量控制QC波段掩膜数据

      本文介绍基于Python中GDAL模块,实现MODIS遥感影像数据的读取.计算,并基于质量控制QC波段进行图像掩膜的方法.   前期的文章Python GDAL读取栅格数据并基于质量评估波段QA对 ...

  4. 1. GDAL与OpenCV2.X数据转换(适合多光谱和高光谱等多通道的遥感影像)

    一.前言 GDAL具有强大的图像读写功能,但是对常用图像处理算法的集成较少,OpenCV恰恰具有较强的图像处理能力,因此有效的结合两者对图像(遥感影像)的处理带来了极大的方便.那么如何实现GDAL与o ...

  5. GDAL与OpenCV2.X数据转换(适合多光谱和高光谱等多通道的遥感影像)

    一.前言 GDAL具有强大的图像读写功能,但是对常用图像处理算法的集成较少,OpenCV恰恰具有较强的图像处理能力,因此有效的结合两者对图像(遥感影像)的处理带来了极大的方便.那么如何实现GDAL与o ...

  6. Python核对遥感影像批量下载情况的方法

      本文介绍批量下载遥感影像时,利用Python实现已下载影像文件的核对,并自动生成未下载影像的下载链接列表的方法.   批量下载大量遥感影像数据对于GIS学生与从业人员可谓十分常见.然而,对于动辄成 ...

  7. Python ArcPy批量掩膜、重采样大量遥感影像

      本文介绍基于Python中ArcPy模块,对大量栅格遥感影像文件进行批量掩膜与批量重采样的操作.   首先,我们来明确一下本文的具体需求.现有一个存储有大量.tif格式遥感影像的文件夹:且其中除了 ...

  8. python 练习题:计算的BMI指数,并根据BMI指数条件选择

    小明身高1.75,体重80.5kg.请根据BMI公式(体重除以身高的平方)帮小明计算他的BMI指数,并根据BMI指数:低于18.5:过轻18.5-25:正常25-28:过重28-32:肥胖高于32:严 ...

  9. 《Python之BMI计算》

    <Python之BMI计算> 前段时间写了个 BMI 因为刚刚开始学 有几个错误 第一个: 厘米我当时也没注意因为觉得去掉0.00的话后面1866666666是正确的BMI值 刚刚去看看去 ...

  10. 深度学习遥感影像(哨兵2A/B)超分辨率

    这段时间,用到了哨兵影像,遇到了一个问题,就是哨兵影像,它的RGB/NIR波段是10米分辨率的,但是其他波段是20米和60米的,这就需要pansharpening了,所以我们需要设计一种算法来进行解决 ...

随机推荐

  1. Quicker快速开发,简单的网页数据爬取(示例,获取天眼查指定公司基础工商数据)

    前言 有某个线上项目,没有接入工商接口,每次录入公司的时候,都要去天眼查.企查查或者其他公开数据平台,然后手动录入,一两个还好说,数量多了的重复操作就很烦,而且,部分数据是包含超链接,一不注意就点进去 ...

  2. 爬取JSON文件并且存储

    思路 1 先调用模块 2 定义一个函数 2.1 获取网址(点击评论 找到JSON的文件(分析评论preview)获取Request URL后面的地址) 2.2 添加用户的请求头 2.3 使用get方法 ...

  3. flutter---->阿里云oss的插件

    目前为止,阿里云官方并没有dart版本的oss sdk,所以才开发了这个插件flutter_oss_aliyun提供对oss sdk的支持. flutter_oss_aliyun 一个访问阿里云oss ...

  4. [ACM]TL-Kruskal

    #include<iostream> #include<cstdio> using namespace std; struct edge { int u; int v; int ...

  5. Azure Terraform(十三)提升 Azure Web App Plan 的性能

    一,引言 一,引言 我们是否正在为部署在云主机上的应用程序性能缓慢和停机问题而苦恼?我们是否正在因为云主机上仅仅部署了应用程序,在流量平缓的时候而浪费大量的计算资源而心疼荷包.那么让我们来一起看看 A ...

  6. 用 Go 剑指 Offer 11. 旋转数组的最小数字

    已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到:若旋转 4 次,则可以得到 [ ...

  7. django渲染模版时比实际少了8小时?

    这是因为django的时间是UTC时间. 我们通过改配置文件将其改成本地时间 修改配置文件 # 将时间从UTC转化成当前时间 TIME_ZONE = 'Asia/Shanghai' # USE_TZ ...

  8. Python tkinter 进度条代码

    1 import tkinter as tk 2 import time 3 4 # 创建主窗口 5 window = tk.Tk() 6 window.title('进度条') 7 window.g ...

  9. [Wechat]概念辨析:微信的生态平台/运管平台

    0 引言 微信的各类XX社区.XX文档.XX平台,实在是太多,让人眼花缭乱.必须得理一理了. 1 微信公众平台 https://mp.weixin.qq.com/ 即 微信公众号(小程序 / 订阅号 ...

  10. AspNetCore 成长杂记(一):JWT授权鉴权之生成JWT(其二)

    引子 前面说了用第三方类库生成JWT的故事,给我带来了很大的方便,并且我也承诺要写一篇用常规方法生成JWT的文章(一般都是用微软官方的类库),因此才有了这篇文章. 另外,在前面的文章中,我要纠正一下一 ...