[英]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.