如何调整大型NDVI数组尺寸并存储为灰度图供pydeck位图层使用
解决方案
你遇到的死机问题核心是两个原因:一是直接加载全量高分辨率数组后用skimage.resize的高内存开销插值逻辑,二是代码中维度处理错误产生了额外内存占用。以下是两种低内存的可行实现方案:
方案1:读取tif时直接重采样(最优,内存占用最低)
无需先把全量超大数组读入内存,直接用rasterio的重采样能力在读取阶段就生成目标尺寸的数组,全程不会加载原始高分辨率数据:
import rasterio from rasterio.enums import Resampling import numpy as np from PIL import Image fp = 'data/ndvi/index_ndvi.tif' target_width = 1024 with rasterio.open(fp) as src: # 计算目标高度,保持原始宽高比 target_height = int(target_width * src.height / src.width) # 读取时直接重采样,采用双线性插值平衡效果和速度 ndvi_data = src.read( 1, out_shape=(target_height, target_width), resampling=Resampling.bilinear ) # 数值归一化到0-255 ndvi_norm = ((ndvi_data - ndvi_data.min()) / (ndvi_data.max() - ndvi_data.min()) * 255).astype(np.uint8) # 保存为jpg格式 Image.fromarray(ndvi_norm).save('ndvi_resized.jpg')
方案2:已加载全量数组时用Pillow缩放
如果你已经把全量数组加载到内存了,用Pillow的resize接口比skimage效率高很多,内存占用仅为skimage的1/3不到:
import numpy as np from PIL import Image # vals为你已经读取并归一化后的uint8数组,原始shape为(19204, 21063) target_width = 1024 target_height = int(target_width * vals.shape[0] / vals.shape[1]) # 转Image对象后直接缩放,用LANCZOS插值保证缩放后清晰度 img_resized = Image.fromarray(vals).resize((target_width, target_height), resample=Image.Resampling.LANCZOS) # 保存图片 img_resized.save('ndvi_resized.jpg')
原代码问题说明
- 维度逻辑错误:原始数组的shape是
(高度, 宽度),你计算目标高度时的宽高比逻辑写反,还额外扩展了不必要的维度,导致resize时生成了形状错误的超大数组 - skimage.resize默认使用高开销的插值方式,处理超大型数组时内存占用会翻数倍,很容易触发内存不足导致死机
内容的提问来源于stack exchange,提问作者Niko Gamulin
相关产品推荐
相关产品推荐

