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

Python 更改plt.imshow()图像像素的颜色,python,matplotlib,Python,Matplotlib,我需要用matplotlib的imshow()绘制一幅图像,然后用不同的颜色标记一些像素。仅仅在初始数组中更改它们的值是行不通的,因为我需要使用我正在使用的颜色映射中不存在的颜色。因此,我最初的意图是在第一幅图像上方绘制第二个生成的数组,其中大部分被遮罩,所需的像素没有被遮罩,并且有一些值(可能不同的值会对不同的坐标使用不同的颜色)。它与matplotlib的交互式查看器配合得很好,但是当保存到文件中时,所有内容都会被扭曲,这可能是因为我在相同的情况下报告了这个bug: 是否有其他选项可以更改某

我需要用matplotlib的imshow()绘制一幅图像,然后用不同的颜色标记一些像素。仅仅在初始数组中更改它们的值是行不通的,因为我需要使用我正在使用的颜色映射中不存在的颜色。因此,我最初的意图是在第一幅图像上方绘制第二个生成的数组,其中大部分被遮罩,所需的像素没有被遮罩,并且有一些值(可能不同的值会对不同的坐标使用不同的颜色)。它与matplotlib的交互式查看器配合得很好,但是当保存到文件中时,所有内容都会被扭曲,这可能是因为我在相同的情况下报告了这个bug:


是否有其他选项可以更改某些像素的颜色

您已经建议了最简单的方法(在顶部覆盖另一个图像),但是如果这不符合您的要求,还有其他选择


方法#1-手动渲染和合成图像
最直接的方法是使用colormap将阵列渲染为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()
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()

此方法的一个缺点是,当您传入预渲染的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

plt.imshow(rgba, interpolation='nearest')
plt.show()
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()

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

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()

方法2-滥用
设置错误
设置在上方
,或
设置在下方

colormap的
set_bad
set_over
set_under
方法允许您标记为NaN或超出colormap指定范围的像素

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

如果您有一个整数数组或已经需要透明的NaN像素,您可以类似地滥用
set_over
set_over
。在这种情况下,您需要在调用
imshow
时手动指定
vmin
vmax

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

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()

与第一种方法相比,这种方法的一个优点是绘制颜色条稍微容易一些。(缺点是这种方法灵活性差得多。):


为了补充Joe非常好的回答,当向
imshow
提供rgba值数组时,鼠标光标读取的z值现在显示rgba值的元组,而不是原始
数据

为了解决这个问题,我们可以在原始图像上覆盖一个透明图像。 然后,我们可以同时使用此透明图像将颜色条附加到图形上:

import numpy as np
import matplotlib.pyplot as plt

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()

乔,谢谢你的建议,它们看起来很合理。在这些情况下,这些像素会显示在颜色栏上吗?我不需要它们。在尝试了第一个选项后,我发现颜色条和整个图像的颜色都受到了很大的影响。这可能是因为在渲染到rgb后,值的范围仅下降到(0,1),至少我在颜色栏的标签上看到了这一点,而且我以前有一个更大的范围。因此,图像的某些部分的颜色变得难以区分,尽管如果我在原始数据上调用imshow(),它们明显不同。并且使用
set_bad
set_下的
set_和
set_上的
不是一个很好的选择,因为我希望能够用不同的颜色标记不同的像素,这就把它们的数量限制在3个。我可能还需要将
vmin
vmax
用于其他目的。默认情况下,添加的颜色不会显示在颜色栏上。然而,为第一种方法制作一个颜色条需要几个额外的步骤,而第二种方法则不需要做任何额外的事情。哦,如果我按照你对第一种方法的建议进行标准化,那么我会得到一个蓝色的方块,而不是我的图像,没有它看起来更像应该的样子。