简体   繁体   English

numpy 是否有可能在不更改 memory 顺序和迭代器的情况下交换矩阵的 x,y?

[英]Is there possibilty in numpy to swap x,y of matrix without changing memory order and iterators?

I'm trying to switch to numpy from the world of fortran and c++ .我正在尝试从fortranc++ 的世界切换到 numpy Mainly I'm working with huge images, where coordinates directions are x: left to right, y: top down, and pixels are stored in rows, common for image format.主要是我正在处理巨大的图像,其中坐标方向是x:从左到右,y:自上而下,像素存储在行中,常见于图像格式。

Numpy says that also stores matrices by rows. Numpy 说它还按行存储矩阵。 As far as good, it is the same as fortran/c++ saves images.就好的而言,它与 fortran/c++ 保存图像相同。 But, see following example, grays from black to white in rows.但是,请参阅以下示例,从黑色到白色的灰色行。 Lets create image 3x3 where first row is 123 etc让我们创建图像 3x3,其中第一行是 123 等

Black to White image as expected, with matplotlib imshow(mat)黑白图像符合预期,带有 matplotlib imshow(mat)

mat = np.array([1,2,3,4,5,6,7,8,9], 'i1').reshape(3,3)

next I've used following code to get info about matrix.接下来我使用以下代码获取有关矩阵的信息。 Routine prints: value at position x=1, y=0 , position in memory to see if array is copied, strides and iterators.例行打印: position x=1, y=0 , position 中的值在 memory 中查看是否复制了数组、步幅和迭代器。

def pr(a):
    x=1; y=0;
    print(a[x,y])
    print(a.ctypes.data, a.strides, a.ravel(order='K'), [x for x in a.flat], a.flatten(order='K'))
    print(a.flags)

for matrix mat in C-order I've got对于C 顺序的矩阵mat ,我有

4
94598176807408 (3, 1) [1 2 3 4 5 6 7 8 9] [1, 2, 3, 4, 5, 6, 7, 8, 9] [1 2 3 4 5 6 7 8 9]
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False

So it is clear that x,y are swapped, because for x=1 and y=0 pixel value is 2 and not 4, so I've changed to F order.所以很明显x,y被交换了,因为对于x=1y=0像素值是 2 而不是 4,所以我已更改为 F 顺序。

# mat = mat.ravel(order='K').reshape(3,3, order='F')
mat.strides = (1,3)
# mat = np.swapaxes(mat, 0, 1)

Above are three possibilities to get F order with same results.以上是获得具有相同结果的F 阶的三种可能性。

2
94598176807408 (1, 3) [1 2 3 4 5 6 7 8 9] [1, 4, 7, 2, 5, 8, 3, 6, 9] [1 2 3 4 5 6 7 8 9]
  C_CONTIGUOUS : False
  F_CONTIGUOUS : True

Now image is swapped when using F order with same memory layout as before现在,当使用具有相同 memory 布局的 F 订单时,图像被交换

As you can see value 2 for x=1 y=2 is correct, using mat[x,y] is correct, memory order is correct, but iterator is wrong 1 4 7... .如您所见, x=1 y=2的值 2 是正确的,使用mat[x,y]是正确的,memory 顺序是正确的,但迭代器是错误的1 4 7... Consequences are that saving or showing image are bad, all are swapped.结果是保存或显示图像不好,全部被交换。 Iterator not in memory order has big performance penalties.不在 memory 订单中的迭代器有很大的性能损失。

Question is: How to set numpy matrix with swapped x,y without copy of image and all other properties are as in C-order.问题是:如何在没有图像副本的情况下设置 numpy 矩阵,交换 x,y 并且所有其他属性都与 C 顺序相同。 I've tried to set C_CONTIGUOUS=True, but it is not possible.?我尝试设置 C_CONTIGUOUS=True,但这是不可能的。?

One way is to use C-order but on all such matrices one must use reversed indexes [y,x], problem is that it is very confusing, all vectors are normal (x,y,z) and some objects use swap index order.?一种方法是使用 C 顺序,但在所有此类矩阵上都必须使用反向索引 [y,x],问题是它非常混乱,所有向量都是正常的(x,y,z)并且一些对象使用交换索引顺序.? Correct naming order of axes helps in further spatial operation of images.轴的正确命名顺序有助于图像的进一步空间操作。

Maybe there is possibility to extend numpy , with other index method like mat.swap2[x,y] that only returns mat[y,x] or eg.也许有可能扩展numpy ,使用其他索引方法,如mat.swap2[x,y]只返回mat[y,x]或例如。 mat[*reversed((x,y))] . mat[*reversed((x,y))] But is there better solution?但是有更好的解决方案吗?

Next are two examples in fortran and c++ with eg.接下来是fortranc++中的两个示例,例如。 armadillo matrix library (as c/c++ doesn't seem to define own generic matrix object).犰狳矩阵库(因为 c/c++ 似乎没有定义自己的通用矩阵对象)。 Both examples uses F order, indexing is correct mat[x,y] , memory layout is same as binary layout of input images, row by row, iterator are in memory layout.两个示例都使用 F 顺序,索引正确mat[x,y] ,memory 布局与输入图像的二进制布局相同,逐行,迭代器在 memory 布局中。 It seems strange to me that numpy in F order does not support same behavior.在我看来,F 顺序中的 numpy 不支持相同的行为似乎很奇怪。 Or simply I don't understand the philosophy of numpy.或者只是我不明白 numpy 的哲学。

Example in fortran , saving and iterating such matrix is in memory order (not shown here). fortran中的示例,保存和迭代此类矩阵按 memory 顺序(此处未显示)。

...
    integer(1) :: mat(0:2,0:2)      ! matrix 3x3 indexing 0,1,2
    data mat /1,2,3,4,5,6,7,8,9/    ! memory order
    print*, mat(1,0)                ! value for x=1 y=0 is 2 ok
...

Example in C++ with armadillo, saving and iterating again is in memory order (not shown here). C++中的示例与犰狳,保存并再次迭代是按 memory 顺序(此处未显示)。

#define ARMA_U8_TYPE   uint8_t
#define ARMA_S8_TYPE    int8_t        // define support for int8 instead of char
#include <armadillo>
...
    using namespace arma;
    int8_t amem[] = {1,2,3,4,5,6,7,8,9};        // memory order
    Mat<int8_t> mat(amem, 3,3,  false,true);    // matrix 3x3
    cout << (int)mat(1,0) << "\n";              // value for x=1 y=0 is 2 ok
...

First numpy has confusing terms for column major mode, F_CONTIGUOUS is never contiguous in memory for 2D and more.首先 numpy 对列主模式有混淆的术语, F_CONTIGUOUS在 memory 中对于 2D 等从不连续。 It is just like view by design and memory layout is always C .就像按设计查看一样, memory 布局始终为C For performance reasons and axis assignment as you specified it is more natural to use column major order as many do, but not easy in numpy.出于性能原因和您指定的轴分配,使用列主顺序更自然,但在 numpy 中并不容易。

Furthermore built-in/extension doesn't allow to use just setattr() to extend directly numpy classes, but you can derive own.此外,内置/扩展不允许仅使用setattr()直接扩展 numpy 类,但您可以派生自己的。

To be simple in numpy always use default C order (row major order) and swap axes as mat[z,y,x] .为了简单起见, numpy 始终使用默认的C顺序(行主要顺序)并将轴交换为mat[z,y,x] It seems to me to be the least confusing.在我看来,这似乎是最不容易混淆的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM