Search code examples
pythonnumpyimage-processing

Finding the center of mass of an image


enter image description hereI have a grey scale image and would like to find the centre of mass (centre of intensity) of this image. I don't want to find the mean value across of each axis.

So I have a 2D array which represents the intensity of this image along the horizontal and vertical axis. The centre of mass is obviously where the white dot is but i don't manage to find a way to calculate it's coordinates.

The results I obtain are always wrong.[My results are 750 along the horizontal line and 454 along the vertical. The white dot centre coordinates are 520 along the horizontal axis and 430 along the vertical ! enter image description here

Here is what I tried :

img is the 2D array which represents the intensity of this image. Its a 1024 row, 1280 columns array. How can i find the centre of mass of this image pls ?

intensite_total = np.sum(img)#This contains the sum of each element from the img matrix

X = np.linspace(0,1023,1024)
print(X)
print(np.shape(X))
print(np.shape(X))

x_bary = np.sum(np.dot(X,img))/intensite_total

print(x_bary)


print("YYYYYYYYYYYYYY")

Y = np.linspace(0,1279,1280)
print(Y)
print(np.shape(Y))
print(np.shape(np.dot(img,Y)))

y_bary = np.sum(np.dot(img,Y))/intensite_total

print(y_bary)

Solution

  • The center of mass is found by computing its integral. For this you need two coordinate arrays, weight the data with the coordinate arrays and sum:

    import numpy as np
    
    image = np.random.random((100, 200))
    
    x = np.arange(image.shape[1])
    y = np.arange(image.shape[0])
    xx, yy = np.meshgrid(x, y)
    
    A = image.sum()
    
    # Center of mass
    x_cms = (xx * image).sum() / A
    y_cms = (yy * image).sum() / A
    
    print(x_cms, y_cms)
    

    Which prints:

    99.30012423254516 49.62527469708466
    

    UPDATE:

    I double checked and this gives the same result as your code:

    A = np.sum(image)
    
    X = np.linspace(0, image.shape[1] - 1, image.shape[1])
    
    x_cms = np.sum(np.dot(image, X)) / A
    
    Y = np.linspace(0, image.shape[0] - 1, image.shape[0])
    
    y_cms = np.sum(np.dot(Y, image)) / A
    print(x_cms, y_cms)
    

    Which prints:

    99.30012423254516 49.62527469708466
    

    UPDATE 2:

    I took a closer look at the data and plotting on logarithmic scale, one can see that the background is not empty:

    enter image description here

    A simple threshold of the data like image[image < 20] = 0, leads to the expected result:

    521.9619304953782 430.8132321823475
    

    I hope this helps!