[英]Is there possibilty in numpy to swap x,y of matrix without changing memory order and iterators?
我正在尝试从fortran和c++ 的世界切换到 numpy 。 主要是我正在处理巨大的图像,其中坐标方向是x:从左到右,y:自上而下,像素存储在行中,常见于图像格式。
Numpy 说它还按行存储矩阵。 就好的而言,它与 fortran/c++ 保存图像相同。 但是,请参阅以下示例,从黑色到白色的灰色行。 让我们创建图像 3x3,其中第一行是 123 等
黑白图像符合预期,带有 matplotlib imshow(mat)
mat = np.array([1,2,3,4,5,6,7,8,9], 'i1').reshape(3,3)
接下来我使用以下代码获取有关矩阵的信息。 例行打印: 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)
对于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
所以很明显x,y
被交换了,因为对于x=1
和y=0
像素值是 2 而不是 4,所以我已更改为 F 顺序。
# mat = mat.ravel(order='K').reshape(3,3, order='F')
mat.strides = (1,3)
# mat = np.swapaxes(mat, 0, 1)
以上是获得具有相同结果的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
现在,当使用具有相同 memory 布局的 F 订单时,图像被交换
如您所见, x=1 y=2
的值 2 是正确的,使用mat[x,y]
是正确的,memory 顺序是正确的,但迭代器是错误的1 4 7...
。 结果是保存或显示图像不好,全部被交换。 不在 memory 订单中的迭代器有很大的性能损失。
问题是:如何在没有图像副本的情况下设置 numpy 矩阵,交换 x,y 并且所有其他属性都与 C 顺序相同。 我尝试设置 C_CONTIGUOUS=True,但这是不可能的。?
一种方法是使用 C 顺序,但在所有此类矩阵上都必须使用反向索引 [y,x],问题是它非常混乱,所有向量都是正常的(x,y,z)
并且一些对象使用交换索引顺序.? 轴的正确命名顺序有助于图像的进一步空间操作。
也许有可能扩展numpy ,使用其他索引方法,如mat.swap2[x,y]
只返回mat[y,x]
或例如。 mat[*reversed((x,y))]
。 但是有更好的解决方案吗?
接下来是fortran和c++中的两个示例,例如。 犰狳矩阵库(因为 c/c++ 似乎没有定义自己的通用矩阵对象)。 两个示例都使用 F 顺序,索引正确mat[x,y]
,memory 布局与输入图像的二进制布局相同,逐行,迭代器在 memory 布局中。 在我看来,F 顺序中的 numpy 不支持相同的行为似乎很奇怪。 或者只是我不明白 numpy 的哲学。
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
...
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
...
首先 numpy 对列主模式有混淆的术语, F_CONTIGUOUS
在 memory 中对于 2D 等从不连续。 就像按设计查看一样, memory 布局始终为C
。 出于性能原因和您指定的轴分配,使用列主顺序更自然,但在 numpy 中并不容易。
此外,内置/扩展不允许仅使用setattr()
直接扩展 numpy 类,但您可以派生自己的。
为了简单起见, numpy 始终使用默认的C
顺序(行主要顺序)并将轴交换为mat[z,y,x]
。 在我看来,这似乎是最不容易混淆的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.