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 开发起步

相关推荐
橙序员小站35 分钟前
Agent Skill 是什么?一文讲透 Agent Skill 的设计与实现
前端·后端
炫饭第一名3 小时前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
王晓枫3 小时前
flutter接入三方库运行报错:Error running pod install
前端·flutter
符方昊3 小时前
React 19 对比 React 16 新特性解析
前端·react.js
ssshooter3 小时前
又被 Safari 差异坑了:textContent 拿到的值居然没换行?
前端
曲折4 小时前
Cesium-气象要素PNG色斑图叠加
前端·cesium
Forever7_4 小时前
Electron 淘汰!新的桌面端框架 更强大、更轻量化
前端·vue.js
Angelial4 小时前
Vue3 嵌套路由 KeepAlive:动态缓存与反向配置方案
前端·vue.js
jiayu4 小时前
Angular学习笔记24:Angular 响应式表单 FormArray 与 FormGroup 相互嵌套
前端
jiayu4 小时前
Angular6学习笔记13:HTTP(3)
前端