У меня есть несколько массивных форм (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]]
Вы не можете выводить массив двумерных чисел, поскольку выходные строки могут иметь разную длину. Я бы согласился на список массивов 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
в конце, что не очень быстро, потому что оно включает в себя создание списка. Поэтому я считаю, что этот ответ является достаточно хорошим компромиссом между простотой и простотой.
Если предпочтительным выходом является массив, заполненный 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
Вы можете перебирать строки и группировать элемент, создавая новый массив, проверяя последние элементы и добавляя только в случае различий.
Функция следующая:
def groupRow(row):
newRow = [row[0]]
for elem in row:
if elem != newRow[-1]:
newRow.append(elem)
return newRow
Итерации и замените каждую строку в форме на newRow из этой функции
A = np.array([0,0,0,1,1,1,1,0,0,1])
. Тот же алгоритм можно изменить, чтобы показать, если этот набор вам лучше