GDAL 读取遥感影像数据

前言

为了进一步对遥感影像数据进行处理,需要访问遥感影像中的数据,即影像像元灰度值。在 GDAL 中,提供了 ReadRaster() 和 ReadAsArray() 两个方法用来访问影像数据。

本篇教程在之前一系列文章的基础上讲解

  • GDAL 简介[1]
  • GDAL 下载安装[2]
  • GDAL 开发起步[3]

如果你还没有看过,建议从那里开始。

1. 开发环境

本文使用如下开发环境,以供参考。

时间:2025年

系统:Windows 10

Python:3.11.7

GDAL:3.7.3

Numpy:1.24.3

2. ReadRaster 方法

ReadRaster方法返回一个栅格字节流数据,具有多个参数。

  • xoff,yoff :目标点距离全图原点的位置(以像元为单位)
  • xsize,ysize : 目标图像的矩形的长和宽(以像元为单位)
  • buf_xsize,buf_ysize :图像缩放大小。用来定义缩放后图像最终的宽和高
  • buf_type :对读取的数据类型进行转换(比如原图数据类型是short,可以将其缩小成byte
  • band_list :适应多波段的情况。可以指定要读取的波段。
ini 复制代码
from osgeo import gdal

# 启用异常处理(推荐)
gdal.UseExceptions()

# 打开影像文件
dataset = gdal.Open("LC08_L1TP_130042_20210212_20210304_01_T1_B1.TIF")

print(help(dataset.ReadRaster()))
# 获取目标波段数据
band = dataset.GetRasterBand(1)

print("波段数据:",band)

# 读取整个波段为字节流
bytes_stream = band.ReadRaster()

# 读取指定区域
xoff,yoff,xsize,ysize = 100,100,200,200
buf_xsize,buf_ysize = 200,200

data_bytes_region = band.ReadRaster(xoff,yoff,xsize,ysize,buf_xsize,buf_ysize)
# print("n 数据区域:",data_bytes_region)

# 指定数据类型
data_bytes_float = band.ReadRaster(buf_type=gdal.GDT_Float32)
# print("n 数据类型:",data_bytes_float3

3. ReadAsArray 方法

ReadAsArray方法与ReadRaster方法相似具有多个参数,不同的是起返回的数据为类型数组。

  • xoff,yoff :目标点距离全图原点的位置(以像元为单位)
  • xsize,ysize : 目标图像的矩形的长和宽(以像元为单位)
  • buf_xsize,buf_ysize :图像缩放大小。用来定义缩放后图像最终的宽和高
  • buf_type :对读取的数据类型进行转换(比如原图数据类型是short,可以将其缩小成byte
  • band_list :适应多波段的情况。可以指定要读取的波段。
ini 复制代码
from osgeo import gdal
import numpy as np

# 启用异常处理(推荐)
gdal.UseExceptions()

# 打开影像文件
dataset = gdal.Open("LC08_L1TP_130042_20210212_20210304_01_T1_B1.TIF")

band = dataset.GetRasterBand(1)

# 读取整个波段
array = band.ReadAsArray()
print(type(array)) # <class 'numpy.ndarray'>
print(array.shape) # (行数, 列数)

# 读取指定区域
xoff,yoff,xsize,ysize = 100,100,200,200
sub_array = band.ReadAsArray(xoff,yoff,xsize,ysize)

# 分块读取
buf_xsize,buf_ysize = 100,100
array_buf = band.ReadAsArray(buf_xsize=buf_xsize,buf_ysize=buf_ysize)

4. 读取多波段数据

本例中未进行波段合成,只有一个波段数据,所以直接用dataset.GetRasterBand(1)读取波段数据。

ini 复制代码
"""
读取多波段数据
"""
import numpy as np
from osgeo import gdal

# 启用异常处理(推荐)
gdal.UseExceptions()

# 打开影像文件
dataset = gdal.Open("D:AppLC81300422021043LGN00LC08_L1TP_130042_20210212_20210304_01_T1_B1.TIF")

def read_multi_band(dataset,method="array"):
    # 获取波段总数
    bands_count = dataset.RasterCount
    rows,cols = dataset.RasterYSize,dataset.RasterXSize

    if method == "array":
        # 使用 ReadAsArray
        data = np.zeros((rows,cols,bands_count))
        for i in range(bands_count):
            band = dataset.GetRasterBand(1)
            if band:
                data[:,:,i] = band.ReadAsArray()
    elif method == "raster":
        # 使用 ReadRaster
        data = np.zeros((rows,cols,bands_count))
        for i in range(bands_count):
            band = dataset.GetRasterBand(1)
            if band:
                data_bytes = band.ReadRaster()
                # 数据转换
                band_array = np.frombuffer(data_bytes,dtype=gdal.GetDataTypeName(band.DataType).lower())
                data[:, :, i] = band_array.reshape((rows, cols))

    return data

data_bytes = read_multi_band(dataset,'raster') 
data_array = read_multi_band(dataset,'array')  

print(f"数据相等:{data_bytes == data_array}") 

5. 性能测试

在GDAL中,使用ReadAsArray方法与ReadRaster方法读取栅格数据在效率上存在较大差距。经过测试发现,ReadRaster方法比起ReadAsArray方法要快很多。

python 复制代码
"""
性能测试
"""
import time
import numpy as np
from osgeo import gdal

# 启用异常处理(推荐)
gdal.UseExceptions()

# 打开影像文件
dataset = gdal.Open("D:AppLC81300422021043LGN00LC08_L1TP_130042_20210212_20210304_01_T1_B1.TIF")

band = dataset.GetRasterBand(1)

def perfomanse(band):
    # 测试ReadArray
    start_time = time.time()
    array1 = band.ReadAsArray()
    time_array = time.time() - start_time

    # 测试ReadRaster
    start_time = time.time()
    data_bytes = band.ReadRaster()
    array2 = np.frombuffer(data_bytes,dtype=gdal.GetDataTypeName(band.DataType).lower())
    array2 = array2.reshape((band.YSize,band.XSize))
    time_raster = time.time() - start_time

    print(f"ReadArray时间:{time_array:.4f} s")
    print(f"ReadRaster时间:{time_raster:.4f} s")
    print(f"结果相等: {np.array_equal(array1, array2)}")

    return time_array, time_raster

perfomanse(band)

以下是输出结果。

6. 主要区别

ReadAsArray方法与ReadRaster方法存在以下区别。ReadAsArray()方法更简单、更直接,适合大多数应用场景;而ReadRaster()方法更灵活、更底层,适合需要精细控制的高级应用。

特性 ReadRaster() ReadAsArray()
返回类型 二进制字节流 (bytes) NumPy数组
内存使用 较低,需要手动处理 较高,自动转换为数组
灵活性 高,可控制数据类型和读取区域 较低,但更易用
性能 需要额外转换步骤 直接返回数组,性能更好
使用复杂度 较高,需要更多代码 较低,简单易用

参考资料

1\]GDAL 简介 \[2\]GDAL 下载安装 \[3\]GDAL 开发起步

相关推荐
IT_陈寒3 小时前
Spring Boot 3.2 新特性全解析:这5个性能优化点让你的应用提速50%!
前端·人工智能·后端
携欢3 小时前
PortSwigger靶场之Stored DOM XSS通关秘籍
前端·xss
LDM>W<4 小时前
Electron下载失败
前端·javascript·electron
EndingCoder4 小时前
Electron 新特性:2025 版本更新解读
前端·javascript·缓存·electron·前端框架·node.js·桌面端
BillKu4 小时前
Vue3 中使用 DOMPurify 对渲染动态 HTML 进行安全净化处理
前端·安全·html
子兮曰4 小时前
🔥深度解析:Nginx目录浏览美化与功能增强实战指南
前端·javascript·nginx
machinecat4 小时前
node,小程序合成音频的方式
前端·node.js
我是日安4 小时前
从零到一打造 Vue3 响应式系统 Day 4 - 核心概念:收集依赖、触发更新
前端·vue.js
跟橙姐学代码4 小时前
不要再用 print() 了!Python logging 库才是调试的终极武器
前端·python