前言
❝
为了进一步对遥感影像数据进行处理,需要访问遥感影像中的数据,即影像像元灰度值。在 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 开发起步