有没有办法将ndy中的2d数组切成较小的2d数组?
例
[[1,2,3,4], -> [[1,2] [3,4]
[5,6,7,8]] [5,6] [7,8]]
Run Code Online (Sandbox Code Playgroud)
所以我基本上想要将2x4阵列减少为2个2x2阵列.寻找用于图像的通用解决方案.
unu*_*tbu 66
你应该能够打破你的数组转换成"块"使用的一些组合reshape和swapaxes:
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 should look like n subblocks with
each subblock preserving the "physical" layout of arr.
"""
h, w = arr.shape
assert h % nrows == 0, "{} rows is not evenly divisble by {}".format(h, nrows)
assert w % ncols == 0, "{} cols is not evenly divisble by {}".format(w, ncols)
return (arr.reshape(h//nrows, nrows, -1, ncols)
.swapaxes(1,2)
.reshape(-1, nrows, ncols))
Run Code Online (Sandbox Code Playgroud)
圈 c
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]]
Run Code Online (Sandbox Code Playgroud)
成
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]]]
Run Code Online (Sandbox Code Playgroud)
我已经张贴了反函数,unblockshaped在这里,和N维泛化这里.这种概括可以更深入地了解该算法背后的推理.
请注意,还有超级鱼类
blockwise_view.它以不同的格式排列块(使用更多的轴),但它的优点是(1)总是返回视图,(2)能够处理任何维度的数组.
在我看来,这是一个numpy.split或某个变体的任务。
例如
a = np.arange(30).reshape([5,6]) #a.shape = (5,6)
a1 = np.split(a,3,axis=1)
#'a1' is a list of 3 arrays of shape (5,2)
a2 = np.split(a, [2,4])
#'a2' is a list of three arrays of shape (2,5), (2,5), (1,5)
Run Code Online (Sandbox Code Playgroud)
如果您有 NxN 图像,您可以创建,例如,2 NxN/2 子图像的列表,然后沿另一个轴划分它们。
numpy.hsplit并且numpy.vsplit也可用。
还有一些其他答案似乎已经非常适合您的具体案例,但是您的问题引起了我对有效内存效率解决方案可能达到numpy支持的最大维数的可能性的兴趣,而我最终花费了大部分时间.下午提出了可能的方法.(方法本身相对简单,只是我还没有使用numpy支持的大多数真正奇特的功能,所以大部分时间花在研究上看看numpy可用的东西以及它可以做多少以便我没有不得不这样做.)
def blockgen(array, bpa):
"""Creates a generator that yields multidimensional blocks from the given
array(_like); bpa is an array_like consisting of the number of blocks per axis
(minimum of 1, must be a divisor of the corresponding axis size of array). As
the blocks are selected using normal numpy slicing, they will be views rather
than copies; this is good for very large multidimensional arrays that are being
blocked, and for very large blocks, but it also means that the result must be
copied if it is to be modified (unless modifying the original data as well is
intended)."""
bpa = np.asarray(bpa) # in case bpa wasn't already an ndarray
# parameter checking
if array.ndim != bpa.size: # bpa doesn't match array dimensionality
raise ValueError("Size of bpa must be equal to the array dimensionality.")
if (bpa.dtype != np.int # bpa must be all integers
or (bpa < 1).any() # all values in bpa must be >= 1
or (array.shape % bpa).any()): # % != 0 means not evenly divisible
raise ValueError("bpa ({0}) must consist of nonzero positive integers "
"that evenly divide the corresponding array axis "
"size".format(bpa))
# generate block edge indices
rgen = (np.r_[:array.shape[i]+1:array.shape[i]//blk_n]
for i, blk_n in enumerate(bpa))
# build slice sequences for each axis (unfortunately broadcasting
# can't be used to make the items easy to operate over
c = [[np.s_[i:j] for i, j in zip(r[:-1], r[1:])] for r in rgen]
# Now to get the blocks; this is slightly less efficient than it could be
# because numpy doesn't like jagged arrays and I didn't feel like writing
# a ufunc for it.
for idxs in np.ndindex(*bpa):
blockbounds = tuple(c[j][idxs[j]] for j in range(bpa.size))
yield array[blockbounds]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
29671 次 |
| 最近记录: |