为什么这个numpy数组操作这么慢?
我是一名Python初学者,正在尝试对两个形状为(1024, 1024)的NumPy二维数组进行平均。像这样做速度很快:
newImage = (image1 + image2) / 2
但是现在这些图像有一个“掩码”,如果某些元素被设置为零,就会使这些元素无效。这意味着如果其中一个元素是零,结果元素也应该是零。我的简单解决方案是:
newImage = numpy.zeros( (1024,1024) , dtype=numpy.int16 )
for y in xrange(newImage.shape[0]):
for x in xrange(newImage.shape[1]):
val1 = image1[y][x]
val2 = image2[y][x]
if val1!=0 and val2!=0:
newImage[y][x] = (val1 + val2) / 2
但这样做真的很慢。我没有计时,但感觉速度慢了大约100倍。
我还尝试过使用lambda表达式和“map”,但这样做并没有返回一个NumPy数组。
4 个回答
1
在Python中,使用明确的for
循环通常效率很低,不仅仅是在处理numpy
操作时。幸运的是,我们有更快的方法来解决这个问题。如果内存不是问题,这个解决方案相当不错:
import numpy as np
new_image = np.zeros((1024, 1024), dtype=np.int16)
valid = (image1!=0) & (image2!=0)
new_image[valid] = (image1+image2)[valid]
还有一种使用掩码数组的解决方案,它不会创建数组的副本(它们只是原始image1/2
的视图):
m1 = np.ma.masked_equal(image1, 0)
m2 = np.ma.masked_equal(image2, 0)
new_image = (m1+m2).filled(0)
更新:对于大约1000个非零元素的数组,第一个解决方案的速度似乎是第二个的三倍。
2
用原生的Python代码来循环处理数据,通常比使用内置的工具要慢很多,因为后者是用快速的C语言循环实现的。我对NumPy不太了解;你能不能用map()
这个函数,把你两个输入数组的数据转换成输出?如果可以的话,这样应该会更快。
8
试试这个:
newImage = numpy.where(np.logical_and(image1, image2), (image1 + image2) / 2, 0)
如果 image1
和 image2
都不等于零,就计算它们的平均值;如果有一个等于零,就返回零。