Search code examples
pythonimage-processingscikit-image

Finding the center of mass in an image


Here is my image: enter image description here

I want to find the center of mass in this image. I can find the approximate location of the center of mass by drawing two perpendicular lines as shown in this image: enter image description here

I want to find it using an image processing tool in python. I have a little experience in the image processing library of python (scikit-image) but, I am not sure if this library could help finding the center of mass in my image. I was wondering if anybody could help me to do it. I will be happy if it is possible to find the center of mass in my image using any other library in python. Thanks in advance for your help!


Solution

  • skimage.measure.regionprops will do what you want. Here's an example:

    import imageio as iio
    from skimage import filters
    from skimage.color import rgb2gray  # only needed for incorrectly saved images
    from skimage.measure import regionprops
    
    image = rgb2gray(iio.imread('eyeball.png'))
    threshold_value = filters.threshold_otsu(image)
    labeled_foreground = (image > threshold_value).astype(int)
    properties = regionprops(labeled_foreground, image)
    center_of_mass = properties[0].centroid
    weighted_center_of_mass = properties[0].weighted_centroid
    
    print(center_of_mass)
    

    On my machine and with your example image, I get (228.48663375508113, 200.85290046969845).

    We can make a pretty picture:

    import matplotlib.pyplot as plt
    from skimage.color import label2rgb
    
    colorized = label2rgb(labeled_foreground, image, colors=['black', 'red'], alpha=0.1)
    fig, ax = plt.subplots()
    ax.imshow(colorized)
    # Note the inverted coordinates because plt uses (x, y) while NumPy uses (row, column)
    ax.scatter(center_of_mass[1], center_of_mass[0], s=160, c='C0', marker='+')
    plt.show()
    

    That gives me this output:

    eye center of mass

    You'll note that there's some bits of foreground that you probably don't want in there, like at the bottom right of the picture. That's a whole nother answer, but you can look at scipy.ndimage.label, skimage.morphology.remove_small_objects, and more generally at skimage.segmentation.