【问题标题】:How to quickly sum a range of indexes in multiple arrays in Python?如何在 Python 中快速求和多个数组中的一系列索引?
【发布时间】:2020-05-02 04:47:10
【问题描述】:

我正在尝试使用一个等式重建 HDR 图像,其中我必须对每个 i 值的分子和分母中的 j 个值 (0-15) 求和。有没有更快的方法来做到这一点?也许使用 np.sum?

g 是一个 255 长的一维数组,用于重新映射所有像素值。

lEks 是 15 张图像的日志曝光时间

Z 是一个大小为 [95488, 15] 的数组,第一维是像素索引,第二维是图像编号

def genHDR(Z,g,lEks):

    Zi, Zj = Z.shape        #[95488, 15]
    HDRimage= np.zeros(Zi)

    for i in range(Zi):
        numerator   = 0
        denominator = 0

        for j in range(Zj):
            numerator   +=(Z[i,j])*(g[Z[i,j]] - lEks[j])
            denominator +=(Z[i,j])

        HDRimage[i] = numerator/denominator
    return HDRimage

【问题讨论】:

  • 变量glEks是什么?
  • g 是一个 255 长的数组,用于重新映射像素值,lEks 是 15 张图像的对数曝光时间
  • Numpy 是一个矢量化库(大部分代码都是用 C 编写的,速度非常快)。所以你不要使用 for 循环(在 Python 中非常慢)。假设您有一个数组time=np.arange(0,1,100),即包含 [0,0.01,..,.0.99]。要将函数应用于所有元素,您可以在将 f 定义为某个频率后编写 np.sin(2*np.pi*f*time)。在您的情况下,您可以使用 numpy 函数 np.sum() 而不是添加 for 循环。

标签: python numpy indexing sum equation


【解决方案1】:

可能最好的方法是使用 np.Array.sum(axis=1)。假设 g(Z[i,j]) 调用有效。你实际上甚至不需要任何循环:

import numpy as np

Z = np.random.randint(0,255,(10,15))
g=np.random.randint(0,10,(256))
lEks = np.random.rand((15))

def genHDR(Z,g,lEks):
    numerator = (Z*(g[Z]-lEks.view().reshape((1,)+ lEks.shape))).sum(axis=1)
    denominator = Z.sum(axis=1)
    HDRimage = numerator/denominator
    return HDRimage

【讨论】:

  • 是的。非常优雅。
【解决方案2】:

@Dillman 打败了我。也许您仍然可以使用以下内容来了解​​如何构建它。我喜欢循序渐进地思考。

import numpy as np

Z=  np.random.randint(low=0,high=256,size=(6,3))   # assume just 3 images with 6 pixels each
print(f' Z= {Z}')

lEks=np.random.rand(3)
print(f'lEks = {lEks}')

g0=np.arange(255)   #some example mapping; here from byte to half byte
g= g0//2        # // integer division


npxl,nimage=np.shape(Z)
print(f'npxl={npxl} nimage={nimage}')

# vectorize just one operation at first, easier to visualize
hdr=np.zeros(npxl)

for i in np.arange(npxl):
    #print(Z[i])
    denom=np.sum(Z[i])
    hdr[i]= np.sum(Z[i] *(g[Z[i]]- lEks))/denom 
    # Z[i] is just a vector of length 3, just like lEks

print(hdr)

# this would do it, but still be slower than necessary, as your remaining loop has many more elements that 
# the one we dealt with


# now vectorize the other coordinate (remove the remaining for-loop)
hdr=np.zeros(npxl)
hdr=  np.sum(Z *(g[Z]- lEks), axis=1)/ np.sum(Z,axis=1)   # which axis to sum over is critical
print(hdr)

#final code

def genHDR(Z, g, lEks):
    npxl,nimage=np.shape(Z)
    hdr=np.zeros(npxl)
    hdr=  np.sum(Z *(g[Z]- lEks), axis=1)/ np.sum(Z,axis=1) 
    return hdr


print(genHDR(Z,g,lEks))

输出:

 Z= [[199 101  67]
 [134  16 137]
 [219   5 135]
 [153  19  17]
 [238  41 120]
 [ 93  50 179]]
lEks = [0.57778608 0.18113957 0.85257974]
npxl=6 nimage=3
[72.94714613 63.50130665 91.04028102 62.58551969 90.46303414 65.97390417]
[72.94714613 63.50130665 91.04028102 62.58551969 90.46303414 65.97390417]
[72.94714613 63.50130665 91.04028102 62.58551969 90.46303414 65.97390417]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多