Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 730
mwaskom Avatar asked Aug 01 '14 21:08

mwaskom


Video Answer


1 Answers

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.

like image 70
Dan Allan Avatar answered Oct 19 '22 12:10

Dan Allan