Есть ли способ глобально указать пиксели (ячейки) для «стирания» в Numpy, используя матрицу с этой информацией? - PullRequest
2 голосов
/ 12 февраля 2020

У меня есть (намного большая) матрица, которая выглядит следующим образом:

  0     0     4     0     0     1
  1     0     0     0     1     0
  2     1     0     1     0     0
  0     0     0     0     0     0
 -1     0    -2    -3     0     0
  0     0    -1    -2     0    -2
  0    -5     0    -1     0    -1

Она должна превратиться в нечто вроде этого:

  0     1     1     1     0     1
  0     0     1     0     1     1
  1     1     1     1     1     1
  1     1     1     1     1     1
  1     1     1     1     1     1
  0     1     0     0     1     1
  1     1     0     0     1     0

Итак, каждая ячейка в первый мат содержит количество соседних (по столбцам) пикселей, которые должны быть стерты (для этой цели получен логический тип маски). Если значение в первой матрице положительное, пиксели должны быть удалены вверх, в отрицательном случае - вниз.

Я уже реализовал это с двойным значением для, которое оказывается слишком медленным .. .

Итак, есть способ сделать это с помощью глобального метода numpy?

(я использую python 3.8, но на самом деле могу использовать любую версию)

РЕДАКТИРОВАТЬ:

Двойник для l oop, который я использовал: где «pix_to_erase» - первый мат, а «mask_array» - второй

for i in range(nRows):
        for j in range(nCols):
            signal = np.sign(pixels_to_erase[i,j])

            if signal > 0:
                upper_bound = i - pixels_to_erase
                if upper_bound < 0:
                    upper_bound = 0
                lower_bound = i
            else:
                upper_bound = i
                lower_bound = i + pixels_to_erase
                if lower_bound > max_row:
                    lower_bound = max_row

            mask_array[upper_bound:lower_bound,j] = 0

(на самом деле это адаптированная часть гораздо большего кода, которую я могу опубликовать в гисте, если нужно)

1 Ответ

1 голос
/ 12 февраля 2020

Если числа в каждой позиции относительно малы, al oop для отдельных значений, вероятно, даст вам гораздо лучшую производительность:

import numpy as np

m = np.array([
    [0,    0,     4,     0,     0,     1],
    [1,    0,     0,     0,     1,     0],
    [2,    1,     0,     1,     0,     0],
    [0,    0,     0,     0,     0,     0],
    [-1,   0,    -2,    -3,     0,     0],
    [0,    0,    -1,    -2,     0,    -2],
    [0,   -5,     0 ,   -1,     0,    -1] ])

result = np.ones(np.shape(m), dtype=int)
for d in np.unique(m):
    if d == 0: continue
    mask  = m if d < 0 else m[::-1,:]
    mask  = np.cumsum(np.cumsum(mask==d,axis=0),axis=0)-1
    mask  = 1 - (mask>0)*(mask<=abs(d))
    if d>0 : mask = mask[::-1,:]
    result *= mask 
    #print(d)
    #print(mask)

print(result)

Это обрабатывает каждое значение стирания индивидуально и генерирует маску для значение вверх или вниз. Результатом является пересечение всех масок.

Однако ... глядя на структуру чисел, я подозреваю, что числа стирания всегда будут в возрастающей / убывающей последовательности вокруг данной точки. Это может привести к гораздо более простому (и более быстрому) решению, когда вам нужно только обработать предыдущую и следующую строки, чтобы определить, нужно ли очищать точки:

result = np.ones(np.shape(m), dtype=int)
result[1:,:]  *= m[:-1,:]>=0
result[:-1,:] *= m[1:,:] <=0
print(result)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...