当我尝试对这个numpy数组求和时,为什么Python会崩溃?

时间:2015-03-17 17:54:02

标签: python python-3.x numpy

我正在使用Python 3.4(Numpy 1.9.2和PIL.Image 1.1.7)处理Ubuntu 14.04。这就是我的所作所为:

>>> from PIL import Image
>>> import numpy as np

>>> img = Image.open("./tifs/18015.pdf_001.tif")
>>> arr = np.asarray(img)
>>> np.shape(arr)
(5847, 4133)

>>> arr.dtype
dtype('bool')

# all of the following four cases where I incrementally increase
# the number of rows to 700 are done instantly
>>> v = arr[1:100,1:100].sum(axis=0)
>>> v = arr[1:500,1:100].sum(axis=0)
>>> v = arr[1:600,1:100].sum(axis=0)
>>> v = arr[1:700,1:100].sum(axis=0)

# but suddenly this line makes Python crash
>>> v = arr[1:800,1:100].sum(axis=0)

fish: Job 1, “python3” terminated by signal SIGSEGV (Address boundary error)

对我而言,就像Python突然耗尽内存一样。如果是这种情况 - 如何为Python分配更多内存?正如我从htop看到的那样,我的32GB内存容量甚至都没有消耗殆尽。

您可以下载TIFF图像here


如果我创建一个空的布尔数组,请明确设置像素然后应用求和 - 然后它可以工作:

>>> arr = np.empty((h,w), dtype=bool)
>>> arr.setflags(write=True)

>>> for r in range(h):
>>>     for c in range(w):
>>>         arr.itemset((r,c), img.getpixel((c,r)))

>>> v=arr.sum(axis=0)

>>> v.mean()
5726.8618436970719

>>> arr.shape
(5847, 4133)

但这"解决方法"不是很令人满意,因为复制每个像素需要太长时间 - 也许有更快的方法?

1 个答案:

答案 0 :(得分:3)

我可以使用从Ubuntu存储库安装的numpy v1.8.2 / PIL v1.1.7重现您的段错误。

  • 如果我使用pip在virtualenv中安装numpy 1.8.2(仍然使用Ubuntu repos中的PIL v1.7.1),那么我就不会再看到段错误了。

  • 如果我做相反的事情(使用pip安装PIL v1.1.7,并使用Ubuntu repos中的numpy v1.8.2),我仍然会遇到段错误。

这让我相信它是由numpy中的一个老虫引起的。我无法在numpy的问题跟踪器中找到一个好的候选人,但我怀疑更新numpy(例如从当前来源或通过pip)可能会解决问题。

一种解决方法是在创建数组之前将图像模式转换为"P"(无符号8位整数),然后将其转换回布尔值:

arr2 = np.asarray(img.convert("P")).astype(np.bool)
v = arr2[1:800,1:100].sum(axis=0)