有效地将Numpy阵列重新整形/重新排序为正确排序的图块(图像)

时间:2012-04-02 16:07:08

标签: python numpy python-imaging-library

我希望能够以某种方式重新排序numpy数组,以便有效地处理tile。

我得到了什么:

>>> A = np.array([[1,2],[3,4]]).repeat(2,0).repeat(2,1)
>>> A  # image like array
array([[[1, 1, 2, 2],
        [1, 1, 2, 2]],

       [[3, 3, 4, 4],
        [3, 3, 4, 4]]])

>>> A.reshape(2,2,4)
array([[[1, 1, 2, 2],
        [1, 1, 2, 2]],

       [[3, 3, 4, 4],
        [3, 3, 4, 4]]])

我想要的是什么:如何获得X:

>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [4, 4, 4, 4]]])

这可能没有慢速python循环吗?

奖励:从X转换回A

Bago指出了一个我错过的类似问题:Creating a 4D view on 2D array to divide it into cells of fixed size


为什么一切都麻烦?能够做类似的事情:

>>> X[X.sum(2)>12] -= 1
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [3, 3, 3, 3]]])

编辑:解决方案:

# MIT - License

import numpy as np

def tile_reorder(A, t):
    """reshape and transpose quadratic array for easy access to quadratic tiles of size t"""
    l = A.shape[0] / t
    X = A.reshape((l, t, l, t))
    X = X.transpose([0, 2, 1, 3])
    return X

def tile_reorder_reverse(X):
    l = X.shape[0] * X.shape[2]
    A = X.transpose([0, 2, 1, 3])
    A = A.reshape((l, l))
    return A

if __name__ == "__main__":
    A = np.array([[1,2,3],[3,4,5],[6,7,8]]).repeat(4,0).repeat(4,1)

    print "A:\n", A, "\n\n"

    print "A_tiled:\n", tile_reorder(A,4), "\n\n"

    print "A_tiled_reversed:\n", tile_reorder_reverse(tile_reorder(A,4)), "\n\n"

    X = tile_reorder(A,4)
    X[X.sum((2)).sum(2)>63,:,:] += 10
    B = tile_reorder_reverse(X)

    print "B_processed:\n", B, "\n\n"

2 个答案:

答案 0 :(得分:3)

你想要这样的东西:

>>> X = A.reshape(2,2,2,2)
>>> X = X.transpose([0,2,1,3])
>>> X = X.reshape((2,2,-1))
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [4, 4, 4, 4]]])
>>> B = X.reshape((2,2,2,2))
>>> B = B.transpose([0,2,1,3])
>>> B = B.reshape((2,2,-1))
>>> B
array([[[1, 1, 2, 2],
        [1, 1, 2, 2]],

       [[3, 3, 4, 4],
        [3, 3, 4, 4]]])

答案 1 :(得分:1)

我认为你只是在查看数组的错误部分。以下应该做你想做的事。

>>> X[(X.sum(2)>12),:] -= 1
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [3, 3, 3, 3]]])

回到原来的顺序有点复杂。我相信你可以将下面的代码修改为一个名为get_back()的函数,或者你不必一直重用它。

import numpy as np
X = np.asarray([[[1,1,1,1],[2,2,2,2]],[[3,3,3,3],[4,4,4,4]]])
print X

# Make the change to the array
# Note that I make the change to +=1 so we can indeed see that
# the reshaping worked by looking for the 5's.
X[(X.sum(2)>12),:] += 1

(M,N,P) = X.shape;      # Number of tiles is MxN
orig_i = 2; orig_j = 2; # (Original rows/cols in a tile).
orig = (orig_i, orig_j) # Define as a tuple for convenience.
hstacks = []
for ii in range(M):
    hstacks.append(X[ii,0,:].reshape(orig))
    for jj in range(1,N):
        hstacks[-1] = np.hstack(( hstacks[-1], X[ii,jj,:].reshape(orig) ))

orig_array = hstacks[0]
for kk in range(1,len(hstacks)):
    orig_array = np.vstack(( orig_array, hstacks[kk] ))

# Print to confirm that it worked.
print orig_array

我得到以下内容:

>>> [[[1 1 1 1]
      [2 2 2 2]]

     [[3 3 3 3]
      [4 4 4 4]]]

>>> [[1 1 2 2]
     [1 1 2 2]
     [3 3 5 5]
     [3 3 5 5]]

为了测试,我尝试了更大的瓷砖图案,它给出了正确的结果。请注意,我使用函数get_back()来封装上面的代码,我只是在平铺维度参数中硬编码到函数中。真的,他们应该是输入参数。

>>> X = np.asarray([[[1,1,1,1],[2,2,2,2],[3,3,3,3]],
                    [[4,4,4,4],[5,5,5,5],[6,6,6,6]]])
>>> X
array([[[1, 1, 1, 1],
        [2, 2, 2, 2],
        [3, 3, 3, 3]],

       [[4, 4, 4, 4],
        [5, 5, 5, 5],
        [6, 6, 6, 6]]])

>>> get_back(X)
array([[1 1 2 2 3 3]
       [1 1 2 2 3 3]
       [4 4 5 5 6 6]
       [4 4 5 5 6 6]])