如何用Python从Mapbox RGB地形PNG生成16位高度图(代码问题排查)
解决Mapbox RGB地形转高度图的两个问题
问题分析
- 山顶区域本该显示白色却呈现黑色:归一化逻辑本身无错误,但需确保解码后的高度值正确映射到目标范围的最大值,同时保存时匹配对应的数据类型。
- 改用255作为归一化范围时图像全黑:原代码统一使用
np.uint16类型,0-255的数值在16位图像中仅占极小亮度区间,视觉上接近黑色,需根据目标范围选择对应的数据类型(uint8对应255,uint16对应65535)。
修正后的代码
from PIL import Image import numpy as np from io import BytesIO def rgb_to_elevation(images_array_key, save_path, normalize_range=65535): rgb_elevation = Image.open(BytesIO(images_array_key)) rgb_data = np.array(rgb_elevation) # 解码Mapbox RGB地形数据为高度值 r = rgb_data[..., 0] g = rgb_data[..., 1] b = rgb_data[..., 2] decoded_data = -10000 + ((r * 256 * 256 + g * 256 + b) * 0.1) # 归一化处理,避免除以0的情况 min_val = decoded_data.min() max_val = decoded_data.max() if max_val == min_val: normalized = np.zeros_like(decoded_data) else: normalized = ((decoded_data - min_val) / (max_val - min_val)) * normalize_range # 根据归一化范围选择对应的数据类型 if normalize_range == 255: normalized = normalized.astype(np.uint8) elif normalize_range == 65535: normalized = normalized.astype(np.uint16) else: raise ValueError("仅支持255(8位)或65535(16位)的归一化范围") # 保存图像 outimage = Image.fromarray(normalized) outimage.save(save_path) # 使用示例 # rgb_to_elevation(images_array[key], "16bit_heightmap.png", normalize_range=65535) # rgb_to_elevation(images_array[key], "8bit_heightmap.png", normalize_range=255)
关键修正点
- 新增数据类型匹配逻辑:当目标范围为255时转换为
np.uint8,让0-255的数值对应8位图像的完整亮度区间,解决全黑问题。 - 添加除以0的异常处理:当图像所有像素高度相同时,直接生成全0图像,避免计算报错。
- 封装为函数,方便快速切换归一化范围。
内容的提问来源于stack exchange,提问作者dan
相关产品推荐
相关产品推荐

