我在指定的行中从以下 Python3 代码中收到错误。 x、y 和 z 都是普通的 2D numpy 数组,除了大小相同外,它们的工作方式应该相同。然而它们的行为不同,y 和 z 崩溃而 x 工作正常。
import numpy as np
from PIL import Image
a = np.ones( ( 3,3,3), dtype='uint8' )
x = a[1,:,:]
y = a[:,1,:]
z = a[:,:,1]
imx = Image.fromarray(x) # ok
imy = Image.fromarray(y) # error
imz = Image.fromarray(z) # error
但这行得通
z1 = 1*z
imz = Image.fromarray(z1) # ok
错误是:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python3\lib\site-packages\PIL\Image.py", line 1918, in fromarray
obj = obj.tobytes()
AttributeError: 'numpy.ndarray' object has no attribute 'tobytes'
那么 x、y、z、z1 之间有什么不同?我无话可说。
>>> z.dtype
dtype('uint8')
>>> z1.dtype
dtype('uint8')
>>> z.shape
(3, 4)
>>> z1.shape
(3, 4)
我在一台 Windows 7 Enterprise 机器上使用 Python 3.2.3,一切都是 64 位。
最佳答案
我可以在 ubuntu 12.04 上使用 Python 3.2.3、numpy 1.6.1 和 PIL 1.1.7-for-Python 3 在 http://www.lfd.uci.edu/~gohlke/pythonlibs/#pil 重现.出现差异是因为 x 的 array_interface 没有步幅值,但 y 和 z 有:
>>> x.__array_interface__['strides']
>>> y.__array_interface__['strides']
(9, 1)
>>> z.__array_interface__['strides']
(9, 3)
因此这里采用了不同的分支:
if strides is not None:
obj = obj.tobytes()
文档提到了tostring
,而不是tobytes
:
# If obj is not contiguous, then the tostring method is called
# and {@link frombuffer} is used.
而 PIL 1.1.7 的 Python 2 源代码使用 tostring
:
if strides is not None:
obj = obj.tostring()
所以我怀疑这是在进行 str/bytes 更改的 2 到 3 转换期间引入的错误。只需将 Image.py
中的 tobytes()
替换为 tostring()
就可以了:
Python 3.2.3 (default, May 3 2012, 15:54:42)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> from PIL import Image
>>>
>>> a = np.ones( ( 3,3,3), dtype='uint8' )
>>> x = a[1,:,:]
>>> y = a[:,1,:]
>>> z = a[:,:,1]
>>>
>>> imx = Image.fromarray(x) # ok
>>> imy = Image.fromarray(y) # now no error!
>>> imz = Image.fromarray(z) # now no error!
>>>
关于python - 是什么导致 PIL fromarray 函数中与维度相关的 AttributeError?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10854903/