import numpy as np import pandas as pd

# Problem

I have an image, `n`

pixel wide, `m`

pixel tall. Both of these numbers are even. Pixels are squares. Pixel values are in a numpy array.

I need to calculate the distance from each pixel’s centre to the centre of the image. Ie the pixels just next to the centre should have associated values `sqrt(2)/2`

. If the image is like a chess-board, the pixel corresponding to g6 square should have associated distance value should be (2.5^2+1.5^2)^0.5=2.91

# My solution

I have achieved the task by the following code:

image=np.zeros([2,4]) # let's say this is my image df = pd.DataFrame(image) distances = pd.DataFrame( df.apply( lambda row: (row.index+0.5-len(df.index)/2)**2,axis=0).to_numpy()+ df.T.apply( lambda row: (row.index+0.5-len(df.columns)/2)**2,axis=0).T.to_numpy()) .apply(np.sqrt).to_numpy()

`distances`

will be:

array([[1.58113883, 0.70710678, 0.70710678, 1.58113883], [1.58113883, 0.70710678, 0.70710678, 1.58113883]])

As expected.

# Question

Is there a better way? I would appreciate a shorter, more-numpy oriented, or more transparent method.

## Answer

I do not know any specific algorithms to do this except this straightforward implementation in Numpy, that is, using the indices (creates array of indices from shape of array) and linalg.norm (calculates norms) functions. Note we also use broadcasting by indexing new dimensions in `center[:,None,None]`

(necessary because of `indices`

intrinsic output shape).

import numpy as np import pandas as pd # Numpy function def np_function(image): center = np.array([(image.shape[0])/2, (image.shape[1])/2]) distances = np.linalg.norm(np.indices(image.shape) - center[:,None,None] + 0.5, axis = 0) return distances # Pandas function def pd_function(image): df = pd.DataFrame(image) distances = pd.DataFrame( df.apply( lambda row: (row.index+0.5-len(df.index)/2)**2,axis=0).to_numpy()+ df.T.apply( lambda row: (row.index+0.5-len(df.columns)/2)**2,axis=0).T.to_numpy()) .apply(np.sqrt).to_numpy() return distances

For a 4000×6000 image, Numpy’s method is more than one order of magnitude faster than the original function in my computer. You could also just compute the distances from the center to one octant and then copy the results conveniently to the remaining octants (exploiting simmetry), but this will probably be only worth for big images imho.