самый быстрый способ перебрать все пиксели изображения в python

я уже прочитал изображение как массив:

import numpy as np
from scipy import misc
face1=misc.imread('face1.jpg')

размеры face1 равны (288, 352, 3)

мне нужно перебрать каждый пиксель и заполнить столбец y в тренировочном наборе. Я использовал следующий подход:

Y_training = np.zeros([1,1],dtype=np.uint8)

for i in range(0, face1.shape[0]): # We go over rows number 
    for j in range(0, face1.shape[1]): # we go over columns number
        if np.array_equiv(face1[i,j],[255,255,255]):
           Y_training=np.vstack(([0], Y_training))#0 if blank
        else:
           Y_training=np.vstack(([1], Y_training))

b = len(Y_training)-1
Y_training = Y_training[:b]
np.shape(Y_training)`

Wall time: 2.57 s

Поскольку мне нужно выполнить описанный выше процесс примерно для 2000 изображений, есть ли более быстрый подход, при котором мы могли бы сократить время выполнения до миллисекунд или наонов секунд?


person chessosapiens    schedule 27.07.2017    source источник
comment
Для будущих подобных проблем вы можете попробовать декоратор numba @njit. Так что вы получите скомпилированную JIT-функцию, которая работает очень быстро   -  person Gioelelm    schedule 02.08.2017


Ответы (1)


Вы можете использовать broadcasting для сравнения трансляции с белым пикселем: [255, 255, 255] и ALL сокращают каждую строку с помощью .all(axis=-1) и, наконец, преобразуют в int dtype. Это даст нам результат, который вы получите сразу после выхода из цикла.

Таким образом, одна реализация будет -

(~((face1 == [255,255,255]).all(-1).ravel())).astype(int)

Как вариант, чуть более компактный вариант -

1-(face1 == [255,255,255]).all(-1).ravel()
person Divakar    schedule 27.07.2017
comment
я думаю, что это должно быть (~((face1 != [255,255,255]).all(-1).ravel())).astype(int), так как мне нужно пометить белые пиксели 0 - person chessosapiens; 27.07.2017
comment
@sanaz Нет. Проверьте еще раз, пожалуйста. - person Divakar; 27.07.2017
comment
(~((face1 == [255,255,255]).all(-1).ravel())).astype(int) возвращает array([1, 1, 1, ..., 1, 1, 1]), который помечает белые пиксели с помощью 1 , мой собственный подход к циклу for помечает их с помощью 0 - person chessosapiens; 27.07.2017
comment
@sanaz Попробуйте небольшой образец: face1 = np.random.randint(0,255,(4,5,3)). Затем установите два пикселя в белый цвет: face1[2,3] = [255,255,255]; face1[1,2] = [255,255,255]. Теперь сделайте третий пиксель синим: face1[1,3] = [255,0,0]. Итак, теперь используйте все методы, которые у вас есть, и посмотрите, какие методы дают вам массив ровно с двумя 0. Это правильные. - person Divakar; 27.07.2017
comment
каким будет наиболее эффективный способ получить результат в виде вектора-столбца, а не вектора-строки? имея (101376,1) вместо (101376,) - person chessosapiens; 27.07.2017
comment
@sanaz NumPy не имеет понятия вектора строки/столбца. Но, судя по формату, который у вас есть в вопросе, я бы сказал, что вектор-строка был бы лучшим, тогда как создание вектора-столбца из него также не будет слишком дорогостоящим. - person Divakar; 27.07.2017
comment
я имел в виду наличие (101376,1) вместо (101376,) - person chessosapiens; 27.07.2017
comment
@sanaz Да, это то, о чем я догадался, и мои комментарии были основаны на этом предположении. - person Divakar; 27.07.2017