4

I have 3 numpy arrays of shape > (500, 500). I am trying to iterate over them simultaneously. I have tried two different methods but both of them are slow.

Here Ix_Ix_blur, Ix_Iy_blur and Iy_Iy_blur are of the same size. I'm trying to find features and draw it on 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)

This takes around 7 seconds for image of size of 512*512


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 take 7 seconds to iterate over the same size of image.

Is there any other way using which I can reduce the time required for iterations?

Configuration:

  • Ubuntu 12.04
  • 3rd Gen core i5 processor
  • 4 GB RAM
  • 2 GB ATI RADEON GPU (which I have turned off)

1 Answer 1

4

First 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 speedup element access with ndarray, you can use item() method, which return python native numeric values, and you don't need to create a temporary array A. Calculation with native numeric values is faster than numpy 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 particular problem, it's not necessary to do the calculation 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)
Sign up to request clarification or add additional context in comments.

1 Comment

This is brilliant. I didn't think of doing it this way. Thanks for the answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.