You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为栅格数据中的特定地类分配固定对应颜色

土地利用栅格可视化:地类与颜色匹配错误的解决方法

问题背景

我需要展示某区域的土地利用类型,现有多个包含地类信息的栅格文件,每个像素值对应特定地类。已定义地类值、对应颜色及文本标签:

from matplotlib.colors import ListedColormap
import rasterio
import numpy as np
import earthpy.plot as ep
import matplotlib.pyplot as plt

cmap_values = [0, 11, 22, 33, 40, 55, 66, 77]
cmap_colors = ['white', ## 0: 无数据
               'black', ## 11: 城镇用地
               'darkorange', ## 22: 耕地
               'brown', ## 33: 牧场
               'darkgreen', ## 40: 林地
               'purple', ## 55: 草地/灌丛
               'gray', ## 66: 其他土地
               'blue'  ## 77: 水域
              ] 
cmap = ListedColormap(cmap_colors)
value_text = ['无数据', '城镇用地', '耕地', '牧场', 
             '林地', '草地/灌丛', 
             '其他土地', '水域']

但部分栅格文件缺少部分地类,例如某栅格的唯一像素值为:

src = rasterio.open('myFile.tif')
data = src.read(1)
print(np.unique(data))
# 输出:array([11, 22, 33, 40, 55, 77], dtype=uint8)

使用以下代码可视化时,颜色与地类对应错误(如城镇用地被显示为白色):

f, ax = plt.subplots()
im = ax.imshow(data, cmap=cmap)
ep.draw_legend(im, titles=value_text, classes=cmap_values)

解决方案

问题根源是ListedColormap按索引匹配颜色,而imshow会自动将数据的最小值映射到色图第一个颜色、最大值映射到最后一个,导致缺失地类时颜色错位。需明确指定数值与颜色的对应关系,以下是两种可行方法:

方法1:用BoundaryNorm绑定数值与颜色

通过BoundaryNorm定义每个地类值的区间,确保特定数值对应固定颜色,不受数据缺失影响:

from matplotlib.colors import BoundaryNorm
from matplotlib.patches import Patch

# 为每个地类值创建边界区间(避免数值落在区间外)
bounds = [val - 0.5 for val in cmap_values] + [cmap_values[-1] + 0.5]
# 创建Norm对象,绑定边界与色图
norm = BoundaryNorm(bounds, cmap.N)

# 可视化时传入norm参数
f, ax = plt.subplots()
im = ax.imshow(data, cmap=cmap, norm=norm)

# 筛选当前数据存在的地类,生成对应图例
present_values = np.unique(data)
present_indices = [cmap_values.index(val) for val in present_values]
legend_elements = [
    Patch(facecolor=cmap_colors[i], label=value_text[i]) 
    for i in present_indices
]
ax.legend(handles=legend_elements, loc='lower right', bbox_to_anchor=(1.2, 0))

plt.show()

这种方法适合需要统一所有栅格颜色规则,或保留完整地类体系的场景。

方法2:过滤色图与标签,仅保留存在的地类

如果只需要展示当前栅格存在的地类,可先筛选对应颜色和标签,再创建新色图:

# 获取当前数据包含的地类值
present_values = np.unique(data)
# 匹配对应的颜色和文本标签
filtered_colors = [cmap_colors[cmap_values.index(val)] for val in present_values]
filtered_texts = [value_text[cmap_values.index(val)] for val in present_values]
# 创建仅包含当前地类的色图
filtered_cmap = ListedColormap(filtered_colors)

# 可视化并绘制对应图例
f, ax = plt.subplots()
im = ax.imshow(data, cmap=filtered_cmap)
ep.draw_legend(im, titles=filtered_texts, classes=present_values)

plt.show()

该方法更简洁,适合聚焦当前栅格地类的场景。


内容的提问来源于stack exchange,提问作者emax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 15:55:01