Субсэмплирование трехмерного массива с использованием суммы окрестностей - PullRequest
1 голос
/ 06 июня 2019

Название, вероятно, сбивает с толку. У меня достаточно большой массив 3D. Я хотел бы сократить его размер на 2 ^ 3, разбивая блоки размером (2,2,2). Каждый элемент в новом трехмерном массиве должен содержать сумму элементов в соответствующем блоке в исходном массиве.

В качестве примера рассмотрим массив 4x4x4:

input = [[[1, 1, 2, 2],
          [1, 1, 2, 2],
          [3, 3, 4, 4],
          [3, 3, 4, 4]],
         [[1, 1, 2, 2],
          [1, 1, 2, 2],
          [3, 3, 4, 4],
          [3, 3, 4, 4]],
              ...    ]]]

(я представляю только половину, чтобы сэкономить место). Обратите внимание, что все элементы с одинаковым значением составляют блок (2x2x2). Выходные данные должны быть массивом 2x2x2, так что каждый элемент является суммой блока:

output = [[[8, 16],
          [24, 32]],
             ... ]]]

Итак, 8 - это сумма всех 1, 16 - это сумма 2 и т. Д.

1 Ответ

2 голосов
/ 06 июня 2019

Есть встроенное средство для выполнения этих блочных сокращений - skimage.measure.block_reduce -

In [36]: a
Out[36]: 
array([[[1, 1, 2, 2],
        [1, 1, 2, 2],
        [3, 3, 4, 4],
        [3, 3, 4, 4]],

       [[1, 1, 2, 2],
        [1, 1, 2, 2],
        [3, 3, 4, 4],
        [3, 3, 4, 4]]])

In [37]: from skimage.measure import block_reduce

In [39]: block_reduce(a, block_size=(2,2,2), func=np.sum)
Out[39]: 
array([[[ 8, 16],
        [24, 32]]])

Используйте другие уфунки сокращения, скажем max-reduction -

In [40]: block_reduce(a, block_size=(2,2,2), func=np.max)
Out[40]: 
array([[[1, 2],
        [3, 4]]])

Реализация такой функции не так уж сложна с инструментами NumPy и может быть сделана так -

def block_reduce_numpy(a, block_size, func):
    shp = a.shape
    new_shp = np.hstack([(i//j,j) for (i,j) in zip(shp,block_size)])
    select_axes = tuple(np.arange(a.ndim)*2+1)
    return func(a.reshape(new_shp),axis=select_axes)
...