英文:
fitting an ellipse inside of the boundary of a polygon
问题
I am struggling with fitting the biggest possible ellipse (biggest possible are of the ellipse) inside of a polygon. So the ellipse should not go outside of the polygon border, which is not the case for the common "best fitting ellipse" algorithms. The polygon/desired form is saved as binary mask. (i will enclose one so you can better understand the task).
我正在努力将尽可能大的椭圆(椭圆的最大可能面积)适配到多边形内部。因此,椭圆不应超出多边形边界,这与常见的“最佳拟合椭圆”算法不同。多边形/期望形状保存为二进制掩码(我会附上一个以便更好地理解任务)。
I have already looked for algorithms for this task but was not able to find one that works here.
我已经寻找了这个任务的算法,但未能找到适用的算法。
Do you know any working algorithm (preferrably for python) or have an idea what would be the best approach here or maybe even have a code for this?
你知道任何适用的算法(最好是Python)或者有关于在这里的最佳方法的想法,甚至可能有相关的代码吗?
thank you very much!
英文:
I am struggling with fitting the biggest possible ellipse (biggest possible are of the ellipse) inside of a polygon. So the ellipse should not go outside of the polygon border, which is not the case for the common "best fitting ellipse" algorithms. The polygon/desired form is saved as binary mask. (i will enclose one so you can better understand the task).
I have already looked for algorithms for this task but was not able to find one that works here.
Do you know any working algorithm (preferrably for python) or have an idea what would be the best approach here or maybe even have a code for this?
thank you very much!
答案1
得分: 3
这个问题被称为“最大容纳椭球体积”,可以在任何维度中解决。问题及其解决方案在Boyd和Vandenberghe的《凸优化》书中提出。
以下是Python实现。它使用pycddlib
(cdd
)来获取多边形的H表示,也就是将其写成一组不等式的解决方案Ax <= b
。然后它使用cvxpy
来解决这个问题。
这个实现返回椭圆的形状矩阵B
和其中心d
。这意味着椭圆是形如Bu + d
的点集,其中u
位于单位球中。您可以写成u = [cos(theta), sin(theta)]
,这将得到一个通常用于绘图的椭圆方程。
import cvxpy as cp
import numpy as np
import cdd as pcdd
# 多边形的顶点
pts = np.array([
[0, 0],
[0, 1],
[1, 0]
])
npoints = pts.shape[0]
# 制作点的V表示; 您必须在点前面添加一列1
V = np.column_stack((np.ones(npoints), pts))
mat = pcdd.Matrix(V, number_type='fraction') # 如果可能,使用分数
mat.rep_type = pcdd.RepType.GENERATOR
poly = pcdd.Polyhedron(mat)
# 点的H表示: 获得矩阵A和向量b,使得多边形由Ax <= b定义
H = poly.get_inequalities()
# 获取A和b
G = np.asarray(H[0:])
b = G[:,0]
A = -G[:,1:3]
# 现在我们定义凸优化问题
n = 2 # 维度
# 变量
Bvar = cp.Variable((n, n), symmetric=True) # n x n 对称矩阵
dvar = cp.Variable(n) # 向量
# 约束
constraints = [] # 存储约束
for i in range(npoints):
constraints.append(
cp.norm(Bvar @ A[i,:]) + A[i,:] @ dvar <= b[i]
)
# 目标
objective = cp.Minimize(-cp.log_det(Bvar))
# 问题
problem = cp.Problem(objective, constraints)
# 解决问题
x = problem.solve(solver=cp.SCS)
# 解决方案
variables = problem.solution.primal_vars
print("形状矩阵B是")
print(Bvar.value)
print("中心d是")
print(dvar.value)
from matplotlib import pyplot as plt
from math import pi
polygon = np.append(pts, [pts[0,:]], axis = 0)
B = Bvar.value
d = dvar.value
d = np.transpose(np.repeat([d], 100, axis = 0))
t = np.linspace(0, 2*pi, 100)
u = np.array([np.cos(t) , np.sin(t)])
coords = B @ u + d
f, ax = plt.subplots(1)
ax.plot(polygon[:,0], polygon[:,1])
ax.plot(coords[0,:], coords[1,:] )
ax.grid(color='lightgray', linestyle='--')
plt.show()
英文:
This problem is called the maximum volume inscribed ellipsoid, and can be solved in any dimension. The problem and its solution are presented in Convex optimization book by Boyd & Vandenberghe.
Below is a Python implementation. It uses pycddlib
(cdd
) to get the H-representation of the polygon, that is to say to write it as the solution of a set of inequalities Ax <= b
. Then it uses cvxpy
to solve the problem.
The implementation returns the shape matrix B
of the elliipse and its center d
. That means the ellipse is the set of points of the form Bu + d
for u
in the unit ball. You can write u = [cos(theta), sin(theta)]
and you'll get a usual equation for an ellipse, useful for plotting.
import cvxpy as cp
import numpy as np
import cdd as pcdd
# vertices of the polyhedron
pts = np.array([
[0, 0],
[0, 1],
[1, 0]
])
npoints = pts.shape[0]
# make the V-representation of the points; you have to prepend the points with a column of ones
V = np.column_stack((np.ones(npoints), pts))
mat = pcdd.Matrix(V, number_type='fraction') # use fractions if possible
mat.rep_type = pcdd.RepType.GENERATOR
poly = pcdd.Polyhedron(mat)
# H-representation of the points: obtain matrix A and vector b such that
# the polyhedron is defined by Ax <= b
H = poly.get_inequalities()
# get A and b
G = np.asarray(H[0:])
b = G[:,0]
A = -G[:,1:3]
# now we define the convex optimization problem
n = 2 # dimension
# variables
Bvar = cp.Variable((n, n), symmetric=True) # n x n symmetric matrix
dvar = cp.Variable(n) # vector
# constraints
constraints = [] # to store the constraints
for i in range(npoints):
constraints.append(
cp.norm(Bvar @ A[i,:]) + A[i,:] @ dvar <= b[i]
)
# objective
objective = cp.Minimize(-cp.log_det(Bvar))
# problem
problem = cp.Problem(objective, constraints)
# solve problem
x = problem.solve(solver=cp.SCS)
# solutions
variables = problem.solution.primal_vars
print("The shape matrix B is")
print(Bvar.value)
print("The center d is")
print(dvar.value)
The shape matrix B is
[[ 0.32199634 -0.08628191]
[-0.08628191 0.32195628]]
The center d is
[0.3333573 0.33331871]
from matplotlib import pyplot as plt
from math import pi
polygon = np.append(pts, [pts[0,:]], axis = 0)
B = Bvar.value
d = dvar.value
d = np.transpose(np.repeat([d], 100, axis = 0))
t = np.linspace(0, 2*pi, 100)
u = np.array([np.cos(t) , np.sin(t)])
coords = B @ u + d
f, ax = plt.subplots(1)
ax.plot(polygon[:,0], polygon[:,1])
ax.plot(coords[0,:], coords[1,:] )
ax.grid(color='lightgray', linestyle='--')
ax.show()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论