如何阻止Folium对栅格值进行缩放以适配分类颜色映射?
解决Folium分类栅格自动缩放导致的颜色显示错误问题
Folium的ImageOverlay默认会自动缩放栅格数据的数值范围,这会直接搞乱分类栅格的颜色映射效果。比如你示例里的栅格只有3、4、8三个值,值为8的区域本该显示栗色,结果因为缩放被映射成了红色。要解决这个问题,核心就是绕过Folium的自动缩放逻辑。
解决思路
问题根源在于ImageOverlay会把输入的栅格值归一化到[0,1]区间后再传给颜色映射函数,导致自定义的分段颜色规则失效。最简单的办法是提前把栅格数据转换成RGBA格式的图像数组,直接给Folium传已经完成颜色映射的图像,让它没法再对数值做缩放。
修改后的代码
import folium import numpy as np import branca.colormap as cm from PIL import ImageColor # 生成仅包含3、4、8的测试栅格 raster_data = np.random.randint(low=3, high=9, size=(10, 10)) raster_data[np.where(np.logical_and(raster_data>4, raster_data<8))] = 4 # 自定义分段颜色组,对应值3→蓝色,4→绿色,8→栗色 custom_colormap = [ (0, 255, 255, 255.0), # 备用颜色(示例中用不到) (0, 0, 255, 255.0), # 值3对应的颜色 (0, 255, 0, 255.0), # 值4对应的颜色 (255, 128, 0, 255.0), # 备用颜色 (255, 0, 0, 255.0), # 备用颜色 (128, 0, 0, 255.0) # 值8对应的颜色 ] # 创建分段颜色映射器,匹配我们的数值区间 cmap = cm.StepColormap( custom_colormap, vmin=2.5, vmax=8.5, index=[2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5] ) # 把栅格数据转换成RGBA图像数组,提前完成颜色映射 def raster_to_rgba(raster, cmap): # 创建空的RGBA数组,形状为(行数, 列数, 4) rgba_data = np.zeros((raster.shape[0], raster.shape[1], 4), dtype=np.uint8) # 遍历每个像素,映射对应颜色 for i in range(raster.shape[0]): for j in range(raster.shape[1]): val = raster[i, j] if not np.isnan(val): rgba_data[i, j] = ImageColor.getcolor(cmap(val), 'RGBA') else: rgba_data[i, j] = (0, 0, 0, 0) # 空值设为透明 return rgba_data # 生成RGBA图像 rgba_image = raster_to_rgba(raster_data, cmap) # 创建地图并添加图像叠加层 m = folium.Map(location=(-31.05, 151.15), zoom_start=12) # 直接传入RGBA图像,无需再指定colormap参数 image_overlay = folium.raster_layers.ImageOverlay( image=rgba_image, bounds=[[-31.0, 151.1], [-31.1, 151.2]], zindex=1 ).add_to(m) # 添加颜色图例 m.add_child(cmap) m
关键说明
- 提前映射颜色:自己遍历栅格的每个值,用自定义的分段颜色规则生成对应的RGBA颜色,得到现成的图像数组。
- 绕过自动缩放:把RGBA数组传给
ImageOverlay时,Folium会直接识别为图像,不会再对原始数值做缩放,颜色完全按我们的规则显示。 - 图例保持一致:原来的分段颜色图例可以正常添加,和地图上的显示效果完全匹配。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

