Python中循环遍历图像每个像素的更快方法?

14

我需要循环遍历一个2560x2160的2D numpy数组(图片)中的每个像素。我的问题简化如下:

import time
import numpy as np

t = time.clock()
limit = 9000
for (x,y), pixel in np.ndenumerate(image):
    if( pixel > limit )
        pass
tt = time.clock()
print tt-t

在我的电脑上,这需要讨人厌的大约30秒才能完成。(核心i7,8GB内存)是否有更快的方法执行内部带“if”语句的循环?我只对超过一定限制的像素感兴趣,但我确实需要它们的(x,y)索引和值。

2个回答

22

使用布尔矩阵:

x, y = (image > limit).nonzero()
vals = image[x, y]

2
哇!我的眼睛睁开了。只用了 <0.1 秒。 - dinkelk
这里的 x 和 y 分别是什么? - Andrew Hundt
1
@AndrewHundt:xy分别是非零点的x和y索引数组。 - nneonneo
当我使用Python 2.7运行此代码时,我会收到一个属性错误,显示“'bool'对象没有'nonzero'属性”。图像>限制的部分应该做什么? - Marjoram
imagelimit中必须有一个是NumPy数组 - 如果它们都不是NumPy对象,则image> limit可能会解析为Python布尔值,而不是NumPy布尔数组。 - nneonneo

7

首先,尝试使用向量化计算:

i, j = np.where(image > limit)

如果您的问题无法通过向量化计算解决,可以通过以下方式加速for循环:
for i in xrange(image.shape[0]):
    for j in xrange(image.shape[1]):
        pixel = image.item(i, j)
        if pixel > limit:
            pass

或者:

from itertools import product
h, w = image.shape
for pos in product(range(h), range(w)):
    pixel = image.item(pos)
    if pixel > limit:
        pass

numpy.ndenumerate很慢,通过使用普通的for循环并使用item方法从数组中获取值,可以将循环加速4倍。

如果你需要更快的速度,尝试使用Cython,它将使你的代码像C代码一样快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接