Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient summed Area Table Calculation with Numpy

I'm trying to calculate a summed area table of a feature count matrix using python and numpy. Currently I'm using the following code:

def summed_area_table(img):

    table = np.zeros_like(img).astype(int)

    for row in range(img.shape[0]):
        for col in range(img.shape[1]):

            if (row > 0) and (col > 0):
                table[row, col] = (img[row, col] +
                                   table[row, col - 1] +
                                   table[row - 1, col] -
                                   table[row - 1, col - 1])
            elif row > 0:   
                table[row, col] = img[row, col] + table[row - 1, col]
            elif col > 0:
                table[row, col] = img[row, col] + table[row, col - 1]
            else:
                table[row, col] = img[row, col]

    return table

The above code takes about 35 seconds to perform the calculation on a 3200 x 1400 array. Is there any way to use Numpy trick to speed up the computation? I realize the fundamental speed problem lies in the nested python loops, but I don't know how to avoid them.

like image 725
Nick Avatar asked Aug 28 '14 21:08

Nick


1 Answers

There's a NumPy function cumsum for cumulative sums. Applying it twice yields the desired table:

import numpy as np

A = np.random.randint(0, 10, (3, 4))

print A
print A.cumsum(axis=0).cumsum(axis=1)

Output:

[[7 4 7 2]
 [6 9 9 5]
 [6 6 7 6]]
[[ 7 11 18 20]
 [13 26 42 49]
 [19 38 61 74]]

Performance analysis: (https://stackoverflow.com/a/25351344/3419103)

import numpy as np
import time

A = np.random.randint(0, 10, (3200, 1400))

t = time.time()
S = A.cumsum(axis=0).cumsum(axis=1)
print np.round_(time.time() - t, 3), 'sec elapsed'

Output:

0.15 sec elapsed
like image 72
Falko Avatar answered Oct 13 '22 19:10

Falko