gpt4 book ai didi

python - "only size-1 arrays can be converted to Python scalars"或 "` x0 ` must have at most 1 dimension"

转载 作者:太空宇宙 更新时间:2023-11-03 21:11:52 25 4
gpt4 key购买 nike

我正在做一个练习,以熟悉 scipy.optimize 中的 Python least_squares

该练习尝试将椭圆拟合到二维点列表中,从而最小化点与椭圆之间的平方距离之和。

也许数学方法不是正确的,但让我们假装它没问题,因为我认为我的困难在其他地方。

这个想法是首先编写一个函数来计算点和椭圆之间的距离,然后在优化器中使用这个函数。

我还将这个距离函数编程为一个最小化问题:给定一个查询点和椭圆的参数方程,我寻找连接查询点和属于椭圆的点的最小长度线段,其长度是所需的距离。

import math
import numpy as np
from scipy.optimize import least_squares

# I would like to fit an ellipse to these points (a point in each row):
p=[
[614.0471123474172,289.51195416538405],
[404.85868232180786,509.3183970173126],
[166.5322099316754,335.6006010213824],
[302.6076456817051,71.14357043842081],
[614.094939200562,285.48762845572804]
]

# This is the x of the parametric equation of an ellipse
# centered at (C_x,C_y), with axis R_x and R_y and angle
# of rotation theta. alpha is the parameter that describe
# the ellipse when going from 0 to 2pi.
def x_e(alpha,R_x,R_y,theta,C_x):
return R_x*math.cos(alpha)*math.cos(theta)-R_y*math.sin(alpha)*math.sin(theta)+C_x
# This is the y
def y_e(alpha,R_x,R_y,theta,C_y):
return R_x*math.cos(alpha)*math.sin(theta)+R_y*math.sin(alpha)*math.cos(theta)+C_y

points = np.array(p)
x=points[:,0]
y=points[:,1]

def residual_for_distance(params,x_q,y_q,R_x,R_y,theta,C_x,C_y):
alpha = params[0]
return (x_q-x_e(alpha,R_x,R_y,theta,C_x))**2+(y_q-y_e(alpha,R_x,R_y,theta,C_y))**2

def ellipse_point_distance(x_q,y_q,R_x,R_y,C_x,C_y,theta):
params_0 = np.array([math.atan2(y_q-C_y,x_q-C_x)])
result = least_squares(residual_for_distance,params_0,args=(x_q,y_q,R_x,R_y,theta,C_x,C_y))
d=math.sqrt(residual_for_distance(result.x,x_q,y_q,R_x,R_y,theta,C_x,C_y))
return d

现在我在一个简单的情况下测试ellipse_point_distance:

x_q=1
y_q=1
R_x=1
R_y=1
C_x=0
C_y=0
theta=0

print(ellipse_point_distance(x_q,y_q,R_x,R_y,C_x,C_y,theta))

我得到了0.414213562373,看起来不错,所以让我们继续解决拟合的最小化问题:

def residual_for_fit(params,x,y):
R_x = params[0]
R_y = params[1]
C_x = params[2]
C_y = params[3]
theta = params[4]
return ellipse_point_distance(x,y,R_x,R_y,C_x,C_y,theta)

params_0 = np.array([227,227,x.mean(),y.mean(),0])
result = least_squares(residual_for_fit,params_0,args=(x,y),verbose=1)

我收到此错误:

Traceback (most recent call last):
File "fit_ellipse.py", line 57, in <module>
result = least_squares(residual_for_fit,params_0,args=(x,y),verbose=1)
File "/home/aj/anaconda2/lib/python2.7/site-packages/scipy/optimize/_lsq/least_squares.py", line 799, in least_squares
f0 = fun_wrapped(x0)
File "/home/aj/anaconda2/lib/python2.7/site-packages/scipy/optimize/_lsq/least_squares.py", line 794, in fun_wrapped
return np.atleast_1d(fun(x, *args, **kwargs))
File "fit_ellipse.py", line 54, in residual_for_fit
return ellipse_point_distance(x,y,R_x,R_y,C_x,C_y,theta)
File "fit_ellipse.py", line 33, in ellipse_point_distance
params_0 = np.array([math.atan2(y_q-C_y,x_q-C_x)])
TypeError: only size-1 arrays can be converted to Python scalars

快速浏览一下 TypeError: only length-1 arrays can be converted to Python scalars while trying to exponentially fit data,我认为我解决了问题:

def ellipse_point_distance_2(x_q,y_q,R_x,R_y,C_x,C_y,theta):
params_0 = np.array([np.arctan2(y_q-C_y,x_q-C_x)])
result = least_squares(residual_for_distance,params_0,args=(x_q,y_q,R_x,R_y,theta,C_x,C_y))
d=math.sqrt(residual_for_distance(result.x,x_q,y_q,R_x,R_y,theta,C_x,C_y))
return d

我刚刚用 np.arctan2 替换了 math.atan2,希望能得到最好的结果:

print(ellipse_point_distance_2(x_q,y_q,R_x,R_y,C_x,C_y,theta))

ellipse_point_distance_2 仍然不错(给出 0.414213562373),所以我们在这里:

def residual_for_fit_2(params,x,y):
R_x = params[0]
R_y = params[1]
C_x = params[2]
C_y = params[3]
theta = params[4]
return ellipse_point_distance_2(x,y,R_x,R_y,C_x,C_y,theta)

params_0 = np.array([227,227,x.mean(),y.mean(),0])
result = least_squares(residual_for_fit_2,params_0,args=(x,y),verbose=1)

但现在我得到了一个不同的错误:

Traceback (most recent call last):
File "fit_ellipse.py", line 76, in <module>
result = least_squares(residual_for_fit_2,params_0,args=(x,y),verbose=1)
File "/home/aj/anaconda2/lib/python2.7/site-packages/scipy/optimize/_lsq/least_squares.py", line 799, in least_squares
f0 = fun_wrapped(x0)
File "/home/aj/anaconda2/lib/python2.7/site-packages/scipy/optimize/_lsq/least_squares.py", line 794, in fun_wrapped
return np.atleast_1d(fun(x, *args, **kwargs))
File "fit_ellipse.py", line 73, in residual_for_fit_2
return ellipse_point_distance_2(x,y,R_x,R_y,C_x,C_y,theta)
File "fit_ellipse.py", line 61, in ellipse_point_distance_2
result = least_squares(residual_for_distance,params_0,args=(x_q,y_q,R_x,R_y,theta,C_x,C_y))
File "/home/aj/anaconda2/lib/python2.7/site-packages/scipy/optimize/_lsq/least_squares.py", line 772, in least_squares
raise ValueError("`x0` must have at most 1 dimension.")
ValueError: `x0` must have at most 1 dimension.

现在我有点困惑......我认为我的问题与矢量化问题有关,但我无法解决它。

最佳答案

在此函数中,您需要更改两行:

def ellipse_point_distance(x_q,y_q,R_x,R_y,C_x,C_y,theta):
# params_0 = np.array([math.atan2(y_q-C_y,x_q-C_x)])
params_0 = np.array(math.atan2(y_q-C_y,x_q-C_x)) # removed inner square brackets
result = least_squares(residual_for_distance,params_0,args=(x_q,y_q,R_x,R_y,theta,C_x,C_y))
# d=math.sqrt(residual_for_distance(result.x,x_q,y_q,R_x,R_y,theta,C_x,C_y))
d=np.sqrt(residual_for_distance(result.x,x_q,y_q,R_x,R_y,theta,C_x,C_y)) # changed from math.sqrt to np.sqrt
return d

我认为你的代码仍然无法工作,但现在它可以正常运行了。如果您无法让 least_squares 执行您想要的操作,您可能需要发布另一个问题。

关于python - "only size-1 arrays can be converted to Python scalars"或 "` x0 ` must have at most 1 dimension",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55011581/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com