更改plt.imshow()图像的像素颜色

时间:2014-11-01 20:33:33

标签: python matplotlib

我需要使用matplotlib的imshow()绘制图像,然后用不同的颜色标记一些像素。只是在初始数组中更改它们的值不会起作用,因为我需要使用我正在使用的颜色映射中不存在的颜色。所以我最初的目的是在第一个图像上方绘制第二个生成的数组,其中大部分都被屏蔽,所需的像素没有被屏蔽,并且有一些值(对于不同的坐标可能使用不同的颜色可能不同)。它可以很好地与matplotlib的交互式查看器配合使用,但是当保存到文件中时,一切都会因为这个错误而被扭曲,我在同样的情况下报告了这个错误:https://github.com/matplotlib/matplotlib/issues/3057

还有其他选项可以改变某些像素的颜色吗?

2 个答案:

答案 0 :(得分:8)

你已经建议了最简单的方法(在顶部覆盖另一个图像),但是如果它不能按照你想要的方式工作,还有其他选择。


方法#1 - 手动渲染和合成图像


最直接的方法是使用色彩映射将数组渲染为RGB,然后更改所需的像素。

作为一个简单的例子:

import numpy as np
import matplotlib.pyplot as plt

data = np.arange(100).reshape(10, 10)

cmap = plt.cm.gray
norm = plt.Normalize(data.min(), data.max())
rgba = cmap(norm(data))

# Set the diagonal to red...
rgba[range(10), range(10), :3] = 1, 0, 0

plt.imshow(rgba, interpolation='nearest')
plt.show()

enter image description here

此方法的一个缺点是,当您传入预渲染的rgb图像时,不能只调用fig.colorbar(im)。因此,如果您需要彩条,则必须使用代理艺术家。最简单的方法是使用imshow(data, visible=False)添加一个额外的,不可见的(未绘制的,而不是透明的)艺术家,然后将该颜色图作为该艺术家的基础。作为一个简单的例子:

import numpy as np
import matplotlib.pyplot as plt

data = np.arange(100).reshape(10, 10)

cmap = plt.cm.gray
norm = plt.Normalize(data.min(), data.max())
rgba = cmap(norm(data))

# Set the diagonal to red
rgba[range(10), range(10), :3] = 1, 0, 0

fig, ax = plt.subplots()
ax.imshow(rgba, interpolation='nearest')

# Add the colorbar using a fake (not shown) image.
im = ax.imshow(data, visible=False, cmap=cmap)
fig.colorbar(im)

plt.show()

enter image description here

使用不可见的imshow是为此目的制作代理艺术家的最简单方法,但如果速度是一个问题(或者如果它以某种方式触发你提到的渲染错误),你也可以使用任何{{1 }}。 ScalarMappable是一个抽象基类,通常只用于继承colorbar支持。因为我们不需要绘制任何东西,所以我们可以直接使用它。

ScalarMappable

方法#2 - 滥用import numpy as np import matplotlib.pyplot as plt from matplotlib.cm import ScalarMappable data = np.arange(100).reshape(10, 10) cmap = plt.cm.gray norm = plt.Normalize(data.min(), data.max()) rgba = cmap(norm(data)) # Set the diagonal to red rgba[range(10), range(10), :3] = 1, 0, 0 fig, ax = plt.subplots() ax.imshow(rgba, interpolation='nearest') # Add the colorbar using a ScalarMappable im = ScalarMappable(norm, cmap) im.set_array(data) fig.colorbar(im) plt.show() set_badset_over


色彩映射的set_underset_badset_over方法允许您标记NaN或像色图的指定范围之外的像素。

因此,另一种做你想要的方法是将这些值设置为NaN并指定NaN颜色应该是什么(set_under。默认情况下,它对大多数色彩图都是透明的。)。

如果您有整数数组或者需要具有透明的NaN像素,则可以同样滥用set_badset_over。在这种情况下,您需要在致电set_under时手动指定vminvmax

作为使用/滥用imshow执行此操作的快速示例:

set_bad

enter image description here

这种方法相对于第一种方法的一个优点是绘制颜色条更容易一些。 (缺点是这种方法不够灵活。):

import numpy as np
import matplotlib.pyplot as plt

data = np.arange(100).reshape(10, 10).astype(float)

cmap = plt.cm.gray
cmap.set_bad((1, 0, 0, 1))

# Set the diagonal to NaN
data[range(10), range(10)] = np.nan

plt.imshow(data, cmap=cmap, interpolation='nearest')
plt.show()

enter image description here

答案 1 :(得分:0)

为给Joe带来一个很好的答案,当向imshow提供rgba值数组时,鼠标光标读取的z值现在显示rgba值的元组,而不是原始的data值。

要解决此问题,我们可以将透明图像叠加到原始图像上。 然后,我们可以同时使用此透明图像将彩条附加到图形上:

import numpy as np
import matplotlib.pyplot as np

fig, ax = plt.subplots()

data = np.arange(100).reshape(10, 10)

cmap = plt.cm.gray
norm = plt.Normalize(data.min(), data.max())
rgba = cmap(norm(data))

# Set the diagonal to red...
rgba[range(10), range(10), :3] = 1, 0, 0

im = ax.imshow(rgba, interpolation='nearest')
im2 = ax.imshow(data, cmap='gray')
cbar = plt.colorbar(im2, ax=ax)
im2.set_alpha(0.0)

请注意,在这种情况下,在调用im2.set_alpha(0.0)之前创建颜色栏很重要。 如果不是,则颜色栏中的颜色也将是透明的(它们遵循图像的当前alpha)。

在无法遵守创建顺序的情况下,可以使用以下方法将颜色栏中颜色的不透明度设置回1。

cbar.set_alpha(1.0)
cbar.draw_all()