-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[Bug]: alpha array-type not working with RGB image in imshow() #26092
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Here is an example without import numpy as np
import matplotlib.colors as mcolors
import matplotlib.pyplot as plt
arr = np.random.random((10, 10))
cmap = plt.get_cmap('gray')
norm = mcolors.Normalize()
arr_rgb = cmap(norm(arr))[:, :, :3]
alpha = np.ones_like(arr)
alpha[:5] = 0.2
plt.subplot(121)
plt.title("Expected outcome")
plt.imshow(arr, alpha=alpha, cmap='gray')
plt.subplot(122)
plt.title("Actual outcome")
plt.imshow(arr_rgb, alpha=alpha)
plt.show() I get this with both v3.7.1 and The docstring for |
hello @rcomer, |
This is a bug. I suspect that when we implemented the "alapha-as-array" we forgot about the RGB(A) case. |
Yeah, the issue is in matplotlib/lib/matplotlib/image.py Lines 553 to 576 in dbc906a
#14889 is where this feature came in and where we picked up the explicit call to That said, I think the fix is to add logic to matplotlib/lib/matplotlib/image.py Lines 557 to 558 in dbc906a
I suspect that we have the same bug in matplotlib/lib/matplotlib/image.py Line 580 in dbc906a
matplotlib/lib/matplotlib/image.py Lines 554 to 556 in dbc906a
I am going to label this as good first issue as it is a clear bug (array alpha should work with RGB input). I would say this is a medium difficulty because the image processing code is a bit complicated. Most of that complexity is there for a good reason so be prepared to understand a majority of the The patch: diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py
index 135934a244..0ca26bdabf 100644
--- a/lib/matplotlib/image.py
+++ b/lib/matplotlib/image.py
@@ -553,9 +553,11 @@ class _ImageBase(martist.Artist, cm.ScalarMappable):
else:
if A.ndim == 2: # _interpolation_stage == 'rgba'
self.norm.autoscale_None(A)
- A = self.to_rgba(A)
- if A.shape[2] == 3:
+ A = self.to_rgba(A, alpha=self.get_alpha())
+ elif A.shape[2] == 3:
A = _rgb_to_rgba(A)
+ if alpha := self.get_alpha() is not None:
+ A[:, :, 3] = self.get_alpha()
alpha = self._get_scalar_alpha()
output_alpha = _resample( # resample alpha channel
self, A[..., 3], out_shape, t, alpha=alpha) fixes at least the obvious cases, but does not address the "what about RGBA" issue and I think will double apply the alpha in scalar cases. I don't have time today to chase through those details or write tests. |
Good first issue - notes for new contributorsThis issue is suited to new contributors because it does not require understanding of the Matplotlib internals. To get started, please see our contributing guide. We do not assign issues. Check the Development section in the sidebar for linked pull requests (PRs). If there are none, feel free to start working on it. If there is an open PR, please collaborate on the work by reviewing it rather than duplicating it in a competing PR. If something is unclear, please reach out on any of our communication channels. |
Looks like we have a precedent that alpha overrides the existing alpha channel on an rgba tuple. matplotlib/lib/matplotlib/colors.py Lines 400 to 401 in 72885cc
Edit: OTOH we also have precedent for ignoring alpha. |
Oh the fun, there is also a precedent that it doesn't for ScalarMappables too :) matplotlib/lib/matplotlib/cm.py Lines 454 to 457 in 72885cc
|
And via matplotlib/lib/matplotlib/image.py Lines 560 to 564 in 3b30f47
import numpy as np
import matplotlib.pyplot as plt
a = np.zeros([2, 2, 4])
a[:, :, 0] = 1
a[:, :, 3] = np.linspace(0, 1, 4).reshape(2, 2)
fig, (ax1, ax2) = plt.subplots(1, 2)
ax1.imshow(a)
ax2.imshow(a, alpha=.5)
plt.show() |
So we should add one that raises, to complete the set 🤪 More seriously, I think it’s probably more important for |
Hello there! I'd like to contribute to this issue. I'm new to contributing to Matplotlib, so please pardon me if I ask any silly questions! I'd just like to clarify what the issue is, and the general sketch of the solution: When displaying images using Matplotlib, if the provided image is of 2 dimensions (grayscale image) and an However, if the provided image is of 3 dimensions (RGB image) and an array is provided for If the provided image is of 4 dimensions (RGBA), and a value for alpha is provided, no matter what the value is (scalar or array), the image isn't affected: it uses the preexisting alpha array present in the image. We'd like to change this behavior: the case for grayscale images works well, so we don't need to change that. For cases where the dimensions of the image are > 2, we'd like to add cases covering all bases: if the image is RGB, add cases where the display function can accept array values for alpha, and if the image is RGBA, decide on a way to let the user know that there are two alpha values: one already provided in the image, and one provided by them. The way to start would be by examining the code snippets @/tacaswell listed, and making the corresponding changes. Please pardon me if I've made any mistake in my clarification! Thanks for patiently reading through this. |
The dimensions are either 2 or 3, and in the case of 3, may have length 3 or 4 in the last dimension (we should fail on 4D input!). The goal is to make RGB and RGBA input work with both scalar alpha and array alpha (like the the color-mapped case) with alpha blending in the RGBA case. |
All right, sounds good! I'll get to work on this, if that's fine. |
Hello, I am currently working on this issue. I would like to ask if we have a problem if the array is RGB and not RGBA? Should we change the |
Just want to clarify that if both RGBA input and parameter I' m a little bit of confused about the code below - is the code desired? It looks a bit weird for me that we are passing alpha to
I can fix it or we can wait for new contributors as this one looks quite straightforward after so many discussions? |
I think we should combine them. For better or worse, the scalar alpha case is blending so the array case should blend too. It would be very confusing if those two things were different. If the user has an RGBA array they want to replace the alpha channel of, then doing
is possible (either choice we make), but if they want to blend then is a bit more awkward if we choose to unconditionally replace the alpha channel. If this is interesting to you, please go ahead and do it @stevezhang1999 ! |
Is it common that we want to apply another alpha blending on a RGBA images? Now this looks less weird to me, but still a little bit confused about when we want to do it. |
What I remain confused about is combining the alpha provided by the user and in RGBA image. How should I go about addressing this in the PR, need some guidance here. matplotlib/lib/matplotlib/image.py Lines 560 to 564 in 3b30f47
As for the
|
Can you provide a code snippet about how you are using |
I'm using the test script from QuLogic above as shown ...
for ax, alpha, t in zip(axs, [None, alpha_scalar, alpha_2d], ['off', 'float', 'array']):
ax[0].imshow(mapped, alpha=alpha)
ax[0].set_title(f'2D, alpha={alpha_scalar} {t}')
ax[1].imshow(mapped, cmap=cmap_with_alpha, alpha=alpha)
ax[1].set_title(f'2D with {alpha_scalar} alpha cmap, alpha={alpha_scalar} {t}')
ax[2].imshow(rgb, alpha=alpha)
ax[2].set_title(f'RGB, alpha={alpha_scalar} {t}')
ax[3].imshow(rgba, alpha=alpha)
ax[3].set_title(f'RGBA, alpha={alpha_scalar} {t}')
plt.savefig('imsave.png') # produces erroneous output
plt.show() # produces correct output but erroneous after saving figure |
So I got you are refering to
|
Is this issue still open? I am willing to work on this issue. |
The example from #26092 (comment) was fixed by #28437 If I've understood correctly, the example from #26092 (comment) is still wrong on the bottom right as of 7e997ae |
Removed the "has patch" label because the relevant code has been refactored since the patch was written. |
Bug summary
Hi,
Whereas
alpha = constant
works with RGB image, this is not the case when working with anarray-type
for alpha.(In my real case, I can only pass standard imshow parameters like
alpha
to the function of the library I use, and not a RGBA array).Patrick
Code for reproduction
Actual outcome
Expected outcome
Additional information
No response
Operating system
Windows
Matplotlib Version
3.7.1
Matplotlib Backend
TkAgg
Python version
Python 3.10.11
Jupyter version
No response
Installation
pip
The text was updated successfully, but these errors were encountered: