自定义点拟合最合适的圆

写入拟合点:x与y对应

#输入所需拟合的点
x = r_[20.96, 22.25, 23.51, 24.32, 21.64, 22.94,20.32,19.68,19.07,18.31]
y = r_[23.02, 22.83, 22.34, 21.83, 22.96, 22.61,23.00,22.94,22.82,22.53]

代码如下:

 1 #导入第三方库
 2 import functools
 3 from numpy import *
 4 from scipy import optimize
 5 from matplotlib import pyplot as plt, cm, colors
 6 
 7 legendone  = "Fitting circle"
 8 #输入所需拟合的点
 9 x = r_[20.96, 22.25, 23.51, 24.32, 21.64, 22.94,20.32,19.68,19.07,18.31]
10 y = r_[23.02, 22.83, 22.34, 21.83, 22.96, 22.61,23.00,22.94,22.82,22.53]
11 
12 # 质心坐标
13 x0 = mean(x)
14 y0 = mean(y)
15 
16 #修饰器加以修饰反馈结果
17 def Decorator(s):
18     @functools.wraps(s)
19     def wrapped(*args):
20         wrapped.ncalls +=1
21         return s(*args)
22     wrapped.ncalls = 0
23     return wrapped
24 
25 def R_one(xc, yc):
26     return sqrt((x - xc) ** 2 + (y - yc) ** 2)
27 
28 @Decorator
29 def f_2(c):
30     Ri = R_one(*c)
31     return Ri - Ri.mean()
32 
33 #圆心估计
34 center_estimate = x0, y0
35 center_2, _ = optimize.leastsq(f_2, center_estimate)
36 
37 xc_2, yc_2 = center_2
38 Ri_2       = R_one(xc_2, yc_2)
39 #拟合圆的半径
40 R_2        = Ri_2.mean()
41 residu_2   = sum((Ri_2 - R_2)**2)
42 residu2_2  = sum((Ri_2**2-R_2**2)**2)
43 ncalls_2   = f_2.ncalls
44 #输出列表
45 plist = '%-22s %10.5f %10.5f %10.5f %10d %10.6f %10.6f %10.2f'
46 
47 #输出图
48 plt.close('all')
49 def Drawing_display(residu2=False):
50     plt.figure(figsize=(7.5, 7.5),facecolor='#BBFFFF',dpi=100)
51     plt.axis('equal')
52     theta_fit = linspace(-pi, pi, 180)
53 
54     x_fit2 = xc_2 + R_2 * cos(theta_fit)
55     y_fit2 = yc_2 + R_2 * sin(theta_fit)
56     plt.plot(x_fit2, y_fit2, 'k--', label=legendone, lw=2)
57 
58     plt.plot([xc_2], [yc_2], 'gD', mec='r', mew=1)
59 
60     # 坐标画图
61     plt.xlabel('X')
62     plt.ylabel('Y')
63 
64     # 数据横表
65     plt.plot(x, y, 'ro', label='data', ms=8, mec='b', mew=1)
66     plt.legend(loc='best', labelspacing=0.1)
67     plt.title('Fitting Display Diagram')
68     plt.savefig('拟合展示图%d.jpg' % (2 if residu2 else 1))
69 Drawing_display(residu2=True)
70 plt.show()
71 
72 def main():
73     print("------------圆的拟合结果------------")
74     print("质心坐标:({:.2f},{:.2f})".format(x0,y0))  #保留两位小数
75     print("圆心:({:.2f},{:.2f})".format(xc_2,yc_2))  #保留两位小数
76     print("半径:{:.2f}".format(R_2))   #保留两位小数
77     print(('\n%-22s' + ' %10s' * 7) % tuple('datas Xc Yc Rc nb_calls std(Ri) residu residu2'.split()))
78     print('-' * (22 + 7 * (10 + 1)))
79     print(plist % (legendone, xc_2, yc_2, R_2, ncalls_2, Ri_2.std(), residu_2, residu2_2))
80 if __name__ == '__main__':
81     main()

拟合效果图如图:

 

posted @ 2022-09-11 17:16  一眉师傅  阅读(72)  评论(0编辑  收藏  举报