srcerer
srcerer

Reputation: 1098

Find distance between all pairs of pixels in an image

Question

I have a numpy.array of shape (H, W), storing pixel intensities of an image. I want to generate a new array of shape (H, W, H, W), which stores the Euclidean distance between each pair of pixels in the image (the "spatial" distance between the pixels; not the difference in their intensities).

Solution attempt

The following method does exactly what I want, but very slowly. I'm looking for a fast way to do this.

d = numpy.zeros((H, W, H, W)) # array to store distances.
for x1 in range(H):
    for y1 in range(W):
        for x2 in range(H):
            for y2 in range(W):
                d[x1, y1, x2, y2] = numpy.sqrt( (x2-x1)**2 + (y2-y1)**2 )

Extra details

Here are more details for my problem. A solution to the simpler problem above would probably be enough for me to figure out the rest.

Upvotes: 5

Views: 870

Answers (1)

Divakar
Divakar

Reputation: 221504

We can setup open grids with 1D ranged arrays using np.ogrid, which could be operated upon in the same iterator notation for a vectorized solution and this will leverage broadcasting for the perf. boost :

X1,Y1,X2,Y2 = np.ogrid[:H,:W,:H,:W]
d_out = numpy.sqrt( (X2-X1)**2 + (Y2-Y1)**2 )

To save on two open grids :

X,Y = np.ogrid[:H,:W]
d_out = numpy.sqrt( (X[:,:,None,None]-X)**2 + (Y[:,:,None,None]-Y)**2 )

If we are working with large arrays, consider using numexpr for further boost :

import numexpr as ne

d_out = ne.evaluate('sqrt( (X2-X1)**2 + (Y2-Y1)**2 )')

Upvotes: 3

Related Questions