首页 > 编程语言 >【Python&RS】基于GDAL哨兵二号波段合成

【Python&RS】基于GDAL哨兵二号波段合成

时间:2023-06-13 15:22:40浏览次数:57  
标签:img RS Python image 波段 band path ds GDAL

        学遥感的避免不了使用哨兵数据,毕竟10m的分辨率可以满足大部分的定量分析,同时也是最重要的一点,它免费!!!

 

        之前好像ENVI5.3打不开哨兵数据,易智瑞已给出了解决办法。我想说的是大家能下载L2A级数据就去下,省的麻烦。如果需要的数据只有L1C级,那就使用欧空局发布的Sen2Cor去进行辐射定标和大气校正。

 

        这样就出现了问题,因为Sen2Cor是对单波段进行导出,如果我们一个个导入ENVI去波段组合,那岂不是浪费了很多时间,所以我这里使用Python实现Sentinel-2数据的批量波段组合(PS:Sen2Cor也可以批量大气校正,后面可以出一篇教程)

注意:遥感影像的本质就是多维数组,所以原理并不复杂!看懂这篇文章后同样也可以对其他卫星数据进行波段组合,都是一样的!

一、获取数据的基本信息

        这一步主要是为了给我们波段组合后的栅格数据赋值,如投影、分辨率等信息。这段代码在我之前的博文中出现过无数次了,就不多说了。同时对GDAL库的安装之前也有教过,可以自行翻阅:【Python&RS】GDAL批量裁剪遥感影像/栅格数据

        这里的基本信息可以从任意一个波段获取,因为他们都是一样的。

ds = gdal.Open(image_path)  # 打开数据集dataset
ds_width = ds.RasterXSize  # 获取数据宽度
ds_height = ds.RasterYSize  # 获取数据高度
ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数
ds_prj = ds.GetProjection()  # 获取投影信息

二、将基本信息写入新的栅格驱动

        这里创建驱动时,输入的参数分别是输出文件名,影像宽度、影像高度、输出的波段数。这里波段数可以依据不同卫星自己修改,同时如果你想加入某些卫星的辅助波段(如云掩膜、水汽等)也可以修改这个参数。

driver = gdal.GetDriverByName('ENVI')  # 载入数据驱动,用于存储内存中的数组
ds_result = driver.Create(out_path, ds_width, ds_height, bands=11, eType=gdal.GDT_Int32)
# 创建一个数组,宽高为原始尺寸
ds_result.SetGeoTransform(ds_geo)  # 导入仿射地理变换参数
ds_result.SetProjection(ds_prj)  # 导入投影信息
# 上述代码用于创建空白数组以及获取投影信息

三、遍历文件夹写入波段数据

        我这里是写死了波段名称,如果你们想对其他卫星数据进行组合的话需要自己修改,我这里只适用于哨兵二号数据。此外,如果你有多个哨兵数据需要组合,可以在外面再添加一个for循环文件夹即可实现。

band_lists = ["B2.img", "B3.img", "B4.img", "B5.img", "B6.img", "B7.img", "B8.img", "B8A.img", "B9.img", "B11.img", "B12.img"]
i = 1
for band_list in band_lists:
    # 遍历波段列表
    for image_list in image_lists:
        # 遍历文件夹中所有的文件
        if band_list == image_list:
            # 如果波段列表与文件一致,则将该文件打开
            print(str(i) + ".正在融合%s" % band_list)
            filepath1 = os.path.join(file_path, image_list)
            ds = gdal.Open(filepath1)  # 打开数据集dataset
            band_data = ds.GetRasterBand(1).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float)
            # 以数组的形式读取当前波段
            ds_result.GetRasterBand(i).WriteArray(band_data)
            i += 1
del ds_result
# 删除内存中的结果,否则结果不会写入图像中

四、完整代码

# -*- coding: utf-8 -*-
"""
@Time : 2023/3/31 15:35
@Auth : RS迷途小书童
@File :Band Synthesis.py
@IDE :PyCharm
@Purpose :哨兵2号波段组合
"""
import os
import numpy as np
from osgeo import gdal
from osgeo.gdalconst import *


def Layerstack(file_path, out_path, image_path):
    """
    :param file_path: 输入波段存放的文件夹
    :param out_path: 输出文件路径
    :param image_path: 输入任意影像数据,用于定义坐标系等信息
    :return:
    """
    print("-----开始组合波段-----")

    ds = gdal.Open(image_path)  # 打开数据集dataset
    ds_width = ds.RasterXSize  # 获取数据宽度
    ds_height = ds.RasterYSize  # 获取数据高度
    ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数
    ds_prj = ds.GetProjection()  # 获取投影信息
    driver = gdal.GetDriverByName('ENVI')  # 载入数据驱动,用于存储内存中的数组
    ds_result = driver.Create(out_path, ds_width, ds_height, bands=11, eType=gdal.GDT_Int32)
    # 创建一个数组,宽高为原始尺寸
    ds_result.SetGeoTransform(ds_geo)  # 导入仿射地理变换参数
    ds_result.SetProjection(ds_prj)  # 导入投影信息
    image_lists = os.listdir(file_path)
    del ds
    # 上述代码用于创建空白数组以及获取投影信息
    band_lists = ["B2.img", "B3.img", "B4.img", "B5.img", "B6.img", "B7.img", "B8.img", "B8A.img",
                  "B9.img", "B11.img", "B12.img"]
    i = 1
    for band_list in band_lists:
        # 遍历波段列表
        for image_list in image_lists:
            # 遍历文件夹中所有的文件
            if band_list == image_list:
                # 如果波段列表与文件一致,则将该文件打开
                print(str(i) + ".正在融合%s" % band_list)
                filepath1 = os.path.join(file_path, image_list)
                ds = gdal.Open(filepath1)  # 打开数据集dataset
                band_data = ds.GetRasterBand(1).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float)
                # 以数组的形式读取当前波段
                ds_result.GetRasterBand(i).WriteArray(band_data)
                i += 1
    del ds_result
    # 删除内存中的结果,否则结果不会写入图像中
    print("全部波段合并完成")


if __name__ == "__main__":
    file_path1 = r"G:/resampled/"
    # 存放单波段的文件夹目录
    image_path1 = r"G:/resampled/B2.img"
    # 以B2波段的基本信息作为新栅格投影、地理变换的标准
    out_path1 = r"G:/GDAL_try/3"
    # 输出的文件名,这里是输出ENVI格式,所以不用加后缀名
    Layerstack(file_path1, out_path1, image_path1)
    # 执行函数

 

        本博文代码是我之前在编写使用GDAL计算NDVI时顺便写出来的,自己已经运行过很多次了。效率相比ENVI手动合成肯定提升了不少,但代码感觉还是有些冗余,能用就行还要啥自行车啊。

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

标签:img,RS,Python,image,波段,band,path,ds,GDAL
From: https://www.cnblogs.com/RSran/p/17477609.html

相关文章

  • python3-注释与声明
    1、单行注释也称为行注释,使用字符#在注释内容前标注单行注释可以是独占一行,也可以是在一行代码的尾端添加单行注释一般与下一行代码同样的缩进,但是并不强制2、多行注释也称为块注释,使用成对三个单引号,或三个双引号标记多行注释必须独占一行或多行,不能与代码并行多行注释......
  • beego:interface conversion: interface {} is string, not int
    代码organizationId:=info[0]["organization_id"].(int)报错beego_api:interfaceconversion:interface{}isstring,notintRequestMethod: GETRequestURL: /v1/board2/students/detail2?id=237497RemoteAddr: ::1Stack/usr/local/go/src/runtime/panic.go......
  • Python: json object_hook object_paire_hook
      data='[{"foo":"bar","foo":"baz","b":99}]'json.loads(data,object_hook=print)json.loads(data,object_pairs_hook=print)  ......
  • 【python基础】复杂数据类型-字典(嵌套)
    有时候,需要将一系列字典存储在列表中,或将列表作为值存储在字典中,这称为嵌套。我们可以在列表中嵌套字典、在字典中嵌套列表、在字典中嵌套字典。1.列表嵌套字典我们可以把一个人的信息放在字典中,但是多个人的信息我们无法放在同一个字典中,所以就需要字典列表。其语法格式:[字典......
  • windows卸载应用商店python后,导致conda环境变量不可用解决办法
    输入wherepython可以查看命令位置,大概率会出现两行。在windowsstore安装过python之后,在控制台输入python总是会跳转到应用商店,让再次安装Python,原因是在C:\Users\用户名\AppData\Local\Microsoft\WindowsApps目录下生成了python.exe和python3.exe解决方法:在设置->应用->应用和......
  • Python - fibonacci
    Soisthereeveragoodplacetousemutabledefaults?Yes!Mutabledefaultscanbeveryusefulforcachingand/orrecursivealgorithms:deffibonacci(n,cache={0:0,1:1}):ifnincache:returncache[n]else:value=fibonacci(n-......
  • 如何运行python脚本
    在运行Python脚本之前,您需要确保已经安装了Python解释器。可以在终端中输入以下命令检查是否已安装Python:命令窗口输入:python--version如果输出了Python的版本号,则说明您已经安装了Python。如果没有输出,则需要先安装Python。已安装Python后,可以使用以下命令来运行Python脚本:命......
  • UG二次开发NXOpen-Python(十三)内螺纹滚道干涉磨砂轮截形计算
    滚珠螺母内螺纹滚道在加工时,砂轮接杆偏摆角度为滚道螺旋升角,砂轮截形为滚道法向截形。当螺母导程较大时,比如说1616、2020等规格,螺旋升角较大,若按螺旋升角的大小调整砂轮接杆角度,则砂轮接杆会和螺母内孔产生干涉,此时就需要采用其它加工方法,比如说“以车代磨”、“软轴磨”、“......
  • Python实验课7
    实验任务1classAccount:'''一个模拟银行账户的简单类'''def__init__(self,name,account_number,initial_amount=10):'''构造新账户'''self._name=nameself._card_no=account_numb......
  • Python如何把字符串中形如'\uXXXX'的Unicode字符转换为原始字符
    jsonpickle保存的文本有形如"\u6211\u7684"的字符,看起来很不方便,怎么转换为原始字符呢?参考如下代码:importjsonpickle#定义一个包含Unicode编码字符的字符串text="我的名字是\u674e\u5b87\u5b87"#将字符串保存为JSON格式json_string=jsonpickle.encode(text)......