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). 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.
这正是我想要的。但这太慢了(大约需要10秒)。有更快的方法吗?我上面包括img。形状,你知道这个numpy数组的大小。
EDIT - ADDITIONAL INFO: My img
array could also be a 3D array in the form of 4x4, 5x5, 7x7.. etc submatrices. This is specified by the variables sub_rows
and sub_cols
.
编辑-附加信息:我的img数组也可以是一个4×4,5×5,7×7的3D数组。等子矩阵。由变量sub_rows和sub_cols指定。
3 个解决方案
#1
4
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. 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.
sum允许您指定要求和的轴或轴,而不只是对整个数组求和。这允许NumPy在C中循环数组,每次执行几个机器指令,而不需要经过Python字节码计算循环并创建大量的包装器对象来插入列表。
#2
0
Using a numpy method (apply_over_axes
) is usually quicker and indeed that is the case here. I just tested on a 4000x2x2 array:
使用numpy方法(apply_over_axes)通常更快,实际上就是这样。我刚刚测试了一个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
#3
0
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
#1
4
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. 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.
sum允许您指定要求和的轴或轴,而不只是对整个数组求和。这允许NumPy在C中循环数组,每次执行几个机器指令,而不需要经过Python字节码计算循环并创建大量的包装器对象来插入列表。
#2
0
Using a numpy method (apply_over_axes
) is usually quicker and indeed that is the case here. I just tested on a 4000x2x2 array:
使用numpy方法(apply_over_axes)通常更快,实际上就是这样。我刚刚测试了一个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
#3
0
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