以 numpy 表示的三维数组

Python 和 Numpy 的新人尝试创建三维数组。我的问题是,与 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 导入图像的颜色维度是最后一个维度,也就是说,我将颜色信息视为深度维度。如果我想做的只是在一个已知的较小的三维数组上尝试一些东西,那么这会使事情变得非常复杂。

我是不是误会了什么?如果不是,为什么使用这种不直观的方式处理三维数组是麻木的呢?

262406 次浏览

你是对的,你正在创建一个矩阵2行,3列和4深度。Numpy 打印的矩阵与 Matlab 不同:

麻木不仁:

>>> 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

但是你计算的是同一个矩阵。看一下 abc 0,它会指导你把 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)。

你有一个截断的数组表示。让我们看一个完整的例子:

>>> 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 中,只是用另一种方式打印。

一些警告:

  1. Matlab 按列存储数据(“ Fortran order”) ,而 NumPy 默认按行存储数据(“ C order”)。这不会影响索引,但可能会影响性能。例如,在 Matlab 中,高效循环将遍历列(例如 for n = 1:10 a(:, n) end) ,而在 NumPy 中,最好是遍历行(例如 for n in range(10): a[n, :]——注意 n在第一个位置,而不是最后一个)。

  2. 如果你在 OpenCV 中使用彩色图片,请记住:

    它像大多数 Python 库一样以 BGR 格式而不是 RGB 格式存储图像。

    大多数函数在图像坐标(x, y)上工作,这与矩阵坐标(i, j)相反。

尽管人们喜欢说“订单并不重要它的公正约定”,但是当进入跨域接口时,IE 从 C 订单转移到 Fortran 订单或其他订单方案时,这种说法就会被打破。在这里,如何精确地布局数据以及如何用数字表示形状是非常重要的。

默认情况下,numpy 使用 C 排序,这意味着内存中的连续元素是存储在 一排排中的元素。您还可以执行 FORTRAN 排序(“ F”) ,这样就可以根据列对元素进行排序,并对相邻元素进行索引。

Numpy's shape further has its own order in which it displays the shape. In numpy, shape is largest stride first, ie, in a 3d vector, it would be the 最小连续维数, Z, or pages, 3rd dim etc... So when executing:

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 ]]]。这迫使你取消引用第一个数组,该数组包含所有其他数组(第四维) ,然后一路向下(第三维、第二维、第一维) ,结果语法如下:

double element = array4d[w][z][y][x];

在 fortran 中,这个索引顺序是相反的(x 是第一个 array4d[x][y][z][w]) ,从最连续到最不连续,在 matlab 中,它变得非常奇怪。

Matlab 试图同时保留数学默认排序(行、列) ,但在库内部也使用 column main,而不遵循维度排序的 C 约定。在 Matlab 中,你这样订购:

double element = array4d[y][x][z][w];

它神化了所有的约定,并且创建了一些奇怪的情况,在这些情况下,您有时会像行排序一样建立索引,有时会像列排序一样建立索引(比如创建矩阵)。

实际上,Matlab 是不直观的,而不是 Numpy。

阅读这篇文章可以获得更好的洞察力: # :% 7E: text = 3D% 20array,order% 20Layer% 2C% 20rows% 2C% 20column。”rel = “ nofollow noReferrer”> numpy: Array forms and reping Array 麻木: 数组形状和重塑数组

注意: NumPy按照 layers, rows, columns顺序报告3D 阵列的形状。

没必要深究这么多技术细节,还让自己喝醉。让我用最简单的 大部分解释一下。我们在上学期间都学过数学的“ 集合”。只要考虑3D 数字数组作为“集合”的形成。

x = np.zeros((2,3,4))

简单的说:

2 Sets, 3 Rows per Set, 4 Columns

例如:

输入

x = np.zeros((2,3,4))

输出

Set # 1 ---- [[[ 0.,  0.,  0.,  0.],  ---- Row 1
[ 0.,  0.,  0.,  0.],  ---- Row 2
[ 0.,  0.,  0.,  0.]], ---- Row 3
    

Set # 2 ----  [[ 0.,  0.,  0.,  0.],  ---- Row 1
[ 0.,  0.,  0.,  0.],  ---- Row 2
[ 0.,  0.,  0.,  0.]]] ---- Row 3

说明: 看到了吗? 我们有2套,每套3行,和4列。

注意: 当你看到一个“ 一组数字”在两端的双括号中闭合时。就当是“ 准备好了”吧。并且3D 和3D + 数组总是建立在这些“集合”上。