Более быстрый способ перебирать каждый пиксель изображения в Python?

Мне нужно перебрать каждый пиксель 2D-массива numpy 2560x2160 (изображение). Упрощенная версия моей проблемы выглядит следующим образом:

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 секунд на моем компьютере. (Core i7, 8 ГБ оперативной памяти ) Есть ли более быстрый способ выполнить этот цикл с внутренней инструкцией "if"? Меня интересуют только пиксели выше определенного предела,но мне нужны их (x, y) индексы и значение.

2 ответов


используйте логическую матрицу:

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

во-первых, попробуйте использовать расчет векторизовать:

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 медленный, используя normal for loop и получить значение из массива по item метод вы можете ускорить цикл на 4x.

Если вам нужно больше скорости, попробуйте использовать Cython, он сделает ваш код так же быстро, как C-код.