【问题标题】:Speed up iteration over Numpy arrays / OpenCV cv2 image加速 Numpy 数组 / OpenCV cv2 图像的迭代
【发布时间】:2013-01-21 10:07:11
【问题描述】:

我有 3 个形状 > (500, 500) 的 numpy 数组。我正在尝试同时迭代它们。我尝试了两种不同的方法,但它们都很慢。

这里Ix_Ix_blurIx_Iy_blurIy_Iy_blur 大小相同。我正在尝试查找特征并将其绘制在 OpenCV 图像上。


方法一:

for i in xrange (Ix_Ix_blur.shape[1]):
    for j in xrange(Ix_Ix_blur.shape[0]):
        A = np.array([ [Ix_Ix_blur[j][i], Ix_Iy_blur[j][i]], 
            [Ix_Iy_blur[j][i], Iy_Iy_blur[j][i]] ])
        detA = (A[0][0]*A[1][1])-(A[0][1]*A[1][0])
        traceA = A[0][0]+A[1][1]

        harmonic_mean = detA/traceA
        if(harmonic_mean > thresh):
            cv2.circle(img, (i,j), 1, (0, 0, 255), -1, 8)

对于大小为 512*512 的图像,这大约需要 7 seconds


方法二:

Ix_Iy_blur_iter = np.nditer(Ix_Iy_blur)
Iy_Iy_blur_iter = np.nditer(Iy_Iy_blur)
Ix_Ix_blur_iter = np.nditer(Ix_Ix_blur)

while(not Ix_Iy_blur_iter.finished):
    try:
        A = np.array([[Ix_Ix_blur_iter.next(), Ix_Iy_blur_iter.next()],[Ix_Iy_blur_iter.value, Iy_Iy_blur_iter.next()]])
    except StopIteration:
        break
    detA = (A[0][0]*A[1][1])-(A[0][1]*A[1][0])
    traceA = A[0][0]+A[1][1]

    harmonic_mean = detA/traceA
    if(harmonic_mean > thresh):
        i = Ix_Ix_blur_iter.iterindex/Ix.shape[0]
        j = Ix_Ix_blur_iter.iterindex - Ix.shape[0]*i
        cv2.circle(img, (j,i), 1, (0, 0, 255), -1, 8)

这种方法似乎也需要7 seconds 来迭代相同大小的图像。

有没有其他方法可以减少迭代所需的时间?

配置:

  • Ubuntu 12.04
  • 第三代核心 i5 处理器
  • 4 GB 内存
  • 2 GB ATI RADEON GPU(我已关闭)

【问题讨论】:

    标签: python performance opencv numpy iteration


    【解决方案1】:

    首先您可以使用Ix_Ix_blur[j, i] 代替Ix_Ix_blur[j][i]Ix_Ix_blur[j][i] 会创建一个非常慢的临时数组。

    使用 ndarray 来加速元素访问,你可以使用 item() 方法,它返回 python 原生数值,你不需要创建一个临时数组 A。使用原生数值计算比 numpy 标量更快。

    for i in xrange (Ix_Ix_blur.shape[1]):
        for j in xrange(Ix_Ix_blur.shape[0]):
            a, b, c = Ix_Ix_blur.item(j, i), Ix_Iy_blur.item(j, i), Iy_Iy_blur.item(j, i)
            detA = a*c - b*b
            traceA = a + c
            harmonic_mean = detA/traceA
            if harmonic_mean > thresh:
                cv2.circle(img, (i,j), 1, (0, 0, 255), -1, 8)
    

    对于你的具体问题,不需要循环计算,你可以:

    detA = Ix_Ix_blur * Iy_Iy_blur - Ix_Iy_blur**2
    traceA = Ix_Ix_blur + Iy_Iy_blur
    harmonic_mean = detA / traceA
    for j, i in np.argwhere(harmonic_mean > thresh):
        cv2.circle(img, (i,j), 1, (0, 0, 255), -1, 8)
    

    【讨论】:

    • 这太棒了。我没想过这样做。感谢您的回答。
    猜你喜欢
    • 2021-12-09
    • 2011-10-03
    • 2015-12-12
    • 1970-01-01
    • 2021-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    相关资源
    最近更新 更多