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

相关推荐
mapbar_front1 分钟前
顺利通过试用期:避开三大陷阱,掌握三个关键点
前端·面试
why技术20 分钟前
1K+Star的开源项目能给一个在校大学生带来什么?
前端·人工智能·后端
@PHARAOH21 分钟前
HOW - localstorage 超时管理方案
前端·javascript·vue.js
im_AMBER36 分钟前
React 05
开发语言·前端·javascript·笔记·学习·react.js·前端框架
showker38 分钟前
ecstore等产品开启缓存-后台及前台不能登录原因-setcookie+session问题
java·linux·前端
csj502 小时前
前端基础之《React(4)—webpack简介-编译打包优化》
前端·react
万少2 小时前
Trae AI 编辑器6大使用规则
前端·javascript·人工智能
好玩的Matlab(NCEPU)3 小时前
如何编写 Chrome 插件(Chrome Extension)
前端·chrome
Yan-英杰3 小时前
Deepseek大模型结合Chrome搜索爬取2025AI投资趋势数据
前端·chrome
Crystal3283 小时前
app里video层级最高导致全屏视频上的操作的东西显示不出来的问题
前端·vue.js