Speed up iteration over Numpy / OpenCV arrays cv2 image
I have 3 numpy arrays of shape> (500, 500). I am trying to iterate over them at the same time. I tried two different methods, but both are slow.
Here Ix_Ix_blur
, Ix_Iy_blur
and Iy_Iy_blur
are the same size. I am trying to find functions and draw them on an OpenCV image.
Method 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)
It takes about 7 seconds
for a 512 * 512 image
Method 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)
This method also seems to accept 7 seconds
to repeat the same image size.
Is there any other way that I can shorten the time it takes to iterate?
Configuration:
- Ubuntu 12.04
- 3rd generation Core i5 processor.
- RAM 4 GB
- 2GB ATI RADEON GPU (which I disabled)
source to share
You can use Ix_Ix_blur[j, i]
instead of Ix_Ix_blur[j][i]
. Ix_Ix_blur[j][i]
will create a temporary array which is very slow.
To speed up item access with ndarray, you can use the item () method, which returns python's own numeric values, and you don't need to create a temporary array A. Computing with native numeric values is faster than numeric scalars.
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)
For your specific task, there is no need to perform calculations in a loop, you can:
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)
source to share