如何基于5×5像素聚合统计对TIFF影像降尺度生成50m分辨率结果
10m二值TIFF降尺度生成50m水体占比影像实现方法
核心需求
对10m分辨率的二值分类TIFF做聚合重采样,输出50m分辨率结果:原始影像像素值0代表水体、1代表冰,每个50m像素的值对应该像素覆盖的原始影像5×5像素块内的水体占比,取值范围为01(可按需转换为0100的百分比值)。
方案1:GDAL命令行快速实现(推荐)
无需手写代码,GDAL内置工具即可完成全流程,内部做了分块读写优化,处理大影像不会占满内存,适合批量作业:
- 先安装配置好GDAL运行环境
- 因为要统计0值(水体)的占比,先将像素值反转(水体转为1、冰转为0),再用平均重采样聚合到50m分辨率,平均值就是对应窗口的水体占比,直接执行以下命令:
# 反转像素值,生成临时中间文件 gdal_calc.py -A 输入的10m影像.tif --calc="1-A" --outfile=temp_reclass.tif # 重采样到50m分辨率,用平均算法计算窗口内水体占比 gdalwarp -tr 50 50 -r average -tap temp_reclass.tif 输出_50m水体占比.tif # 删除临时文件(Windows下用del命令) rm temp_reclass.tif
参数说明:
-tap参数会强制输出影像对齐整格网,避免5×5窗口和原始像素块错位;如果不需要严格对齐格网可以去掉该参数。
方案2:Python自定义脚本实现
如果需要自定义边缘区域处理逻辑、统计规则,可以用rasterio+numpy编写脚本,灵活度更高:
- 先安装依赖库:
pip install rasterio numpy - 参考代码如下:
import numpy as np import rasterio from rasterio.windows import Window # 按需修改以下参数 INPUT_PATH = "你的10m输入影像路径.tif" OUTPUT_PATH = "50m水体占比结果.tif" SCALE_FACTOR = 5 # 10m到50m对应5倍聚合 WATER_VAL = 0 # 原始影像中水体对应的像素值 with rasterio.open(INPUT_PATH) as src: # 计算输出影像尺寸和空间参考 out_height = int(np.ceil(src.height / SCALE_FACTOR)) out_width = int(np.ceil(src.width / SCALE_FACTOR)) out_transform = rasterio.transform.from_origin( src.bounds.left, src.bounds.top, src.res[0] * SCALE_FACTOR, src.res[1] * SCALE_FACTOR ) res = np.zeros((out_height, out_width), dtype=np.float32) # 逐窗口计算水体占比 for out_row in range(out_height): for out_col in range(out_width): # 定位当前50m像素对应的原始影像窗口 row_off = out_row * SCALE_FACTOR col_off = out_col * SCALE_FACTOR win = Window(col_off, row_off, SCALE_FACTOR, SCALE_FACTOR) # 读取窗口数据,边缘不足5*5的区域自动填充空值 win_arr = src.read(1, window=win, boundless=True, fill_value=np.nan) valid_mask = ~np.isnan(win_arr) # 无有效像素则赋值空值,否则计算水体占比 if valid_mask.sum() == 0: res[out_row, out_col] = np.nan else: water_cnt = (win_arr[valid_mask] == WATER_VAL).sum() res[out_row, out_col] = water_cnt / valid_mask.sum() # 要输出百分比的话把上一行换成下面这行 # res[out_row, out_col] = (water_cnt / valid_mask.sum()) * 100 # 更新输出影像元数据并写入文件 out_meta = src.meta.copy() out_meta.update( driver="GTiff", height=out_height, width=out_width, transform=out_transform, dtype=rasterio.float32, nodata=np.nan ) with rasterio.open(OUTPUT_PATH, "w", **out_meta) as dst: dst.write(res, 1)
- 脚本默认逻辑:影像边缘不足5×5像素的区域,按实际存在的有效像素计算占比,不会强制补0或丢弃边缘结果;输出值为0~1的浮点数,1代表对应区域全为水体,0代表全为冰。
内容的提问来源于stack exchange,提问作者SNunes
相关产品推荐
相关产品推荐

