Как заменить повторяющиеся последовательные элементы в двумерном массиве с одним элементом

1

У меня есть несколько массивных форм (1080 960)

[[0 0 255 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 255 0 0]
 ...
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 255 255 ... 0 0 0]]

Я хочу вывести массив numpy, который заменяет повторяющиеся значения как 0, так и 255 одним 0 и одним 255

Массив numpy представляет собой представление двоичного изображения с пикселями в форме BBBWWWWWWWBBBBWWW, где B является черным, а W - белым. Я хочу преобразовать его в BWBW.

Пример:

вход:

[[0,0,0,255,255,255,0,0,0,0],
 [255,255,255,0,0,0,255,255,255],
 [0,0,255,0,0,255,0,0,255]]

выход:

[[0,255,0],
 [255,0,255]
 [0,255,0,255,0,255]]
  • 0
    что ты уже испробовал?
  • 0
    Я пробовал itertools 'groupby функцию, различные преобразования NumPy и т. Д.
Показать ещё 3 комментария
Теги:
arrays
numpy
replace

2 ответа

1
Лучший ответ

Вы не можете выводить массив двумерных чисел, поскольку выходные строки могут иметь разную длину. Я бы согласился на список массивов numpy. Итак, 1-й пусть сгенерирует некоторые данные:

img = np.random.choice([0,255], size=(1080, 960))

Затем перебираем по каждой строке:

out=[]
for row in img:
    idx=np.ediff1d(row, to_begin=1).nonzero()[0]
    out.append(row[idx])

Принимая разницу, мы просто обнаруживаем, где происходят изменения, а затем используя эти индексы idx чтобы выбрать начальный элемент в последовательной строке. Это решение немного проще и быстрее, чем у @DavidWinder (30 мс против 150 мс).

Полностью векторизованное решение может быть немного быстрее, но код будет немного сложным. Это будет включать сглаживание массивов, раскол и распутывание индексов... и применение np.split в конце, что не очень быстро, потому что оно включает в себя создание списка. Поэтому я считаю, что этот ответ является достаточно хорошим компромиссом между простотой и простотой.

Редактировать # 1

Если предпочтительным выходом является массив, заполненный 0s в конце, лучше создать массив нулей и заполнить его значениями списка out. Сначала выясните, в какой строке есть больше элементов, и создайте массив:

max_elms = np.max([len(x) for x in out])
arr = np.zeros((1080, max_elms), dtype=np.int32)

А потом перебирать out списка и arr, заполняя значение arr с теми, в out списка:

for row, data in zip(arr, out):
    row[:len(data)] = data
  • 0
    Да, это проблема. Я хотел бы вывести двумерный массив Numpy и добавить каждую строку с нулями в конце, чтобы сделать их все одинаковой длины.
  • 0
    Не могли бы вы предложить что-то для этого?
Показать ещё 3 комментария
1

Вы можете перебирать строки и группировать элемент, создавая новый массив, проверяя последние элементы и добавляя только в случае различий.

Функция следующая:

def groupRow(row):
    newRow = [row[0]]
    for elem in row:
            if elem != newRow[-1]:
                    newRow.append(elem)
    return newRow

Итерации и замените каждую строку в форме на newRow из этой функции

  • 0
    «Стрелка», которая должна быть передана здесь - это список?
  • 0
    Строка - это массив np как: A = np.array([0,0,0,1,1,1,1,0,0,1]) . Тот же алгоритм можно изменить, чтобы показать, если этот набор вам лучше

Ещё вопросы

Сообщество Overcoder
Наверх
Меню