【问题标题】:How does imshow handle the alpha channel with an M x N x 4 input?imshow 如何处理具有 M x N x 4 输入的 alpha 通道?
【发布时间】:2014-08-01 21:39:20
【问题描述】:

GH问题#3343


我正在使用 matplotlib 中的 imshow 函数来可视化一些数据。我有两个数组,AB,它们的大小相同。我想使用颜色图在 A 中显示标量值,我想使用 alpha 通道在 B 中显示标量值。换句话说,如果 AB 中给定坐标处的值很大,则图中的像素将是亮绿色且不透明。如果它在 A 而不是 B 中很大,那么它将是亮绿色但大部分是透明的。如果它在 B 而不是 A 中很大,那么它将是不透明的,而是白色的。

但是,生成的图像不是我所期望的。我的输入数据称为d,它是通过将 A 数组与 matplotlib 颜色映射(即mpl.cm.BuGn(A))和 B em> 数组。

在这里,我将绘制完整的图像(我想要实际使用的)、RGB 图像(A,使用BuGn 映射)和提供 alpha 的数组(B,带有灰度颜色图)。

f, (ax0, ax1, ax2) = plt.subplots(1, 3, figsize=(5, 2.5))

ax0.imshow(d)
ax1.imshow(d[..., :-1])
ax2.imshow(d[..., -1])

我对完整图像中的斑点灰色垃圾的来源感到困惑,因为颜色图中没有任何值是这些颜色。为了更显着地显示这种效果,我可以更改颜色图的边界,使它们远离数据的极端并重新绘制:

我不明白为什么具有较大 alpha 值的白色像素会显示为灰色。不透明的白色应该仍然是白色的。

请注意,此行为与我绘制 RGB 组件数组并使用 alpha kwarg 降低透明度(即 ax2.imshow(d[..., :-1], alpha=.3))不同:

【问题讨论】:

标签: python matplotlib


【解决方案1】:

古老的ballsdotballs修改后的答案似乎是合理的。从那个邮件列表帖子中,看起来处理 alpha 值没有经过仔细考虑。此外,从原始帖子中的示例来看,在我看来,imshow 中的 alpha arg 的合成方式与 RGBA 数据中提供的 alpha 数字不同。

要解决 Agg 正在执行的任何混合操作,可以避免 alpha 并手动进行合成。

A = np.tile(np.linspace(0, 1, num=100), (100, 1))  # gradient
B = A.T
d = plt.cm.BuGn(A)
d[..., -1] = B

composite = (d[..., :-1] * d[..., -1].reshape(100, 100, 1) +
    (1 - d[..., -1]).reshape(100, 100, 1))

fig, axes = plt.subplots(1, 2)
axes[0].imshow(d)
axes[1].imshow(composite)

我确信有更好的方法来进行重塑,但这不是这里的问题。

【讨论】:

  • 这回答了提出的问题;可悲的是,我实际上需要 alpha,因为我希望能够在 B 较低的区域(大脑)看到背景图像。但这告诉我我必须采取不同的策略。
  • 我猜你可以像我在这里隐式合成一个 1 的数组一样合成图像。
【解决方案2】:

我的第一个答案完全错误,所以这是我的新尝试。

DaveAllen 的上述评论准确地再现了该问题。

import numpy as np
import matplotlib.pyplot as plt

d = np.ones((100, 100, 4), dtype=np.uint8)*255
d[:, :, 3] = np.linspace(0, 255, num=100)
plt.imshow(d, interpolation='none')
plt.show()

产生:

您会期望具有可变 alpha 的白色背景上的白色图像是完全白色的。 “直接” alpha 就是这种情况。

似乎 matlplotlib 的图形后端正在显示图像,假设“预乘”alpha,这意味着 alpha 会影响图像的颜色。这可以解释上图。

http://en.wikipedia.org/wiki/Alpha_compositing http://blogs.msdn.com/b/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx https://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg22377.html

(1.0,1.0,1.0,0.5) 的像素在显示时,其颜色首先乘以其 Alpha 通道,因此它们显示为 (0.5,0.5,0.5,0.5),灰色。

右边的像素是不透明的白色的,所以它们看起来是白色的。左侧的像素显示为黑色和透明,因此它们看起来与背景颜色相同,即白色。

中间的像素是灰色的,因为它们既不显示白色也不透明。

【讨论】:

  • 我认为这不太对,因为如果你这样做ax.imshow(d[..., :-1]], alpha=0.3),你看不到同样的东西。我已经编辑了问题以显示结果以及它与完整图像的对比。
  • @mwaskom:是的,您会看到这种行为,因为 matplotlib 中的轴背景是白色的。使用 fig.axes[0].set_axis_bgcolor("black") 将轴颜色更改为黑色,您会明白我的意思。
  • 我看不出这与上面的图之间的差异有什么关系。轴背景都是白色的。
  • 我没有在这里投反对票,但我很确定你的粗体陈述是错误的。在我曾经使用过的每个成像程序中,alpha 0 的白色像素都是透明的,而不是黑色的。而且背景是白色的。
  • 所以这个解释更有意义,但它并不能完全解释为什么 ax.imshow(..., alpha=.3) 看起来不错,但向图像添加 alpha 通道却没有。预乘行为是否可配置?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-18
  • 1970-01-01
  • 1970-01-01
  • 2013-12-27
  • 2022-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多