如何用Python的LightSource让两张邻接地图保持一致着色(保留垂直夸张)
解决LightSource垂直夸张时相邻影像着色不一致的问题
问题核心:两张相邻的地图影像,使用相同参数的LightSource.shade()处理时,vert_exag=0.05会导致边缘着色不一致;vert_exag=0时衔接正常但丢失地形细节,需要在保留垂直夸张的同时实现无缝着色。
问题原因
LightSource.shade()计算地形阴影时,依赖局部像素邻域的梯度模拟光照效果。单张影像的边缘区域(比如第一张图的右边缘、第二张图的左边缘)没有完整的邻域数据(缺少相邻影像的像素),导致梯度计算偏差,最终阴影和着色出现接缝。当vert_exag=0时,梯度计算被忽略,仅做颜色映射,因此衔接正常,但地形细节丢失。
解决方案:合并影像后统一计算阴影
最可靠的方法是先将两张相邻影像拼接成完整的整体,统一计算阴影和着色,再拆分回原影像。这样边缘区域的梯度计算会用到完整的邻域数据,确保阴影效果一致。
修改后的代码
import numpy as np import rasterio from matplotlib import cm from matplotlib.colors import ListedColormap, LinearSegmentedColormap, LightSource import matplotlib.pyplot as plt # 读取影像数据 with rasterio.open("image_1.tiff", 'r') as ds: z1 = ds.read()[0,:,:] # 直接提取第一个波段 with rasterio.open("image_2.tiff", 'r') as ds: z2 = ds.read()[0,:,:] # 配置参数 vmin = -12000 vmax = 9000 vert_exag = 0.05 blend_mode = 'soft' # 创建自定义色带 cmap_ocean = cm.ocean.copy() ocean = cmap_ocean(np.linspace(0.30, 0.85, 144)) colors = [ (0.00, 'palegoldenrod'), (0.05, 'burlywood'), (0.30, 'sienna'), (0.50, 'tan'), (0.70, 'snow'), (1.00, 'white'), ] cmap_land = LinearSegmentedColormap.from_list('cm', colors) land = cmap_land(np.linspace(0, 1, 108)) cmap = ListedColormap(np.concatenate((ocean, land))) # 合并两张影像(假设横向相邻,axis=1;纵向相邻请改为axis=0) z_combined = np.concatenate((z2, z1), axis=1) # 统一计算阴影和着色 light = LightSource(azdeg=45, altdeg=45) rgb_combined = light.shade( z_combined, cmap=cmap, blend_mode=blend_mode, vert_exag=vert_exag, vmin=vmin, vmax=vmax ) # 处理透明区域 rgb_combined[:,:,-1][np.isnan(z_combined)] = 0 rgb_combined = np.uint8(rgb_combined * 255) # 拆分回原影像 rgb2 = rgb_combined[:, :z2.shape[1], :] rgb1 = rgb_combined[:, z2.shape[1]:, :] # 拼接显示验证 rgb3 = np.concatenate((rgb2, rgb1), axis=1) plt.figure() plt.imshow(rgb3) plt.axis('off') plt.show()
关键修改说明
- 先合并后处理:将
z1和z2拼接成z_combined,确保边缘区域有完整的邻域像素用于梯度计算。 - 统一着色后拆分:对合并后的影像一次性计算阴影,再拆分回原尺寸,保证两张影像的边缘着色完全一致。
- 简化数据读取:直接在读取时提取第一个波段,减少冗余变量。
可选替代方案(适用于无法合并影像的场景)
如果因内存或坐标对齐问题无法合并影像,可以手动扩展每张影像的边缘:
- 从
z1中取左边缘的N列像素,追加到z2的右边缘; - 从
z2中取右边缘的N列像素,追加到z1的左边缘; - 分别处理扩展后的影像,再裁剪回原尺寸。
这种方法需要精确匹配边缘像素,实现复杂度高于合并方案,优先推荐第一种方法。
内容的提问来源于stack exchange,提问作者Marcus K.
相关产品推荐
相关产品推荐

