You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用GDAL重采样实现栅格图层下采样并计算95分位数?

如何计算下采样栅格中每个栅格单元的95分位数?

我们有1米分辨率的数字表面模型(DSM),想要生成50米分辨率的版本,要求每个低分辨率栅格单元的值是对应高分辨率区域的95分位数。已知gdalwarp支持中位数(med)、四分位数(q1/q3)重采样,但不支持自定义分位数设置,以下是几种可行的实现方法:

方法一:GDAL Python API 自定义计算

通过GDAL的Python接口逐窗口读取高分辨率栅格数据,计算95分位数后写入低分辨率输出栅格:

from osgeo import gdal
import numpy as np

# 配置路径
input_tif = "dsm_1m.tif"
output_tif = "dsm_50m_95p.tif"

# 打开输入栅格
src_ds = gdal.Open(input_tif)
src_band = src_ds.GetRasterBand(1)
src_gt = src_ds.GetGeoTransform()
src_proj = src_ds.GetProjection()
nodata_val = src_band.GetNoDataValue()

# 定义输出栅格参数
output_res = 50  # 50米分辨率
output_cols = int((src_ds.RasterXSize * src_gt[1]) / output_res)
output_rows = int((src_ds.RasterYSize * abs(src_gt[5])) / output_res)

# 创建输出栅格
driver = gdal.GetDriverByName("GTiff")
dst_ds = driver.Create(
    output_tif, output_cols, output_rows, 1, gdal.GDT_Float32,
    options=["COMPRESS=LZW"]
)
dst_ds.SetGeoTransform((src_gt[0], output_res, src_gt[2], src_gt[3], src_gt[4], -output_res))
dst_ds.SetProjection(src_proj)
dst_band = dst_ds.GetRasterBand(1)
dst_band.SetNoDataValue(nodata_val)

# 逐窗口计算95分位数
win_xsize = int(output_res / src_gt[1])
win_ysize = int(output_res / abs(src_gt[5]))

for y in range(output_rows):
    for x in range(output_cols):
        # 计算输入栅格中的窗口位置
        src_x = x * win_xsize
        src_y = y * win_ysize
        # 处理边缘窗口,避免超出栅格范围
        actual_xsize = min(win_xsize, src_ds.RasterXSize - src_x)
        actual_ysize = min(win_ysize, src_ds.RasterYSize - src_y)
        
        # 读取窗口数据并过滤无效值
        data = src_band.ReadAsArray(src_x, src_y, actual_xsize, actual_ysize)
        valid_data = data[data != nodata_val]
        
        if len(valid_data) == 0:
            result = nodata_val
        else:
            result = np.percentile(valid_data, 95)
        
        # 写入当前输出栅格单元
        dst_band.WriteArray(np.array([[result]]), x, y)

# 释放资源
dst_band.FlushCache()
src_ds = None
dst_ds = None

方法二:R语言 raster 包快速实现

利用R的raster包的aggregate函数,直接指定分位数计算逻辑:

library(raster)

# 读取高分辨率DSM
dsm_high <- raster("dsm_1m.tif")
# 按50米分辨率聚合,计算95分位数(忽略NA值)
dsm_low_95p <- aggregate(
    dsm_high, 
    fact = 50,  # 聚合因子(50=50米/1米)
    fun = function(x) quantile(x, 0.95, na.rm = TRUE)
)
# 保存结果
writeRaster(dsm_low_95p, "dsm_50m_95p.tif", format = "GTiff", overwrite = TRUE)

方法三:GRASS GIS 命令行工具

使用GRASS的r.resamp.stats工具直接指定分位数参数:

  1. 导入高分辨率栅格:
r.in.gdal input=dsm_1m.tif output=dsm_1m
  1. 设置工作区域为50米分辨率:
g.region raster=dsm_1m res=50
  1. 计算95分位数下采样:
r.resamp.stats input=dsm_1m output=dsm_50m_95p method=quantile quantile=0.95
  1. 导出结果为TIFF:
r.out.gdal input=dsm_50m_95p output=dsm_50m_95p.tif format=GTiff

内容的提问来源于stack exchange,提问作者jens wiesehahn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 22:24:52