How does imshow handle the alpha channel with an M x N x 4 input?

只愿长相守 提交于 2021-02-06 10:59:45

问题


GH issue #3343


I am using the imshow function in matplotlib to visualize some data. What I have are two arrays, A and B, that are the same size. I would like to use a colormap to show scalar values in A, and I would like to use the alpha channel to show the scalar values in B. In other words, if the value at a given coordinate in both A and B is large, then the pixel in the plot will be bright green and opaque. If it is large in A and not B, then it will be bright green but mostly transparent. And if it is large in B and not A, then it will be opaque but white.

However, the resulting image is not what I am expecting. My input data is called d, and it is a combination of the RGB values that result from mapping the A array with a matplotlib colormap (i.e. mpl.cm.BuGn(A)) and the B array.

Here I'm going to plot the full image (what I want to actually use), the RGB image (A, mapped with BuGn), and the alpha-providing array (B, with a grayscale colormap).

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

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

enter image description here

I am confused about where the splotchy gray junk in the full image is coming from, since there aren't any values in the colormap that are those colors. To show this effect more dramatically, I can change the bounds of the colormap so they are far away from the extremes of the data and re-plot:

enter image description here

I don't understand why pixels that are white with a large alpha value show up as gray. Opaque white should still be white.

Note that this behavior is different than if I plot the RGB component array and lower the transparancy with the alpha kwarg, i.e. ax2.imshow(d[..., :-1], alpha=.3):

enter image description here


回答1:


My first answer was completely wrong, so here's my new attempt.

DaveAllen's comment above accurately reproduces the issue.

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

Produces: enter image description here

You would expect a white image on a white background with variable alpha to be completely white. And that would be the case with "straight" alpha.

It would seem that matlplotlib's graphics backend is displaying the image assuming "premultiplied" alpha, which means that the alpha affects the color of the image. This would explain the image above.

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

Pixels that are (1.0,1.0,1.0,0.5), when displayed, have their color first multiplied by their alpha channel, so they appear (0.5,0.5,0.5,0.5), gray.

The pixels on the right are opaque and white, so they appear white. The pixels on the left are displayed black and transparent so they appear the same as the background color, which is white.

The pixels in the middle are grey because they are displayed neither white nor transparent.




回答2:


The revised answer by the venerable ballsdotballs seems plausible. From that mailing list post, it looks like handling of alpha values was not carefully thought out. Further, from the example in the original post, it seems to me that the alpha arg in imshow is composited differently than alpha numbers provided in RGBA data.

To work around whatever blending Agg is doing, one could avoid alpha and do the compositing manually.

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)

enter image description here

I'm sure there's a better way to do the reshaping, but that's not the issue here.



来源:https://stackoverflow.com/questions/25089068/how-does-imshow-handle-the-alpha-channel-with-an-m-x-n-x-4-input

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!