使用imshow绘制GeoTIFF时无法正确定义颜色映射
解决GeoTIFF离散类别颜色绘制不符的问题
核心原因
imshow默认会对栅格数据做自动归一化处理,将数据的最小值到最大值线性映射到色图的0-1范围,这会导致你的离散类别值被错误拉伸,无法对应预设的颜色。此外,颜色格式不匹配、插值方式不当也会导致颜色显示异常。
分步解决方案
1. 确认颜色格式
Matplotlib只接受0-1范围的RGB浮点数,如果你的flag_colors是0-255的整数,必须先转换:
# 示例:将(255, 200, 100)转换为(1, 0.784, 0.392) flag_colors = [(r/255, g/255, b/255) for r, g, b in flag_colors]
2. 创建离散色图与归一化规则
使用ListedColormap绑定类别与颜色,配合BoundaryNorm强制每个类别值对应唯一颜色:
import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap, BoundaryNorm from georaster import Raster # 读取栅格数据 raster = Raster("your_landuse.tif") data = raster.raster[0] # 取单波段数据 extent = raster.extent # 你的类别值与对应颜色 class_values = [10, 11, 12, 20, 30, 40, 50, 60, 61, 62, 70, 90, 100, 110, 120, 122, 130, 150, 153, 160, 170, 180, 190, 200, 210, 220] # 替换为你实际的颜色数组(确保顺序与class_values完全对应) flag_colors = [ (0.96, 0.96, 0.86), (0.90, 0.70, 0.70), (0.80, 0.00, 0.00), (0.90, 0.90, 0.90), (0.60, 0.60, 0.60), (0.80, 0.80, 0.80), (0.00, 0.60, 0.00), (0.00, 0.80, 0.00), (0.50, 0.70, 0.50), (0.30, 0.70, 0.30), (0.70, 0.90, 0.70), (0.80, 0.60, 0.80), (0.90, 0.70, 0.90), (0.90, 0.90, 0.00), (0.70, 0.70, 0.00), (0.90, 0.90, 0.50), (0.50, 0.50, 0.00), (0.90, 0.50, 0.00), (0.90, 0.70, 0.50), (1.00, 0.00, 0.00), (0.70, 0.00, 0.00), (0.50, 0.00, 0.00), (0.90, 0.90, 0.90), (0.60, 0.60, 0.60), (0.80, 0.80, 0.80), (0.00, 0.00, 0.80) ] # 转换颜色格式(如果是0-255的整数) flag_colors = [(r/255, g/255, b/255) for r, g, b in flag_colors] # 创建自定义色图 cmap = ListedColormap(flag_colors) # 生成边界值:每个类别值的±0.5,确保每个值被单独划分 bounds = [val - 0.5 for val in class_values] + [class_values[-1] + 0.5] norm = BoundaryNorm(bounds, cmap.N)
3. 正确绘制栅格
关闭自动归一化,使用最近邻插值避免颜色混合:
plt.figure(figsize=(12, 10)) # 绘制时指定cmap、norm,禁用插值混合 im = plt.imshow(data, extent=extent, cmap=cmap, norm=norm, interpolation="nearest") # 添加对应类别的颜色条 cbar = plt.colorbar(im, ticks=class_values) # 可选:添加类别名称标签(替换为你的土地利用类型名称) cbar.ax.set_yticklabels([ "耕地", "水浇地", "旱地", "林地", "灌木林", "疏林地", "其他林地", "高覆盖草地", "中覆盖草地", "低覆盖草地", "河渠", "湖泊", "水库坑塘", "永久性冰川雪地", "滩涂", "滩地", "城镇用地", "农村居民点", "工矿用地", "沙地", "戈壁", "盐碱地", "沼泽地", "裸土地", "裸岩石质地", "其他" ]) plt.title("CS3土地利用子集") plt.show()
关键检查点
- 确认
class_values与flag_colors的顺序完全一一对应,没有错位。 - 确保颜色值是0-1范围的浮点数,而非0-255的整数。
- 必须使用
BoundaryNorm,否则imshow会自动归一化数据,破坏离散类别的颜色映射。 - 选择
interpolation="nearest",避免相邻像素颜色被插值混合。
内容的提问来源于stack exchange,提问作者Anthony Bernal Ayala
相关产品推荐
相关产品推荐

