Search code examples
pythonopencvnumpypixeleuclidean-distance

Pass coordinates of 2D Numpy pixel array to distance function


I'm working on an image processing program with OpenCV and numpy. For most pixel operations, I'm able to avoid nested for loops by using np.vectorize(), but one of the functions I need to implement requires as a parameter the 'distance from center', or basically the coordinates of the point being processed.

Pseudoexample :

myArr = [[0,1,2]
         [3,4,5]]

def myFunc(val,row,col):
    return [row,col]

f = np.vectorize(myFunc)
myResult = f(myArr,row,col)

I obviously can't get elemX and elemY from the vectorized array, but is there another numpy function I could use in this situation or do I have to use for loops?, Is there a way to do it using openCV?

The function I need to put each pixel through is : f(i, j) = 1/(1 + d(i, j)/L) , d(i,j) being the euclidean distance of the point from the center of the image.


Solution

  • You can get an array of distance from the center using the following lines (which is an example, there are a lot of ways to do this):

        import numpy as np
    
    myArr = np.array([[0,1,2], [3,4,5]])
    
    nx, ny = myArr.shape
    x = np.arange(nx) - (nx-1)/2.  # x an y so they are distance from center, assuming array is "nx" long (as opposed to 1. which is the other common choice)
    y = np.arange(ny) - (ny-1)/2.
    X, Y = np.meshgrid(x, y)
    d = np.sqrt(X**2 + Y**2)
    
    #  d = 
    #  [[ 1.11803399  1.11803399]
    #   [ 0.5         0.5       ]
    #   [ 1.11803399  1.11803399]]
    

    Then you can calculate f(i, j) by:

    f = 1/(1 + d/L)
    


    As an aside, your heavy use of np.vectorize() is a bit dubious. Are you sure it's doing what you want, and did you note the statement from the documentation:

    The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop.

    It's generally better to just write you code in vectorized form (like my line for f above which will work whether L is an array or a scaler), and not use numpy.vectorize(), and these are different things.