Python - Find center of object in an image
If you define center as Center of Mass, then it is not difficult, although the CoM can be outside of your shape. You can interpret your image as a 2D distribution, and you can find its expected value (CoM) using integration (summation).
If you have numpy it is quite simple. First create a numpy array containing 1 where your image is non-white, then to make it a probability distribution divide it by the total number of ones.
from PIL import Image
import numpy as np
im = Image.open('image.bmp')
immat = im.load()
(X, Y) = im.size
m = np.zeros((X, Y))
for x in range(X):
for y in range(Y):
m[x, y] = immat[(x, y)] != (255, 255, 255)
m = m / np.sum(np.sum(m))
From this point on it turns into basic probability theory. You find the marginal distributions, then you calculate the expected values as if it was a discrete probability distribution.
# marginal distributions
dx = np.sum(m, 1)
dy = np.sum(m, 0)
# expected values
cx = np.sum(dx * np.arange(X))
cy = np.sum(dy * np.arange(Y))
(cx, cy)
is the CoM you are looking for.
Remarks:
- If you do not have numpy, you can still do it. It is just a bit more tedious as you have to do the summations by loops / comprehensions.
- This method can easily be extended if you want to assign a 'mass' based on color. You just have to change
m[x, y] = immat[(x, y)] != (255, 255, 255)
tom[x, y] = f(immat[(x, y)])
wheref
is an arbitary (non-negative valued) function. - If you want to avoid the double loop, you can us
np.asarray(im)
, but then be careful with the indices
No loops:
m = np.sum(np.asarray(im), -1) < 255*3
m = m / np.sum(np.sum(m))
dx = np.sum(m, 0) # there is a 0 here instead of the 1
dy = np.sum(m, 1) # as np.asarray switches the axes, because
# in matrices the vertical axis is the main
# one, while in images the horizontal one is
# the first
Related videos on Youtube
Nir
Automation software engineer and team leader at Waves Audio. Python is the main language that I code in. I'm also a sound engineer and a saxophone player.
Updated on June 04, 2022Comments
-
Nir almost 2 years
I have an image file that's has a white background with a non-white object. I want to find the center of the object using python (Pillow).
I have found a similar question in c++ but no acceptable answer - How can I find center of object?
Similar question, but with broken links in answer - What is the fastest way to find the center of an irregularly shaped polygon? (broken links in answer)
I also read this page but it doesn't give me a useful recipe - https://en.wikipedia.org/wiki/Smallest-circle_problem
Edit: The current solution I'm using is this:
def find_center(image_file): img = Image.open(image_file) img_mtx = img.load() top = bottom = 0 first_row = True # First we find the top and bottom border of the object for row in range(img.size[0]): for col in range(img.size[1]): if img_mtx[row, col][0:3] != (255, 255, 255): bottom = row if first_row: top = row first_row = False middle_row = (top + bottom) / 2 # Calculate the middle row of the object left = right = 0 first_col = True # Scan through the middle row and find the left and right border for col in range(img.size[1]): if img_mtx[middle_row, col][0:3] != (255, 255, 255): left = col if first_col: right = col first_col = False middle_col = (left + right) / 2 # Calculate the middle col of the object return (middle_row, middle_col)
-
user20160 almost 8 yearsPossible duplicate of What is the fastest way to find the center of an irregularly shaped polygon?
-
Nir almost 8 years@user20160 Unfortunately the mentioned answer has broken links so again - no usable code
-
-
PaulDong about 7 yearsreally good solution with clean code. Can I suggest to add a link to the intuition behind "You find the marginal distributions, then you calculate the expected values as if it was a discrete probability distribution."? I think it makes sense, but may not be as approachable to ppl who are not familiar with probability theory (which I think is beautiful).