从多个较小的二维数组中形成一个大的二维数组

14

这个问题是 这个问题 的反向。我正在寻找一种通用方法,可以从小数组中生成原始大数组:

array([[[ 0,  1,  2],
        [ 6,  7,  8]],    
       [[ 3,  4,  5],
        [ 9, 10, 11]], 
       [[12, 13, 14],
        [18, 19, 20]],    
       [[15, 16, 17],
        [21, 22, 23]]])

->

array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])

我目前正在开发一种解决方案,完成后会发布它,但我想看看其他更好的方法。

5个回答

39
import numpy as np
def blockshaped(arr, nrows, ncols):
    """
    Return an array of shape (n, nrows, ncols) where
    n * nrows * ncols = arr.size

    If arr is a 2D array, the returned array looks like n subblocks with
    each subblock preserving the "physical" layout of arr.
    """
    h, w = arr.shape
    return (arr.reshape(h//nrows, nrows, -1, ncols)
               .swapaxes(1,2)
               .reshape(-1, nrows, ncols))


def unblockshaped(arr, h, w):
    """
    Return an array of shape (h, w) where
    h * w = arr.size

    If arr is of shape (n, nrows, ncols), n sublocks of shape (nrows, ncols),
    then the returned array preserves the "physical" layout of the sublocks.
    """
    n, nrows, ncols = arr.shape
    return (arr.reshape(h//nrows, -1, nrows, ncols)
               .swapaxes(1,2)
               .reshape(h, w))

例如,
c = np.arange(24).reshape((4,6))
print(c)
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(blockshaped(c, 2, 3))
# [[[ 0  1  2]
#   [ 6  7  8]]

#  [[ 3  4  5]
#   [ 9 10 11]]

#  [[12 13 14]
#   [18 19 20]]

#  [[15 16 17]
#   [21 22 23]]]

print(unblockshaped(blockshaped(c, 2, 3), 4, 6))
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

请注意,还有 superbatfish 的 blockwise_view。它以不同的格式(使用更多的轴)排列块,但具有以下优点:(1)始终返回视图,(2)能够处理任何维度的数组。

对于 c = np.arange(24).reshape((6,4))print(unblockshaped(blockshaped(a, 3, 2), 6, 4)) 是不起作用的。 - TheMeaningfulEngineer
blockshaped 的返回结果正常。问题出在 unblockshaped 上。 - TheMeaningfulEngineer
1
是的,我之前 reshape 函数的参数顺序错了。现在再试试看。 - unutbu
1
@SudiptaBasak:这不是问题,因为没有 arrarr.size 等于素数的二维数组。 - unutbu
@SudiptaBasak:blockshaped 的功能如广告所述。质数只有平凡因子并不是 blockshaped 的错 : )。也许你正在寻找类似于 np.array_split(c, 3, axis=1) 的东西。请注意,结果是数组列表,而不是单个数组。由于 NumPy 数组不能具有长度不均匀的行(或列),因此没有单个数组等效项。 - unutbu
显示剩余3条评论

4

另一种(简单)方法:

threedarray = ...
twodarray = np.array(map(lambda x: x.flatten(), threedarray))
print(twodarray.shape)

1
我希望我理解正确,假设我们有 a,b

>>> a = np.array([[1,2] ,[3,4]])
>>> b = np.array([[5,6] ,[7,8]])
    >>> a
    array([[1, 2],
           [3, 4]])
    >>> b
    array([[5, 6],
           [7, 8]])

为了将其变成一个大的二维数组,请使用 numpy.concatenate
>>> c = np.concatenate((a,b), axis=1 )
>>> c
array([[1, 2, 5, 6],
       [3, 4, 7, 8]])

我正在寻找一种方法,可以从更小的数组重新构建一个大数组(图像)。我需要它是通用的,这样就可以应用于不同尺寸的图像。就像在jpeg中切片。将图像分成8×8块,对每个块进行操作,然后从块中重建原始图像。 - TheMeaningfulEngineer

0
这里有一个解决方案,如果有人想要创建矩阵的平铺,则可以使用它:
from itertools import product
import numpy as np
def tiles(arr, nrows, ncols):
    """
    If arr is a 2D array, the returned list contains nrowsXncols numpy arrays
    with each array preserving the "physical" layout of arr.

    When the array shape (rows, cols) are not divisible by (nrows, ncols) then
    some of the array dimensions can change according to numpy.array_split.

    """
    rows, cols = arr.shape
    col_arr = np.array_split(range(cols), ncols)
    row_arr = np.array_split(range(rows), nrows)
    return [arr[r[0]: r[-1]+1, c[0]: c[-1]+1]
                     for r, c in product(row_arr, col_arr)]

0

目前为止,它可以处理我测试的图像。如果进行进一步的测试,就会知道是否可行。然而,这是一种不考虑速度和内存使用的解决方案。

def unblockshaped(blocks, h, w):
    n, nrows, ncols = blocks.shape
    bpc = w/ncols
    bpr = h/nrows

    reconstructed = zeros((h,w))
    t = 0
    for i in arange(bpr):
        for j in arange(bpc):
            reconstructed[i*nrows:i*nrows+nrows,j*ncols:j*ncols+ncols] = blocks[t]
            t = t+1
    return reconstructed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接