使用folium.raster_layers.ImageOverlay()时地图图像不显示的问题
Folium叠加GeoTIFF仅显示边界框无图像的问题排查与解决
我尝试用folium将GeoTIFF叠加到底图上,代码如下:
import folium import rasterio imgfile = r"path\to\geotiff" with rasterio.open(imgfile) as dobj: print(dobj.crs) m = folium.Map(location=[38.57456919518837, -121.48348853857401], zoom_start = 9) img = folium.raster_layers.ImageOverlay( image=imgfile, name="I am a jpeg", bounds=[[38.2, -122.3], [39.35, -120]], opacity=1, interactive=True, cross_origin=False, zindex=1) folium.Popup("I am an image").add_to(img) img.add_to(m) folium.LayerControl().add_to(m) m
但输出仅显示边界框细线,内部无图像。已尝试:
- 改用PNG/JPG替代GeoTIFF,结果相同
- 查看栅格值范围为0至311000
- 确认CRS为EPSG:3875(注:实际Web Mercator标准代号为EPSG:3857,疑似笔误)
系统信息:Windows 10、folium v0.14.0、rasterio v1.2.10
问题根源
- folium.ImageOverlay不支持直接读取GeoTIFF路径:它仅接受图像格式数据(numpy数组、本地可访问的图像文件路径/URL),GeoTIFF是栅格数据格式,无法直接被识别为图像。
- 栅格值范围超出图像像素有效范围:你的栅格值是0-311000,而图像像素的有效显示范围是0-255,未做归一化处理会导致图像显示异常(全黑或无内容)。
- 手动设置的bounds与实际栅格范围不匹配:手动输入的边界框可能和GeoTIFF的真实范围存在偏差,导致图像无法正确映射到底图。
修复步骤与代码
核心处理逻辑
- 归一化栅格值到0-255的图像像素范围
- 从GeoTIFF读取数据并转换为folium可识别的numpy数组格式
- 自动获取栅格边界并转换为folium底图使用的WGS84(EPSG:4326)坐标系
修改后的代码:
import folium import rasterio import numpy as np from rasterio.warp import transform_bounds imgfile = r"path\to\geotiff" # 读取并预处理栅格数据 with rasterio.open(imgfile) as dobj: # 确认坐标系为Web Mercator(EPSG:3857),若不是需先转换 assert dobj.crs == "EPSG:3857", "GeoTIFF需为EPSG:3857坐标系" # 读取第一波段数据 data = dobj.read(1) # 归一化栅格值到0-255范围 data_min, data_max = np.min(data), np.max(data) normalized_data = ((data - data_min) / (data_max - data_min)) * 255 normalized_data = normalized_data.astype(np.uint8) # 将栅格边界从EPSG:3857转换为EPSG:4326(folium使用的坐标系) bounds_4326 = transform_bounds( dobj.crs, "EPSG:4326", dobj.bounds.left, dobj.bounds.bottom, dobj.bounds.right, dobj.bounds.top ) # 转换为folium要求的bounds格式:[[south, west], [north, east]] folium_bounds = [[bounds_4326[1], bounds_4326[0]], [bounds_4326[3], bounds_4326[2]]] # 创建地图 m = folium.Map(location=[38.57456919518837, -121.48348853857401], zoom_start=9) # 添加处理后的图像叠加层 img = folium.raster_layers.ImageOverlay( image=normalized_data, name="GeoTIFF Overlay", bounds=folium_bounds, opacity=0.7, # 降低透明度方便查看底图 interactive=True, zindex=1 ) folium.Popup("归一化后的栅格图像").add_to(img) img.add_to(m) folium.LayerControl().add_to(m) m
额外说明
- 若GeoTIFF是多波段(如RGB),需读取多个波段并组合成
(height, width, 3)格式的numpy数组。 - 若原始GeoTIFF坐标系不是EPSG:3857,需先用
rasterio.warp.reproject将数据转换为Web Mercator坐标系后再处理。 - 转换为PNG/JPG格式时,同样需要先归一化数值范围,否则图像会因超出像素范围而显示异常。
内容的提问来源于stack exchange,提问作者Darren C.
相关产品推荐
相关产品推荐

