加速遍历Numpy数组/OpenCV cv2图像
我有三个形状都大于 (500, 500) 的 numpy 数组。我想同时对它们进行遍历。但是我尝试了两种不同的方法,结果都很慢。
这里的 Ix_Ix_blur
、Ix_Iy_blur
和 Iy_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 秒
。
方法二:
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 显卡(我已经关闭了)
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)