为什么这个numpy数组操作这么慢?

0 投票
4 回答
1399 浏览
提问于 2025-04-16 15:12

我是一名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)

如果 image1image2 都不等于零,就计算它们的平均值;如果有一个等于零,就返回零。

撰写回答