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

发布于 2024-10-30 05:31:07 字数 621 浏览 8 评论 0原文

我是一个 python 初学者,我正在尝试对形状为 (1024,1024) 的两个 NumPy 2D 数组进行平均。这样做非常快:

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 数组。

I am a python beginner and I am trying to average two NumPy 2D arrays with shape of (1024,1024). Doing it like this is quite fast:

newImage = (image1 + image2) / 2

But now the images have a "mask" that invalidate certain elements if set to zero. That means if one of the elements is zero, the resulting element should also be zero. My trivial solution is:

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

But this is really slow. I did not time it, but it seems to be slower by a factor of 100.

I also tried using a lambda operator and "map", but this does not return a NumPy array.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

春花秋月 2024-11-06 05:31:07

试试这个:

newImage = numpy.where(np.logical_and(image1, image2), (image1 + image2) / 2, 0)

如果 image1image2 都不为零,则取其平均值,否则为零。

Try this:

newImage = numpy.where(np.logical_and(image1, image2), (image1 + image2) / 2, 0)

Where none of image1 and image2 equals zero, take their mean, otherwise zero.

惟欲睡 2024-11-06 05:31:07

使用本机 Python 代码循环通常比使用循环慢得多
使用快速 C 循环的内置工具。我对 NumPy 不熟悉;能
您使用 map() 将两个输入数组转换为
输出?如果是这样的话,应该会更快。

Looping with native Python code is generally much slower than using
built-in tools that use fast C loops. I'm not familiar with NumPy; can
you use map() to do a transformation from your two input arrays to
the output? If so, that should be faster.

嘿嘿嘿 2024-11-06 05:31:07

一般来说,显式 for 循环在 Python 中效率非常低,不仅对于 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 个非零条目的数组,第一个解决方案似乎比第二个解决方案快 3 倍。

Explicit for loops are very inefficient in Python in general, not only for numpy operations. Fortunately, there are faster ways to solve our problem. If memory is not an issue, this solution is quite good:

import numpy as np
new_image = np.zeros((1024, 1024), dtype=np.int16)
valid = (image1!=0) & (image2!=0)
new_image[valid] = (image1+image2)[valid]

Another solution using masked arrays, which do not create copies of the arrays (they represent views of the original image1/2:

m1 = np.ma.masked_equal(image1, 0)
m2 = np.ma.masked_equal(image2, 0)
new_image = (m1+m2).filled(0)

Update: The first solution seems to be 3 times faster than the second for arrays with about 1000 non-zero entries.

仅此而已 2024-11-06 05:31:07

numpy 数组访问操作充其量看起来很慢。我看不出有什么理由。通过构造一个简单的例子就可以清楚地看到:

    import numpy
    # numpy version
    def at(s,n):
      t1=time.time()
      a=numpy.zeros(s,dtype=numpy.int32)
      for i in range(n):
        a[i%s]=n
      t2=time.time()
      return t2-t1
    # native version
    def an(s,n):
      t1=time.time()
      a=[(i) for i in range(s)]
      for i in range(n):
        a[i%s]=n
      t2=time.time()
      return t2-t1

    # test
    [at(100000,1000000),an(100000,1000000)]

结果:[0.21972250938415527, 0.15950298309326172]

numpy array access operation seems slow at best. I can't see any reason for it. You can clearly see it by constructing a simple example:

    import numpy
    # numpy version
    def at(s,n):
      t1=time.time()
      a=numpy.zeros(s,dtype=numpy.int32)
      for i in range(n):
        a[i%s]=n
      t2=time.time()
      return t2-t1
    # native version
    def an(s,n):
      t1=time.time()
      a=[(i) for i in range(s)]
      for i in range(n):
        a[i%s]=n
      t2=time.time()
      return t2-t1

    # test
    [at(100000,1000000),an(100000,1000000)]

Result: [0.21972250938415527, 0.15950298309326172]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文