是什么导致PIL fromarray函数中依赖于维度的AttributeError?

时间:2012-06-01 17:36:57

标签: python numpy python-imaging-library attributeerror

我在指定的行中从以下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企业版机器上使用Python 3.2.3,一切都是64位。

2 个答案:

答案 0 :(得分:6)

我可以在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没有strides值,但是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转换期间引入的错误。只需在tobytes()中将tostring()替换为Image.py即可,它应该有效:

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!
>>> 

答案 1 :(得分:2)

同意DSM。我也遇到了与PIL 1.17相同的问题。

在我的情况下,我需要传输ndarray int图像并保存它。

x = np.asarray(img[:, :, 0] * 255., np.uint8)
image = Image.fromarray(x)
image.save("%s.png" % imgname)

我的错误和你的一样。

我随机尝试了其他方法:scipy.msic.imsave直接保存图像。

scipy.msic.imsave(imgname, x)

有效!不要忘记图片名称中的'.png'。