Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - Find center of object in an image

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

Here's an example image: Moon

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)
like image 568
Nir Avatar asked May 30 '16 06:05

Nir


People also ask

How do you find the center of an object in Python?

To find out the center of an object, you can use the Moments. Threshold the image and get the contours of the object with findContours. Compute the Moments withcv.Moments(arr, binary=0) → moments. As arryou can pass the contours.

How do I find a circle in an image in Python?

Find Circles and Ellipses in an Image using OpenCV | Python. To identify circles, ellipses or in general any shape in which the pixels are connected we use the SimpleBlobDetector() function of OpenCV. In non-technical terms, a blob is understood as a thick liquid drop.

How do you center text on a shape in Python?

Placing a white circle at the center (cX, cY) -coordinates of the shape. Writing the text center near the white circle. To execute our script, just open up a terminal and execute the following command: Figure 3: Looping over each of the shapes individually and then computing the center (x, y)-coordinates for each shape.

How do you find the centroid of an image?

To find the centroid of the image, we generally convert it to binary format and then find its center. is the x coordinate and is the y coordinate of the centroid and denotes the Moment.


1 Answers

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.

result CoM

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) to m[x, y] = f(immat[(x, y)]) where f 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
like image 119
Martin Stancsics Avatar answered Nov 14 '22 21:11

Martin Stancsics