加速迭代Numpy数组/OpenCV cv2图像

3
我有三个形状为(500, 500)的numpy数组。我想同时迭代它们。我尝试了两种不同的方法,但都很慢。
这里的"Ix_Ix_blur"、"Ix_Iy_blur"和"Iy_Iy_blur"大小相同。我正在尝试在OpenCV图像上找到特征并绘制它。
方法1:
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)

这需要大约 7秒 来处理大小为512*512的图像。


方法2:

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秒来迭代同样大小的图像。

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

配置:

  • Ubuntu 12.04
  • 第三代 Core i5 处理器
  • 4 GB 内存
  • 2 GB ATI RADEON GPU(我已经关闭了它)
1个回答

4

首先,你可以使用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)

太棒了!我没想到可以这样做。感谢你的答案。 - Froyo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接