简体   繁体   English

将3D numpy数组有效转换为1D numpy数组

[英]Efficient conversion of a 3D numpy array to a 1D numpy array

I have a 3D numpy array in this form: 我有这种形式的3D numpy数组:

>>>img.shape
(4504932, 2, 2)

>>> img
array([[[15114, 15306],
    [15305, 15304]],

   [[15305, 15306],
    [15303, 15304]],

   [[15305, 15306],
    [15303, 15304]],

   ..., 

   [[15305, 15302],
    [15305, 15302]]], dtype=uint16)

Which I want to convert to a 1D numpy array where each entry is the sum of each 2x2 submatrix in the above img numpy array. 我想将其转换为一个1D numpy数组,其中每个条目都是上述img numpy数组中每个2x2子矩阵的总和。

I have been able to accomplish this using: 我已经能够使用以下方法完成此任务:

img_new = np.array([i.sum() for i in img])
>>> img_new
array([61029, 61218, 61218, ..., 61214, 61214, 61214], dtype=uint64)

Which is exactly what I want. 这正是我想要的。 But this is too slow (takes about 10 seconds). 但这太慢了(大约需要10秒)。 Is there a faster method I could use? 有没有我可以使用的更快的方法? I included above img.shape so you had an idea of the size of this numpy array. 我在img.shape上面包含了它,因此您对这个numpy数组的大小有所了解。

EDIT - ADDITIONAL INFO: My img array could also be a 3D array in the form of 4x4, 5x5, 7x7.. etc submatrices. 编辑-其他信息:我的img数组也可以是4x4、5x5、7x7等子矩阵形式的3D数组。 This is specified by the variables sub_rows and sub_cols . 这由变量sub_rowssub_cols指定。

img.sum(axis=(1, 2))

sum allows you to specify an axis or axes along which to sum, rather than just summing the whole array. sum允许您指定一个或多个沿轴求和,而不仅仅是对整个数组求和。 This allows NumPy to loop over the array in C and perform just a few machine instructions per sum, rather than having to go through the Python bytecode evaluation loop and create a ton of wrapper objects to stick in a list. 这使NumPy可以在C语言中循环遍历数组,并且每个和仅执行几条机器指令,而不必经过Python字节码评估循环并创建大量包装对象以粘贴在列表中。

Using a numpy method ( apply_over_axes ) is usually quicker and indeed that is the case here. 通常,使用numpy方法( apply_over_axes )更快,实际上就是这种情况。 I just tested on a 4000x2x2 array: 我刚刚在4000x2x2阵列上进行了测试:

img = np.random.rand(4000,2,2)
timeit(np.apply_along_axis(np.sum, img, [1,2]))
# 1000 loops, best of 3: 721 us per loop
timeit(np.array([i.sum() for i in img]))
# 100 loops, best of 3: 17.2 ms per loop

You can use np.einsum - 您可以使用np.einsum

img_new = np.einsum('ijk->i',img)

Verify results 验证结果

In [42]: np.array_equal(np.array([i.sum() for i in img]),np.einsum('ijk->i',img))
Out[42]: True

Runtime tests 运行时测试

In [34]: img = np.random.randint(0,10000,(10000,2,2)).astype('uint16')

In [35]: %timeit np.array([i.sum() for i in img]) # Original approach
10 loops, best of 3: 92.4 ms per loop

In [36]: %timeit img.sum(axis=(1, 2)) # From other solution
1000 loops, best of 3: 297 µs per loop

In [37]: %timeit np.einsum('ijk->i',img)
10000 loops, best of 3: 102 µs per loop

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM