#python #arrays #numpy #opticalflow #4d
#python #массивы #numpy #opticalflow #4d
Вопрос:
Я написал функцию, которая добавляет индексы каждого элемента в массиве к элементам.
Примеры:
Первый элемент равен [10,11], индекс равен [0,0] -> Становится [0,0,10,11]
Второй элемент равен [12,13], индекс равен [1,0] -> Становится [1,0,12,13]
Как я могу оптимизировать эту функцию? Есть ли более простой способ написать это? Любые улучшения / рекомендации будут оценены!
Мой проект: Я использую Optical Flow для получения массива величин (u, v), которые представляют компоненты вектора оптического потока каждого пикселя. Я хотел бы добавить положение (x, y) пикселей в массив, чтобы я получил массив (x, y, u, v). Примечание: позиция (x, y) совпадает со значением индекса, что немного упрощает задачу.
Вот мой код:
def vec_4D (mag_2D):
vec_4D = np.zeros((mag_2D.shape[0],mag_2D.shape[1],4))
x = 0
y = 0
for row in vec_4D:
for col in row:
col[0] = x
col[1] = y
col[2] = mag_2D[y][x][0]
col[3] = mag_2D[y][x][1]
x = 1
x=0
y =1
return(vec_4D)
mag_2D = np.array([[[10,11], [12,13], [14,15]], [[16,17], [18,19], [20,21]]])
print(vec_4D(mag_2D))
Input array:
[[[10 11]
[12 13]
[14 15]]
[[16 17]
[18 19]
[20 21]]]
Output array:
[[[ 0. 0. 10. 11.]
[ 1. 0. 12. 13.]
[ 2. 0. 14. 15.]]
[[ 0. 1. 16. 17.]
[ 1. 1. 18. 19.]
[ 2. 1. 20. 21.]]]
Ответ №1:
Здесь неизбежен один вкладыш.
>>> np.concatenate([np.moveaxis(np.indices(mag_2D.shape[:-1]), 0, -1)[..., ::-1], mag_2D], -1)
array([[[ 0, 0, 10, 11],
[ 1, 0, 12, 13],
[ 2, 0, 14, 15]],
[[ 0, 1, 16, 17],
[ 1, 1, 18, 19],
[ 2, 1, 20, 21]]])
Самый простой способ понять это — разбить его:
np.indices
создает индексы из формы
>>> np.indices(mag_2D.shape[:-1])
array([[[0, 0, 0],
[1, 1, 1]],
[[0, 1, 2],
[0, 1, 2]]])
Они, однако, отдельные для каждого измерения. Чтобы получить координатные «кортежи», мы должны переместить начальную ось в конец:
>>> np.moveaxis(np.indices(mag_2D.shape[:-1]), 0, -1)
array([[[0, 0],
[0, 1],
[0, 2]],
[[1, 0],
[1, 1],
[1, 2]]])
Это y, x
, OP хочет x, y
>>> np.moveaxis(np.indices(mag_2D.shape[:-1]), 0, -1)[..., ::-1]
array([[[0, 0],
[1, 0],
[2, 0]],
[[0, 1],
[1, 1],
[2, 1]]])
Комментарии:
1. Без объяснения, этот ответ, хотя и работает в этом случае, не имеет возможности для применения к другим проблемам. Однострочники модны, но без объяснения причин теряют свою ценность. Возможно, вы можете добавить несколько слов к своему ответу
2. @Bazingaa Ты действительно смотрел на это? Я бы сказал, что это довольно понятно, почти как обычный английский: «Объединить индексы для
mag_2D
(с перемещением их начальной оси в конец) сmag_2D
самим собой».3.
...,
для меня это не похоже на простой английский, и я думаю, что даже новичкам. Конечно, у вас уровень английского C2, так что для вас это выглядит как само собой разумеющееся 😉4. @Bazingaa Хорошо, хорошо. Я добавил несколько строк объяснения.
Ответ №2:
Вот «многострочный», использующий np.indices()
, и np.concatenate()
:
y_indices,x_indices = np.indices(mag_2D.shape[0:2])
vec_4D_result = np.concatenate((x_indices[:,:,None],
y_indices[:,:,None],
mag_2D[y_indices,x_indices]), axis = -1)
Тестирование:
import numpy as np
mag_2D = np.array([[[10,11], [12,13], [14,15]], [[16,17], [18,19], [20,21]]])
y_indices,x_indices = np.indices(mag_2D.shape[0:2])
vec_4D_result = np.concatenate((x_indices[:,:,None],
y_indices[:,:,None],
mag_2D[y_indices,x_indices]), axis = -1)
print (vec_4D_result)
Вывод:
[[[ 0 0 10 11]
[ 1 0 12 13]
[ 2 0 14 15]]
[[ 0 1 16 17]
[ 1 1 18 19]
[ 2 1 20 21]]]
Комментарии:
1. Предложенное вами решение очень четкое, и его было намного проще применить к другим задачам, чем другие предложенные (хотя они также отлично работают!). Я отредактирую принятый ответ на этот. Спасибо!
Ответ №3:
Упрощенная версия вашего подхода к заполнению
In [650]: arr = np.arange(10,22).reshape(2,3,2)
In [658]: res = np.zeros((arr.shape[0],arr.shape[1],4),arr.dtype)
In [659]: res[:,:,2:] = arr
Следующий шаг потребовал немного проб и ошибок. Мы заполняем индексы с помощью broadcasting. Нам нужны массивы, которые могут транслировать в (2,3) первые 2 измерения res
.
In [660]: res[:,:,0] = np.arange(arr.shape[1])
In [661]: res[:,:,1] = np.arange(arr.shape[0])[:,None] # size 2 column
In [662]: res
Out[662]:
array([[[ 0, 0, 10, 11],
[ 1, 0, 12, 13],
[ 2, 0, 14, 15]],
[[ 0, 1, 16, 17],
[ 1, 1, 18, 19],
[ 2, 1, 20, 21]]])