Nir*_*Nir 5 python image pillow
我有一个图像文件,其背景为白色,非白色物体.我想使用python(Pillow)找到对象的中心.
我在c ++中发现了一个类似的问题,但没有可接受的答案 - 我怎样才能找到对象的中心?
类似的问题,但回答中链接断开 - 找到不规则形状多边形中心的最快方法是什么?(回答中断链接)
我也阅读了这个页面,但它没有给我一个有用的食谱 - https://en.wikipedia.org/wiki/Smallest-circle_problem
编辑:我正在使用的当前解决方案是:
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)
Run Code Online (Sandbox Code Playgroud)
Mar*_*ics 10
如果将中心定义为质心,那么虽然CoM可能超出您的形状,但并不困难.您可以将图像解释为2D分布,并且可以使用积分(求和)找到其预期值(CoM).
如果你有numpy它很简单.首先创建一个包含1的numpy数组,其中图像是非白色的,然后使其成为概率分布除以1的总数.
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))
Run Code Online (Sandbox Code Playgroud)
从这一点开始,它变成了基本的概率论.您找到边际分布,然后计算预期值,就好像它是一个离散的概率分布.
# 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))
Run Code Online (Sandbox Code Playgroud)
(cx, cy) 是您正在寻找的CoM.
备注:
m[x, y] = immat[(x, y)] != (255, 255, 255)到m[x, y] = f(immat[(x, y)])哪里f是arbitary(非负值)的功能.np.asarray(im),但是要小心索引没有循环:
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
Run Code Online (Sandbox Code Playgroud)