Как быстрее разобраться с nparrays - PullRequest
0 голосов
/ 18 марта 2019

У меня есть два загруженных изображения в два массива. Я хочу получить разницу между ними и удалить значения меньше 50, а остальное установить на 255 с окончательным результатом черно-белого изображения.

def count(base, image):
    x, y, z = base.shape
    sheet = np.zeros(base.shape)
    for i in range(x):
        for j in range(y):
            temp = 0
            for k in range(z):
                if base[i, j, k] > image[i, j, k]:
                    t = base[i, j, k] - image[i, j, k]
                    if t > 50:
                        temp = 255
                else:
                    t = image[i, j, k] - base[i, j, k]
                    if t > 50:
                        temp = 255
            sheet[i, j] = [temp, temp, temp]

    array = sheet[:, :, 0]

этот код делает то, что мне нужно. но, как вы видите, я использовал самый простой цикл for для этой функции, а изображения размером 2000 * 2000 занимают много времени. Мне нужен способ переписать это быстрее.

спасибо

Ответы [ 2 ]

3 голосов
/ 18 марта 2019

Векторизация вашего кода выглядит просто, за исключением одного недочета: ваши данные выглядят как целые числа без знака (uint8 на вид), которые требуют немного дополнительного внимания, поскольку они часто теряют свои результаты с неожиданными результатами.Например, очевидное np.abs(image-base)>50 для обнаружения различий, превышающих 50, не работает, на самом деле np.abs является недействительным для неподписанных данных.Тщательный перевод выглядел бы как

sheet = np.array([[0,0,0],[255,255,255]], 'u1')[((np.maximum(base, image)-np.minimum(base, image))>50).any(2).view('u1')]

или

sheet = np.array([[0,0,0],[255,255,255]], 'u1')[(np.abs(np.subtract(image, base, dtype='i2'))>50).any(2).view('u1')]

Этот

  1. правильно вычисляет субпиксельную мудрую разницу,

    • первая версия имитирует ваше условие if / else

    • вторая вызывает тип результата со знаком 'i2' или int16 для разницы

  2. определяет те, которые больше 50,

  3. отмечает пиксели хотя бы с одним таким подпикселем (any(2)),

  4. преобразует полученную логическую маску в индексы (.view('u1')) 0 и 1

  5. и использует их для индексации в массив шаблонов.

1 голос
/ 18 марта 2019

Большинство операций работают так же, как и в скалярах на массивах NumPy одинакового размера.Я переписал функцию следующим образом:

def count_new(base, image, thresh=50):
    # these are the pixel absolute value differences
    differences = np.abs(base - image)

    # whether the difference exceeds the threshold
    big_difference = differences > thresh

    # whether each pixel has at least one big difference
    big_difference = big_difference.any(axis=2)

    # return 255 where big differences, and 0 everywhere else
    return 255 * big_difference.astype(int)

Надеемся, что комментарии проясняют цель каждой строки.Также проверено, что это дает то же самое, что и предыдущий выход

x = np.random.randint(256, size=(10, 11, 3))
y = np.random.randint(256, size=(10, 11, 3))
assert((count(x,y) == count_new(x,y)).all())

, что показывает, что он делает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...