Эффективно изменяющий / переупорядочивающий массив Numpy к правильно упорядоченным плиткам (изображение) - PullRequest
1 голос
/ 02 апреля 2012

Я хотел бы иметь возможность каким-либо образом изменить порядок массива для эффективной обработки плиток.

что я получил:

>>> 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]]])

Возможно ли это без медленной петли питона?

Бонус: преобразование обратно из X в A

Баго указал на аналогичный вопрос Iупустил: Создание четырехмерного вида на двумерном массиве, чтобы разделить его на ячейки фиксированного размера


Почему все проблемы?Чтобы иметь возможность сделать что-то вроде:

>>> 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 ]

3 голосов
/ 02 апреля 2012

Хотите что-то вроде:

>>> 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 голос
/ 02 апреля 2012

Я думаю, что вы просто смотрите на неправильный фрагмент вашего массива.Следующее должно делать то, что вы хотите.

>>> 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]])
...