首页 > 编程语言 >【Python&RS】基于GDAL遥感影像分幅裁剪

【Python&RS】基于GDAL遥感影像分幅裁剪

时间:2023-08-15 17:23:08浏览次数:171  
标签:RS Python frame col GDAL geo ds 影像 left

        随着科技的进步,遥感影像包含的信息越来越多,存储空间也变得很大,这就导致我们在处理影像时软件会非常的卡。同时目前很火的深度学习也需要对影像分割后制作样本集,所以今天给大家分享下如何使用Python的GDAL库对遥感影像进行分幅裁剪!

一、导入需要的三方库

        tkinter.filedialog是为了使用窗口打开影像,这样就不用每次使用时都修改一下影像路径了。numpy库是为了以数组的形式读取波段。

import os
from osgeo import gdal
import numpy as np
import tkinter.filedialog

二、读取影像的基本信息

def Get_data(filepath):
    """
    :param filepath: 输入数据路径
    :return: 输出影像的基本信息
    """
    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_bands))
    print("仿射地理变换参数为:" + str(ds_geo))
    print("投影坐标系为:" + str(ds_prj))
    # data = ds.ReadAsArray(0, 0, ds_width, ds_height)  # 以数组的形式读取整个数据集

三、分幅裁剪

1.计算裁剪的宽度、高度

        raw是多少行,col是多少列。

raw_frame = int(ds_height / raw)
# 计算每幅图像的高度
col_frame = int(ds_width / col)
# 计算每幅图像的宽度

2.计算分幅左上角的像素坐标

        j,k是通过for循环每一行每一列,这个在后面的完整代码中会有展示

left_x = j * raw_frame
left_y = k * col_frame
# 计算当前影像的左上角像素坐标

3.获取新的投影和仿射地理变换参数

ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数
top_left_x = ds_geo[0]  # 原始影像左上角x的投影坐标
top_left_y = ds_geo[3]  # 原始影像左上角y投影坐标
top_left_x = top_left_x + left_y * ds_geo[1]
top_left_y = top_left_y + left_x * ds_geo[5]
# 计算得到当前影像的左上角投影坐标
ds_geo = (top_left_x, ds_geo[1], ds_geo[2], top_left_y, ds_geo[4], ds_geo[5])
# 新影像的仿射地理变换参数
ds_result.SetGeoTransform(ds_geo)  # 导入仿射地理变换参数
ds_result.SetProjection(ds.GetProjection())  # 导入投影信息

4.创建新的tif循环写入各个波段

driver = gdal.GetDriverByName('GTiff')  # 载入数据驱动,用于存储内存中的数组
ds_result = driver.Create(out_path+"%s_%s.tif" % (j+1, k+1), col_frame, raw_frame,
                                      bands=ds_bands, eType=gdal.GDT_Float64)  # 创建空tif
for i in range(1, ds_bands+1):
    array_band = ds.GetRasterBand(i).ReadAsArray(left_y, left_x, col_frame,raw_frame).astype(np.float64)
    # 根据左上角的像素坐标和幅宽读取指定区域内的数据
    ds_result.GetRasterBand(i).SetNoDataValue(0)  # 将无效值设为0
    ds_result.GetRasterBand(i).WriteArray(array_band)  # 将每个波段写入新的文件中

5.删除空值

        影像一般都不是正正好好的矩形,所以裁剪时会有很多没有数据的影像,所以我们要把这些影像删除。

if array_band.any() == 0:
    ds_result = None
    print("此幅影像为空值,已删除!")
    os.remove(out_path+"%s_%s.tif" % (j+1, k+1))

四、完整代码

# -*- coding: utf-8 -*-
"""
@Time : 2023/8/14 11:34
@Auth : RS迷途小书童
@File :Image Framing and Cropping.py
@IDE :PyCharm
@Purpose :遥感影像分幅裁剪
"""
import os
from osgeo import gdal
import numpy as np
import tkinter.filedialog


def Get_data(filepath):
    """
    :param filepath: 输入数据路径
    :return: 输出影像的基本信息
    """
    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_bands))
    print("仿射地理变换参数为:" + str(ds_geo))
    print("投影坐标系为:" + str(ds_prj))
    # data = ds.ReadAsArray(0, 0, ds_width, ds_height)  # 以数组的形式读取整个数据集


def Frame_image(filepath, out_path, raw, col):
    """
    :param filepath: 输入需要分幅裁剪的影像路径
    :param out_path: 输出文件夹即可,名称固定为行列
    :param raw: 需要分幅的行数
    :param col: 需要分幅的列数
    :return: None
    """
    ds = gdal.Open(filepath)  # 打开数据集dataset
    ds_width = ds.RasterXSize  # 获取数据宽度
    ds_height = ds.RasterYSize  # 获取数据高度
    ds_bands = ds.RasterCount  # 获取波段数
    for j in range(0, raw):
        for k in range(0, col):
            print("正在裁剪第%s行第%s列......" % (j+1, k+1))
            raw_frame = int(ds_height / raw)
            # 计算每幅图像的高度
            col_frame = int(ds_width / col)
            # 计算每幅图像的宽度
            left_x = j * raw_frame
            left_y = k * col_frame
            # 计算当前影像的左上角像素坐标
            raw_frame = min(ds_height-left_x, raw_frame)
            col_frame = min(ds_width-left_y, col_frame)
            # 防止幅宽超过整幅影像
            driver = gdal.GetDriverByName('GTiff')  # 载入数据驱动,用于存储内存中的数组
            ds_result = driver.Create(out_path+"%s_%s.tif" % (j+1, k+1), col_frame, raw_frame,
                                      bands=ds_bands, eType=gdal.GDT_Float64)  # 创建空tif
            ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数
            top_left_x = ds_geo[0]  # 原始影像左上角x的投影坐标
            top_left_y = ds_geo[3]  # 原始影像左上角y投影坐标
            top_left_x = top_left_x + left_y * ds_geo[1]
            top_left_y = top_left_y + left_x * ds_geo[5]
            # 计算得到当前影像的左上角投影坐标
            ds_geo = (top_left_x, ds_geo[1], ds_geo[2], top_left_y, ds_geo[4], ds_geo[5])
            # 新影像的仿射地理变换参数
            ds_result.SetGeoTransform(ds_geo)  # 导入仿射地理变换参数
            ds_result.SetProjection(ds.GetProjection())  # 导入投影信息
            array_band = []
            for i in range(1, ds_bands+1):
                array_band = ds.GetRasterBand(i).ReadAsArray(left_y, left_x, col_frame, raw_frame).astype(np.float64)
                # 根据左上角的像素坐标和幅宽读取指定区域内的数据
                ds_result.GetRasterBand(i).SetNoDataValue(0)  # 将无效值设为0
                ds_result.GetRasterBand(i).WriteArray(array_band)  # 将每个波段写入新的文件中
            if array_band.any() == 0:
                ds_result = None
                print("此幅影像为空值,已删除!")
                os.remove(out_path+"%s_%s.tif" % (j+1, k+1))
            ds_result = None


if __name__ == "__main__":
    fn_input = open(tkinter.filedialog.askopenfilename(title='选择图片', filetypes=[('所有文件', '.*'), ('JPG', '.jpg'), ('JPG', '.jpeg'), ('TIFF', '.tif'), ('DAT', '.dat'), ('PNG', '.png')]), 'rb')
    path = 'B:/Personal/Vegetation enhancement/layer'
    out_path1 = 'B:/Personal/Python_分幅/'
    # 输出文件夹,不需要文件名,通过行列号命名
    raw1 = int(input("请输入行数:"))
    col1 = int(input("请输入列数:"))
    Frame_image(fn_input.name, out_path1, raw1, col1)

 

        今天主要分享的是遥感影像的分幅裁剪,大家可以用这段代码减少数据量,也可以用它制作样本集。如果大家在学习Python或者RS时有什么问题,可以随时留言交流!如果大家对批量处理有兴趣同样可以留言给博主,博主会分享相关代码以供学习!

标签:RS,Python,frame,col,GDAL,geo,ds,影像,left
From: https://www.cnblogs.com/RSran/p/17631881.html

相关文章

  • python中 函数中的self是什么?
      self可视为类的实例,在使用类创建实例时,我们可能需要强制传入一些参数。所以一般在构造函数_init_里给实例的属性赋值。classStudent(obiect):def__init__(self,name,score):self.name=nameself.score=scoredefprint_score(self):......
  • python语言-----------------身份证信息提前验证
    ##截取身份证信息,判断身份证上面的具体信息:上代码:importredefextract_id_card_info(id_card):#匹配身份证号码并提取出生日期和顺序号match=re.match(r'(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d{1})(\d|X)',id_card)ifmatchisNone:returnNonearea......
  • ​python爬虫——爬取天气预报信息
    在本文中,我们将学习如何使用代理IP爬取天气预报信息。我们将使用Python编写程序,并使用requests和BeautifulSoup库来获取和解析HTML。此外,我们还将使用代理服务器来隐藏我们的IP地址,以避免被目标网站封禁。1.安装必须的库首先,我们需要安装必须的库,包括requests、beauti......
  • Python语言中如何实现字符串拼接?
    在学习和应用Python语言的过程中,我们经常会遇到字符串拼接的问题,其实不管是Python还是其他语言,都把字符串列为最基础和最不可或缺的数据类型,拼接字符串也是必备的一项技能,那么Python语言如何实现这个操作呢?以下是详细的内容:1、加号法使用简单直接,但这种方法效率低......
  • Python基础概念以及命名规范
    PythonBasicIntroduction介绍Pythonisadynamicandstronglytypedprogramminglanguage.Itemploysbothducktypingandgradualtypingviatypehints.WhilePythonsupportsmanydifferentprogrammingstyles,internallyeverythinginPythonisanobject......
  • ​python爬虫——爬取天气预报信息
    在本文中,我们将学习如何使用代理IP爬取天气预报信息。我们将使用Python编写程序,并使用requests和BeautifulSoup库来获取和解析HTML。此外,我们还将使用代理服务器来隐藏我们的IP地址,以避免被目标网站封禁。1.安装必须的库首先,我们需要安装必须的库,包括requests、beauti......
  • 离线安装Python第三方库及依赖包
    1、问题在工作中经常需要在内网环境中安装python第三方库,使用从pypi上下载的whl文件来安装又经常遇到该库也需要依赖包,以至于并不能成功安装。2、解决办法(1)查看所需第三方库安装是否需要依赖库(以requests为例)pipshowrequests(2)使用命令将库及依赖包下载到本地(以requests为......
  • ​python爬虫——爬取天气预报信息
    在本文中,我们将学习如何使用代理IP爬取天气预报信息。我们将使用Python编写程序,并使用requests和BeautifulSoup库来获取和解析HTML。此外,我们还将使用代理服务器来隐藏我们的IP地址,以避免被目标网站封禁。1.安装必须的库首先,我们需要安装必须的库,包括requests、beaut......
  • python重采样tif影像,自定义空间分辨率
    importwarningsimportnetCDF4warnings.filterwarnings('ignore')warnings.filterwarnings('ignore',category=DeprecationWarning)importnetCDF4importpandasaspdimportnumpyasnpfromosgeoimportgdalimportmatplotlib.pyplotasp......
  • 某公司笔试题 - 密码验证合格程序(附python代码)
    #密码要求#1.长度超过8位;2.包括大小写字母,数字,其它符号,以上四种至少三种;3.不能有长度大于2的包含公共元素的字串重复(其他符号不含空格或换行)#数据范围:输入的字符串长度满足1<=n<=100#检测输入密码defcheckpassword(psw):iflen(psw)<=8orlen(psw)>100:r......