5

在指示的行中,我从以下 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 位。

4

2 回答 2

5

我可以在http://www.lfd.uci.edu/~gohlke/pythonlibs/#pil上使用 Python 3.2.3、numpy 1.6.1 和 PIL 1.1.7-for-Python 3 在 ubuntu 12.04 上重现。之所以会出现差异,是因为 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 转换期间引入的错误。只需替换tobytes()tostring()in即可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!
>>> 
于 2012-06-01T18:43:37.090 回答
2

同意帝斯曼。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”。

于 2013-05-01T11:23:48.670 回答