繁体   English   中英

使用 matplotlib imshow 绘制分类栅格数据 - 如何正确获取 colors

[英]Plotting categorical raster data with matplotlib imshow - how to get colors right

我正在尝试使用 plt.imshow() plot 光栅图像“test_img.tif”。 这是一张土地覆盖图像,每个唯一值都是不同的土地覆盖 class。问题是 cmap 似乎没有正确设置 colors,因为我正在使用 ListedColormap 创建自定义 cmap。 尽管 plot 图例绘制正确,但 colors 并非如此。

(图片在这里https://drive.google.com/file/d/1aN95UnYmw52GHW017sbfcf4JDSWHIou4/view?usp=sharing

我正在使用以下代码:

## Loading TIF file
import rioxarray as rxr
data_path = 'folder/test_img.tif'
lctif_1km_20530 = rxr.open_rasterio(data_path, masked=True).squeeze()
lctif_1km_20530 = lctif_1km_20530.astype('int')

### Getting unique classes from array and setting color and legend list
import numpy as np

classes_20530 = list(np.unique(lctif_1km_20530).astype('int'))
color_list_20530 = ['#FAF5E4', '#006400', '#45C2A5', '#B8AF4F', '#fff3bf', '#0000FF']
class_names_20530 = ['Out of buffer','Forest Formation','Wetlands','Grassland', 'Mosaic Agriculture and Pasture','River, Lake and Ocean']

# Plot newly classified and masked raster
import matplotlib.pyplot as plt
import earthpy.plot as ep
from matplotlib.colors import ListedColormap

cmap_20530 = ListedColormap(color_list_20530)
f, ax = plt.subplots(figsize=(10,5))
im = ax.imshow(lctif_1km_20530, cmap = cmap_20530)
ax.set(title="Landcover classes")
ep.draw_legend(im, titles = class_names_20530, classes = classes_20530)
ax.set_axis_off()
plt.show()

我在 QGIS 中创建了预期的 output 图像(渲染类型:调色板/唯一值)以进行比较:

方法比较

有谁能够帮我? 非常感谢。

我遇到了同样的问题并解决了 8 土地使用 class 可视化。 在您的示例中,土地覆盖 class 森林缺失,这就是颜色映射错误的原因。

# get np with shape of matplotlib cms, here I use viridis.
cm_solution_map = viridis(np.linspace(0, 1, 256))
#define rgba of you landclasses
cropland_1 = np.array([256 / 256, 246 / 256, 143 / 256, 1])
cropland_2 = np.array([238 / 256, 230 / 256, 133 / 256, 1])
cropland_3 = np.array([256 / 256, 215 / 256, 1 / 256, 1])
cropland_4 = np.array([238 / 256, 201 / 256, 0 / 256, 1])
cropland_5 = np.array([205 / 256, 173 / 256, 1 / 256, 1])
pasture = np.array([162 / 256, 205 / 256, 90 / 256, 1])
forest = np.array([34 / 256, 139 / 256, 34 / 256, 1])
urban = np.array([105 / 256, 105 / 256, 105 / 256, 1])
# identify whether or not the landclasses occour in your map. This can be done more elegant in a loop, but for readability I didn't do it
        if 1. in solution_landuse_map:
        plot_cropland_1 = True
        nr_classes += 1
    else:
        plot_cropland_1 = False

    if 2. in solution_landuse_map:
        plot_cropland_2 = True
        nr_classes += 1
    else:
        plot_cropland_2 = False

    if 3. in solution_landuse_map:
        plot_cropland_3 = True
        nr_classes += 1
    else:
        plot_cropland_3 = False

    if 4. in solution_landuse_map:
        plot_cropland_4 = True
        nr_classes += 1
    else:
        plot_cropland_4 = False

    if 5. in solution_landuse_map:
        plot_cropland_5 = True
        nr_classes += 1
    else:
        plot_cropland_5 = False
    if 6. in solution_landuse_map:
        plot_forest = True
        nr_classes += 1
    else:
        plot_forest = False
    if 7. in solution_landuse_map:
        plot_pasture = True
        nr_classes += 1
    else:
        plot_pasture = False
    if 8. in solution_landuse_map:
        plot_urban = True
        nr_classes += 1
    else:
        plot_urban = False
#now you can update your colormap array. Again, you can do it in a loop and more elegant.
class_counter = 0
    rgb_interval = int(256 / nr_classes)+1
    if plot_cropland_1:
        cm_solution_map[(rgb_interval * class_counter):(rgb_interval * (class_counter + 1)), :] = cropland_1
        class_counter += 1
    if plot_cropland_2:
        cm_solution_map[(rgb_interval * class_counter):(rgb_interval * (class_counter + 1)), :] = cropland_2
        class_counter += 1
    if plot_cropland_3:
        cm_solution_map[(rgb_interval * class_counter):(rgb_interval * (class_counter + 1)), :] = cropland_3
        class_counter += 1
    if plot_cropland_4:
        cm_solution_map[(rgb_interval * class_counter):(rgb_interval * (class_counter + 1)), :] = cropland_4
        class_counter += 1
    if plot_cropland_5:
        cm_solution_map[(rgb_interval * class_counter):(rgb_interval * (class_counter + 1)), :] = cropland_5
        class_counter += 1
    if plot_forest:
        cm_solution_map[(rgb_interval * class_counter):(rgb_interval * (class_counter + 1)), :] = forest
        class_counter += 1
    if plot_pasture:
        cm_solution_map[(rgb_interval * class_counter):(rgb_interval * (class_counter + 1)), :] = pasture
        class_counter += 1
    if plot_urban:
        cm_solution_map[(rgb_interval * class_counter):(256), :] = urban
        class_counter += 1

    cmp_solution_map = ListedColormap(cm_solution_map)
# now, you can use this cmap in ax.imshow as cmap argument

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM