-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[Bug]: Making an RGB image from pickled data throws error #28448
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
I am able to work around this issue by manually re-casting the image data prior to the call, so my hunch is that this is an error to do with the pickling: Updated example with workaround: import io
import pickle
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from pathlib import Path
from matplotlib.animation import FuncAnimation
dir = Path(__file__).parent.resolve()
# generate random rgb data
fig, ax = plt.subplots()
np.random.seed(0)
data = np.random.rand(100, 100, 3)
ax.imshow(data)
# pick the figure and reload
buf = io.BytesIO()
pickle.dump(fig, buf)
buf.seek(0)
fig_pickled = pickle.load(buf)
# Workaround
ax = fig_pickled.get_axes()[0]
artists = ax.get_children()
for artist in artists:
if isinstance(artist, mpl.image.AxesImage):
array = artist.get_array()
artist.set_array(array.data.astype('float64'))
# Animate
def update(frame):
return ax,
ani = FuncAnimation(fig_pickled, update, frames=2)
# Save the animation
filepath = dir / 'test.gif'
ani.save(filepath) |
I can reproduce this on macOS without animation using: import io
import numpy as np
import matplotlib.pyplot as plt
import pickle
fig, ax = plt.subplots()
rng = np.random.default_rng(4181)
data = rng.uniform(size=(2, 2, 3))
axes_image = ax.imshow(data)
print(axes_image._A.shape, axes_image._A.dtype)
im = axes_image.make_image(None)[0]
buf = io.BytesIO()
pickle.dump(axes_image, buf)
buf.seek(0)
axes_image2 = pickle.load(buf)
print(axes_image2._A.shape, axes_image2._A.dtype)
#axes_image2._A = axes_image2._A.astype("float64")
print("Same dtype?", axes_image._A.dtype == axes_image2._A.dtype)
im = axes_image2.make_image(None)[0] Using this you get a The problem occurs on this line matplotlib/src/_image_wrapper.cpp Line 189 in d7d1bba
After pickling and unpickling the numpy array dtype is fine from a Python point of view, but from a C++ pybind11 point of view the dtype has all the right properties but its PyObject has a different address so we conclude that it is not really a double (i.e. np.float64 ) dtype. I haven't got any further than this yet, but If my analysis is correct it should be possible to write a reproducer that doesn't use Matplotlib at all.
|
Can we fallback to eq in the c++ code instead of import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
rng = np.random.default_rng(4181)
data = rng.uniform(size=(2, 2, 3)).astype(np.dtype('float64', copy=True))
axes_image = ax.imshow(data)
print(axes_image._A.shape, axes_image._A.dtype)
im = axes_image.make_image(None)[0] |
It looks like |
Uh oh!
There was an error while loading. Please reload this page.
Bug summary
Getting an error when saving an animated RGB image that was loaded from a pickled figure. I've isolated the error to matplotlib 3.9.0, with this code working in 3.8.3, which makes me think that this is to do with the pybind11 upgrade in #26275?
Things I've tried:
data = np.random.rand(100, 100)
) work.data.dtype
andout.dtype
are showing'float64'
prior to the_image.resample
call.data = data.astype('float64')
,out = ...
, then the_image.resample
call no longer fails!out.dtype == data.dtype
returnsTrue
, but on the function call I get the errorValueError: Input and output arrays have mismatched types
See these parts of the source:
matplotlib/lib/matplotlib/image.py
Lines 205 to 213 in d7d1bba
matplotlib/src/_image_wrapper.cpp
Lines 174 to 199 in d7d1bba
Code for reproduction
Actual outcome
Matplotlib Version
3.9.0
The text was updated successfully, but these errors were encountered: