numpy中的三维数组

Vej*_*jto 45 python numpy

Python和Numpy的新手,尝试创建三维数组.我的问题是,与Matlab相比,维度的顺序是关闭的.事实上,订单根本没有意义.

创建矩阵:

x = np.zeros((2,3,4))
Run Code Online (Sandbox Code Playgroud)

在我的世界中,这应该产生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] 
Run Code Online (Sandbox Code Playgroud)

分离每个深度尺寸.相反,它被呈现为

[0 0 0 0      [0 0 0 0
 0 0 0 0       0 0 0 0
 0 0 0 0]      0 0 0 0]
Run Code Online (Sandbox Code Playgroud)

即,3行,4列和2个深度尺寸.也就是说,第一个维度是"深度".为了进一步添加这个问题,使用OpenCV导入图像颜色维度是最后一个维度,也就是说,我将颜色信息视为深度维度.如果我想做的就是在已知的较小的三维阵列上尝试某些东西,这会使事情变得非常复杂.

我误解了什么吗?如果没有,为什么使用这种不直观的3D维阵列工作方式会让人感到沮丧?

ffr*_*end 33

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

>>> 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.]]])
Run Code Online (Sandbox Code Playgroud)

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]]]
Run Code Online (Sandbox Code Playgroud)

此复合列表的第一级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中使用彩色图像,请记住:

    2.1.它像BGR格式一样存储图像,而不像大多数Python库那样存储RGB.

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

  • 它实际上并不是不合逻辑的,只是与众不同.没有真正的方法在2D屏幕上表示3D阵列,因此不同的环境使用不同的方法.而Matlab和NumPy都有他们打印数组的理由. (3认同)
  • 在阅读完这个答案并摸不着它之后,我觉得想在"行,列,堆栈"序列中的numpy数组是不合适的.最好想一想,"第一个装有第二个容器的容器装有第三个容器". (3认同)
  • 显示是不合逻辑的,它似乎是2个阵列,每个有3行和4列,但这里的答案实际上是2个行和列的4个堆叠数组 (3认同)

jab*_*edo 17

你是对的,你正在创建一个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.]]])
Run Code Online (Sandbox Code Playgroud)

MATLAB

>> zeros(2, 3, 2)
 ans(:,:,1) =
     0     0     0
     0     0     0
 ans(:,:,2) =
     0     0     0
     0     0     0
Run Code Online (Sandbox Code Playgroud)

但是,您正在计算相同的矩阵.看看Numpy for 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)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

如果您查看矩阵,c您将看到它是一个100x200x3矩阵,它正好在图像中显示(红色,因为我们将R坐标设置为255,另外两个保持为0).


Web*_*abs 11

无需深入研究如此深奥的技术,而让自己被炸毁。让我用简单的方式来解释它。我们在数学的学龄期都学过“集合”。只需将 3D numpy 数组视为“集合”的形成。

x = np.zeros((2,3,4)) 
Run Code Online (Sandbox Code Playgroud)

简单的意思:

2 Sets, 3 Rows per Set, 4 Columns
Run Code Online (Sandbox Code Playgroud)

例子:

输入

x = np.zeros((2,3,4))
Run Code Online (Sandbox Code Playgroud)

输出

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
Run Code Online (Sandbox Code Playgroud)

解释: 看到了吗?我们有 2 组,每组 3 行和 4 列。

注意:每当您看到“一组数字”从两端用双括号括起来时。将其视为“集合”。并且 3D 和 3D+ 阵列总是建立在这些“集合”上。


ihe*_*ers 6

阅读这篇文章以获得更好的见解:numpy:数组形状和重塑数组

注意:NumPy按顺序报告 3D 数组的形状layers, rows, columns


whn*_*whn 5

尽管人们喜欢说“顺序与其只是约定无关”,但在进入跨域接口时,IE 从 C 排序转换为 Fortran 排序或其他一些排序方案时,这会崩溃。在那里,精确地如何布局数据以及如何在 numpy 中表示形状非常重要。

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

Numpy 的形状还有它自己的显示形状的顺序。在 numpy 中,形状首先是最大的步幅,即在 3d 向量中,它将是最不连续的维度、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];

在 fortran 中,这种索引顺序是相反的(x 是 first array4d[x][y][z][w]),从最连续到最不连续,而在 matlab 中,它变得很奇怪。

Matlab 试图保留数学默认排序(行、列),但也在内部为库使用列主要,而不是遵循 C 维度排序约定。在 matlab 中,您可以这样订购:

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

它神化了所有约定并创建了奇怪的情况,您有时会像按行排序而有时按列排序(例如创建矩阵)进行索引。

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