Массив Python с несколькими условиями для итерации по изображению

Я фильтрую некоторые изображения, чтобы удалить ненужный фон, и до сих пор был наиболее успешным при проверке значений BGR пикселей (с использованием openCV). Проблема в том, что перебор изображения с двумя вложенными циклами слишком медленный:

h, w, channels = img.shape
    for x in xrange(0,h):
        for y in xrange (0,w):
            pixel = img[x,y]
            blue = pixel[0]
            green = pixel[1]
            red = pixel[2]

            if green > 110:
                img[x,y] = [0,0,0]
                continue

            if blue < 100 and red < 50 and green > 80:
                img[x,y] = [0,0,0]
                continue

Есть еще пара похожих if-утверждений, но вы поняли идею. Проблема в том, что для 672x1250 на i7 требуется около 10 секунд.

Теперь я могу легко сделать первое утверждение if следующим образом:

img[np.where((img > [0,110,0]).all(axis=2))] = [0,0,0]

И это намного быстрее, но я не могу выполнить другие операторы if с несколькими условиями, используя np.where.

Вот что я попробовал:

img[np.where((img < [100,0,0]).all(axis=2)) & ((img < [0,0,50]).all(axis=2)) & ((img > [0,80,0]).all(axis=2))] = [0,0,0]

Но выдает ошибку:

ValueError: operands could not be broadcast together with shapes (2,0) (1250,672)

Любые идеи о том, как правильно перебирать изображение с помощью np.where (или чего-либо, что быстрее 2-х вложенного цикла), очень помогут!

1 ответ

Решение

Вы могли бы выразить условия (без np.where) как это:

import numpy as np
img = np.random.randint(255, size=(4,4,3))
blue, green, red = img[..., 0], img[..., 1], img[..., 2]
img[(green > 110) | ((blue < 100) & (red < 50) & (green > 80))] = [0,0,0]

In [229]: %%timeit img = np.random.randint(255, size=(672,1250,3))
   .....: blue, green, red = img[..., 0], img[..., 1], img[..., 2]
   .....: img[(green > 110) | ((blue < 100) & (red < 50) & (green > 80))] = [0,0,0]
   .....: 
100 loops, best of 3: 14.9 ms per loop

In [240]: %%timeit img = np.random.randint(255, size=(672,1250,3))
   .....: using_loop(img)
   .....: 
1 loop, best of 3: 1.39 s per loop

где using_loop(img) выполняет двойной цикл, размещенный в вопросе.

Другие вопросы по тегам