30

我正在尝试使用 matplotlib 为我正在研究的论文绘制一些数字。我在 2D numpy 数组中有两组数据: 一个 ascii 山体阴影栅格,我可以很高兴地使用它来绘制和调整:

import matplotlib.pyplot as pp
import numpy as np

hillshade = np.genfromtxt('hs.asc', delimiter=' ', skip_header=6)[:,:-1]

pp.imshow(hillshade, vmin=0, vmax=255)
pp.gray()
pp.show()

这使:

山体阴影

第二个 ascii 栅格描绘了流经景观的河流的特性。可以以与上述相同的方式绘制此数据,但是数组中与河网不对应的值被指定为 -9999 的无数据值。目的是将无数据值设置为透明的,以便河流值覆盖山体阴影。

这是河流数据,理想情况下,这里表示为 0 的每个像素都是完全透明的。

河流数据

对此进行了一些研究后,似乎我可以将我的数据转换为 RGBA 数组并设置 alpha 值以仅使不需要的单元格透明。但是,河流数组中的值是浮点数,无法转换(因为原始值是图中的全部点),我相信imshow如果使用 RGBA 格式,该函数只能采用无符号整数。

有没有办法绕过这个限制?我曾希望我可以简单地创建一个带有像素值和 alpha 值的元组并像那样绘制它们,但这似乎是不可能的。

我还PIL尝试创建一个没有数据值透明的河流数据的 PNG 文件,但这似乎会自动将像素值缩放到 0-255,从而丢失我需要保留的值。

我欢迎任何人对这个问题有任何见解。

4

3 回答 3

51

只需掩盖您的“河流”阵列。

例如

rivers = np.ma.masked_where(rivers == 0, rivers)

作为以这种方式覆盖两个图的快速示例:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm

# Generate some data...
gray_data = np.arange(10000).reshape(100, 100)

masked_data = np.random.random((100,100))
masked_data = np.ma.masked_where(masked_data < 0.9, masked_data)

# Overlay the two images
fig, ax = plt.subplots()
ax.imshow(gray_data, cmap=cm.gray)
ax.imshow(masked_data, cmap=cm.jet, interpolation='none')
plt.show()

在此处输入图像描述

此外,附带说明一下,imshow它会很乐意接受其 RGBA 格式的浮点数。它只是期望一切都在 0 和 1 之间。

于 2013-06-18T13:46:58.373 回答
18

不使用掩码数组的另一种方法是设置颜色映射如何处理低于最小值的剪切值clim(无耻地使用 Joe Kington 的示例):

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm

# Generate some data...
gray_data = np.arange(10000).reshape(100, 100)

masked_data = np.random.random((100,100))

my_cmap = cm.jet
my_cmap.set_under('k', alpha=0)


# Overlay the two images
fig, ax = plt.subplots()
ax.imshow(gray_data, cmap=cm.gray)
im = ax.imshow(masked_data, cmap=my_cmap, 
          interpolation='none', 
          clim=[0.9, 1])
plt.show()

例子

还有一个set_over用于裁剪顶部和一个set_bad用于设置颜色映射如何处理数据中的“坏”值。

这样做的一个好处是你可以通过调整来改变你的阈climim.set_clim([bot, top])

于 2013-06-18T21:04:48.840 回答
1

另一种选择是设置所有应保持透明的单元格np.nan(不确定这里的效率更高,我猜tacaswell的答案clim是fastet)。改编乔金顿的答案的例子:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm

# Generate some data...
gray_data = np.arange(10000).reshape(100, 100)

masked_data = np.random.random((100,100))
masked_data[np.where(masked_data < 0.9)] = np.nan

# Overlay the two images
fig, ax = plt.subplots()
ax.imshow(gray_data, cmap=cm.gray)
ax.imshow(masked_data, cmap=cm.jet, interpolation='none')
plt.show()

在此处输入图像描述

请注意,对于dtype=bool您的数组,不应该遵循 IDE 的建议来比较masked_data is TruePEP 8 (E712),而是坚持按masked_data == True元素进行比较,否则屏蔽将失败: 在此处输入图像描述

于 2021-02-08T17:18:41.817 回答