【问题标题】:Faster way to loop through every pixel of an image in Python?在 Python 中循环遍历图像的每个像素的更快方法?
【发布时间】:2012-10-11 19:42:28
【问题描述】:

我需要遍历 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) 索引和值。

【问题讨论】:

    标签: python image loops time numpy


    【解决方案1】:

    使用布尔矩阵:

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

    【讨论】:

    • 哇!我的眼睛睁开了。耗时
    • 这里的 x 和 y 是什么?
    • @AndrewHundt: xy 分别是非零点的 x 和 y 索引数组。
    • 当我用 python 2.7 运行这段代码时,我得到一个属性错误,说“'bool' object has no attribute 'nonzero'”。部分(图像>限制)应该做什么?
    • imagelimit 之一必须是 NumPy 数组 - 如果它们都是非 NumPy 对象,image > limit 可能会解析为 Python 布尔值而不是 NumPy 布尔值数组。
    【解决方案2】:

    首先,尝试使用vectorize计算:

    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 代码一样快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-25
      • 2013-07-16
      • 2011-12-06
      • 2021-11-18
      • 1970-01-01
      • 2017-06-11
      • 2019-08-12
      • 2016-07-07
      相关资源
      最近更新 更多