3-мерный массив в numpy
Новое на Python и Numpy, пытаясь создать 3-мерные массивы. Моя проблема в том, что порядок размеров отключен по сравнению с Matlab. На самом деле порядок не имеет смысла.
Создание матрицы:
x = np.zeros((2,3,4))
В моем мире это должно привести к 2 строкам, 3 столбцам и 4 глубинам и должно быть представлено как:
[0 0 0 [0 0 0 [0 0 0 [0 0 0
0 0 0] 0 0 0] 0 0 0] 0 0 0]
Разделение по каждой глубине.
Вместо этого он представлен как
[0 0 0 0 [0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0] 0 0 0 0]
То есть, 3 строки, 4 столбца и 2 глубины. То есть, первым измерением является "глубина". Чтобы добавить к этой проблеме, импортирование изображения с помощью OpenCV - это измерение размера, то есть я вижу информацию о цвете как измерение глубины. Это усложняет ситуацию, если все, что я хочу сделать, это попробовать что-то в известном меньшем 3-мерном массиве.
Я что-то неправильно понял? Если нет, то почему heck numpy использует такой неинтуитивный способ работы с 3D-мерными массивами?
Ответы
Ответ 1
У вас есть усеченное представление массива. Давайте посмотрим на полный пример:
>>> a = np.zeros((2, 3, 4))
>>> a
array([[[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]],
[[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]]])
Массивы в NumPy печатаются как array
слов с последующей структурой, аналогично встроенным спискам Python. Давайте создадим аналогичный список:
>>> l = [[[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]],
[[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]]]
>>> l
[[[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]],
[[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]]
Первый уровень этого составного списка l
содержит ровно 2 элемента, так же как и первое измерение массива a
(количество строк). Каждый из этих элементов сам по себе список с 3 -х элементов, который является равным второму измерению a
(# столбцов). И, наконец, наиболее вложенные списки имеют 4 элементов, каждый же, как в третьем измерении a
(глубина/# цветов).
Таким образом, у вас точно такая же структура (с точки зрения размеров), как в Matlab, просто напечатанная другим способом.
Некоторые предостережения:
-
Matlab хранит данные столбец за столбцом ("порядок Фортрана"), в то время как NumPy по умолчанию сохраняет их построчно ("порядок С"). Это не влияет на индексирование, но может повлиять на производительность. Например, в Matlab эффективный цикл будет проходить по столбцам (например, for n = 1:10 a(:, n) end
), тогда как в NumPy предпочтительнее выполнять итерацию по строкам (например, for n in range(10): a[n, :]
- примечание n
в первом положении, не последний).
-
Если вы работаете с цветными изображениями в OpenCV, помните, что:
2.1. Он хранит изображения в формате BGR, а не в RGB, как это делают большинство библиотек Python.
2.2. Большинство функций работают с координатами изображения (x, y
), которые противоположны координатам матрицы (i, j
).
Ответ 2
Вы правы, вы создаете матрицу с 2 строками, 3 столбцами и 4 глубинами. Матрица печатает Numpy отличается от Matlab:
Numpy:
>>> import numpy as np
>>> np.zeros((2,3,2))
array([[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]]])
Matlab
>> zeros(2, 3, 2)
ans(:,:,1) =
0 0 0
0 0 0
ans(:,:,2) =
0 0 0
0 0 0
Однако вы рассчитываете ту же матрицу. Посмотрите на Numpy для пользователей Matlab, он поможет вам преобразовать код Matlab в Numpy.
Например, если вы используете OpenCV, вы можете создать образ, используя numpy, учитывая, что OpenCV использует представление BGR:
import cv2
import numpy as np
a = np.zeros((100, 100,3))
a[:,:,0] = 255
b = np.zeros((100, 100,3))
b[:,:,1] = 255
c = np.zeros((100, 200,3))
c[:,:,2] = 255
img = np.vstack((c, np.hstack((a, b))))
cv2.imshow('image', img)
cv2.waitKey(0)
![enter image description here]()
Если вы посмотрите на матрицу c
то увидите, что это матрица 100x200x3, которая в точности соответствует изображению на рисунке (красным, поскольку мы установили координату R на 255, а две другие остались на 0).
Ответ 3
Как бы ни говорили люди: "порядок не имеет значения, это просто соглашение", это ломается при входе в междоменные интерфейсы, переход IE из C-порядка в Fortran или какую-то другую схему упорядочения. Там очень важно, как именно выкладываются ваши данные и как фигура представлена в виде numpy.
По умолчанию numpy использует порядок C, что означает, что смежные элементы в памяти - это элементы, хранящиеся в строках. Вы также можете выполнить упорядочение FORTRAN ("F"), вместо этого элементы упорядочиваются по столбцам, индексируя смежные элементы.
Numpy shape также имеет свой собственный порядок, в котором она отображает форму. В numpy форма имеет наибольший шаг вперед, т.е. В трехмерном векторе это будет наименее непрерывное измерение, Z или страницы, 3-е затемнение и т.д. Так что при выполнении:
np.zeros((2,3,4)).shape
ты получишь
(2,3,4)
что на самом деле (frames, rows, columns)
. выполнение np.zeros((2,2,3,4)).shape
вместо этого будет означать (metaframs, frames, rows, columns)
. Это имеет больше смысла, когда вы думаете о создании многомерных массивов в C, таких как языки. Для C++ создание несмежно определенного 4D массива приводит к array [ of arrays [ of arrays [ of elements ]]]
. Это вынуждает вас ссылаться на первый массив, который содержит все другие массивы (4-е измерение), а затем одинаковые до конца (3-й, 2-й, 1-й), что приводит к синтаксису, например:
double element = array4d[w][z][y][x]
;
В Фортране этот порядок меняется на обратный (вместо x - первый array4d[x][y][z][w]
), наиболее смежный с наименее смежным, а в matlab он становится все странным.
Matlab пытался сохранить как математическое упорядочение по умолчанию (строка, столбец), так и внутреннее использование столбцов для библиотек, и не следовать С соглашению о размерном упорядочении. В Matlab вы заказываете так:
double element = array4d[y][x][z][w]
;
который ограничивает все соглашения и создает странные ситуации, когда вы иногда индексируете, как если бы упорядочивались строки, а иногда упорядочивались столбцы (например, при создании матрицы).
На самом деле, Матлаб - не интуитивный, а не Нампи.