scipy.optimize.leastsq官方文档
之前自己用最小二乘进行过球面、柱面和平面拟合,球面和平面效果都很好,但是柱面效果一直不好(对初值十分敏感,迭代过程中经常出现奇异矩阵,也有可能是自己写的算法没有考虑数值误差)。所以采用scipy自带的最小二乘拟合进行曲面拟合,当对初值进行一定限制时,拟合效果很好。

球面拟合

球面方程:
(x−x0)2+(y−y0)2+(z−z0)2=r02(x-x_0)^2+(y-y_0)^2+(z-z_0)^2=r_0^2(x−x0​)2+(y−y0​)2+(z−z0​)2=r02​
误差函数:
F(x0,y0,z0,r0)=(x−x0)2+(y−y0)2+(z−z0)2−r02F(x_0,y_0,z_0,r_0)=(x-x_0)^2+(y-y_0)^2+(z-z_0)^2-r_0^2F(x0​,y0​,z0​,r0​)=(x−x0​)2+(y−y0​)2+(z−z0​)2−r02​
前面为使用leastsq拟合,先定义误差函数,再通过leastsq进行拟合;后面为自己写的代码,直接计算不用赋初值,具体算法参考球面数据拟合算法简介

############   leastsq拟合  ###############
def spherrors(para, points):"""球面拟合误差"""x0, y0, z0, r0 = parareturn (points[:, 0] - x0) ** 2 + (points[:, 1] - y0) ** 2 + (points[:, 2] - z0) ** 2 - r0 ** 2
# 计算点集的x,y,z均值,用于拟合参数初值
xm = np.mean(points[:,0])    # 特征点集x均值
ym = np.mean(points[:,1])
zm = np.mean(points[:,2])
# 最小二乘拟合
tparas = optimize.leastsq(spherrors, [xm, ym, zm, r0], points, full_output=1)
paras = tparas[0]
# 计算球度误差
es = np.mean(np.abs(tparas[2]['fvec'])) / paras[3]    # 'fvec'即为spherrors的值###############    自己写的    ############
def sphere_surface(points):"""球面拟合"""x = points[:, 0]y = points[:, 1]z = points[:, 2]# 计算拟合矩阵A,数组b的参数xm = np.mean(x)ym = np.mean(y)zm = np.mean(z)xym = np.mean(x * y)xzm = np.mean(x * z)yzm = np.mean(y * z)x2m = np.mean(x * x)y2m = np.mean(y * y)z2m = np.mean(z * z)x2ym = np.mean(x * x * y)x2zm = np.mean(x * x * z)y2xm = np.mean(y * y * x)y2zm = np.mean(y * y * z)z2xm = np.mean(z * z * x)z2ym = np.mean(z * z * y)x3m = np.mean(x * x * x)y3m = np.mean(y * y * y)z3m = np.mean(z * z * z)A = np.array([[x2m - xm * xm, xym - xm * ym, xzm - xm * zm], [xym - xm * ym, y2m - ym * ym, yzm - ym * zm],[xzm - xm * zm, yzm - ym * zm, z2m - zm * zm]])b = 0.5 * np.array([x3m - xm * x2m + y2xm - xm * y2m + z2xm - xm * z2m, x2ym - x2m * ym + y3m - ym * y2m + z2ym - ym * z2m,x2zm - x2m * zm + y2zm - y2m * zm + z3m - z2m * zm])# 求解球心s = linalg.solve(A, b)# 求解半径R = np.sqrt(x2m - 2 * s[0] * xm + s[0] ** 2 + y2m - 2 * s[1] * ym + s[1] ** 2 + z2m - 2 * s[2] * zm + s[2] ** 2)return s, R

圆柱拟合

圆柱面方程:
(x−x0)2+(y−y0)2+(z−z0)2−r02=[l(x−x0)+m(y−y0)+n(z−z0)]2(x-x_0)^2+(y-y_0)^2+(z-z_0)^2-r_0^2=[l(x-x_0)+m(y-y_0)+n(z-z_0)]^2(x−x0​)2+(y−y0​)2+(z−z0​)2−r02​=[l(x−x0​)+m(y−y0​)+n(z−z0​)]2
误差函数:
F(x0,y0,z0,l,m,n,r0)=(x−x0)2+(y−y0)2+(z−z0)2−r02−[l(x−x0)+m(y−y0)+n(z−z0)]2F(x_0,y_0,z_0,l,m,n,r_0)=(x-x_0)^2+(y-y_0)^2+(z-z_0)^2-r_0^2-[l(x-x_0)+m(y-y_0)+n(z-z_0)]^2F(x0​,y0​,z0​,l,m,n,r0​)=(x−x0​)2+(y−y0​)2+(z−z0​)2−r02​−[l(x−x0​)+m(y−y0​)+n(z−z0​)]2
圆柱面拟合对初值十分敏感,需要根据已知信息对初值进行限定,此处操作为:根据圆柱面上点公法线(即与所有点法向量点乘和最小的向量)中主分量(最大分量)来减少参数(如公法线中x分量最大,则轴线一定与yz平面相交,则可减少参数x0x_0x0​,同时根据公法线主分量方向估计圆柱的半径)

def xclinerrors(para, points): """法向量x矢量最大,圆柱面拟合误差"""# points为由点集构成的n*3矩阵,每一行为一个点的x,y,z坐标值x0 = 0y0, z0, a0, b0, c0, r0 = parareturn (points[:, 0] - x0) ** 2 + (points[:, 1] - y0) ** 2 + (points[:, 2] - z0) ** 2 - (a0 * (points[:, 0] - x0) + b0 * (points[:, 1] - y0) + c0 * (points[:, 2] - z0)) ** 2 - r0 ** 2def yclinerrors(para, points):"""法向量y矢量最大,圆柱面拟合误差"""y0 = 0x0, z0, a0, b0, c0, r0 = parareturn (points[:, 0] - x0) ** 2 + (points[:, 1] - y0) ** 2 + (points[:, 2] - z0) ** 2 - (a0 * (points[:, 0] - x0) + b0 * (points[:, 1] - y0) + c0 * (points[:, 2] - z0)) ** 2 - r0 ** 2def zclinerrors(para, points):"""法向量z矢量最大,圆柱面拟合误差"""z0 = 0x0, y0, a0, b0, c0, r0 = parareturn (points[:, 0] - x0) ** 2 + (points[:, 1] - y0) ** 2 + (points[:, 2] - z0) ** 2 - (a0 * (points[:, 0] - x0) + b0 * (points[:, 1] - y0) + c0 * (points[:, 2] - z0)) ** 2 - r0 ** 2# 计算点集的x,y,z均值,x,y的范围,用于拟合参数初值
xm = np.mean(points[:,0])    # 特征点集x均值
ym = np.mean(points[:,1])
zm = np.mean(points[:,2])
xrange = np.max(points[:,0]) - np.min(points[:,0])    # 特征点集x范围
yrange = np.max(points[:,1]) - np.min(points[:,1])# 最小二乘拟合
# x分量最大,则法向量必然与yz平面相交,轴点初值中x可设为0
# cnv为公法线
if cnv[0] >= cnv[1] and cnv[0] >= cnv[2]:   tparac = optimize.leastsq(xclinerrors, [ym, zm, cnv[0], cnv[1], cnv[2], yrange/2], points,full_output=1)parac = np.array([0, tparac[0][0], tparac[0][1], tparac[0][2], tparac[0][3], tparac[0][4], tparac[0][5]])# 圆度误差均值ec = np.mean(np.abs(tparac[2]['fvec'])) / parac[6]if cnv[1] >= cnv[0] and cnv[1] >= cnv[2]:tparac = optimize.leastsq(yclinerrors, [xm, zm, cnv[0], cnv[1], cnv[2], xrange/2], points,full_output=1)parac = np.array([tparac[0][0], 0, tparac[0][1], tparac[0][2], tparac[0][3], tparac[0][4], tparac[0][5]])ec = np.mean(np.abs(tparac[2]['fvec'])) / parac[6]if cnv[2] >= cnv[0] and cnv[2] >= cnv[1]:tparac = optimize.leastsq(zclinerrors, [xm, ym, cnv[0], cnv[1], cnv[2], (xrange + yrange) / 2],points,full_output=1)parac = np.array([tparac[0][0], tparac[0][1], 0, tparac[0][2], tparac[0][3], tparac[0][4], tparac[0][5]])ec = np.mean(np.abs(tparac[2]['fvec'])) / parac[6]

############### 自己写的,效果不好,仅供参考
最小二乘原理拟合圆柱计算方法

def cylindrical_surface(pm):"""采用最小二乘法拟合圆柱面"""# pm为由点集构成的n*3矩阵,每一行为一个点的x,y,z坐标值para = np.array([1, 1, 1, 1, 1, 1], dtype=float)m = np.zeros((pm.shape[0], 6), dtype=float)B = np.zeros((pm.shape[0],), dtype=float)for i in range(5):for i in range(pm.shape[0]):x = pm[i, 0]y = pm[i, 1]z = pm[i, 2]x0 = para[0]y0 = para[1]a0 = para[2]b0 = para[3]c0 = para[4]r0 = para[5]z0 = 0f0 = pow(x - x0, 2) + pow(y - y0, 2) + pow(z - z0, 2) - pow((a0 * (x - x0) + b0 * (y - y0) + c0 * (z - z0)), 2) - r0 * r0B[i] = -f0m[i, 0] = (a0 * (a0 * (x - x0) + b0 * (y - y0) + c0 * (z - z0)) - (x - x0)) * 2m[i, 1] = (b0 * (a0 * (x - x0) + b0 * (y - y0) + c0 * (z - z0)) - (y - y0)) * 2m[i, 2] = -(a0 * (x - x0) + b0 * (y - y0) + c0 * (z - z0)) * (x - x0) * 2m[i, 3] = -(a0 * (x - x0) + b0 * (y - y0) + c0 * (z - z0)) * (y - y0) * 2m[i, 4] = -(a0 * (x - x0) + b0 * (y - y0) + c0 * (z - z0)) * (z - z0) * 2m[i, 5] = -2 * r0mt = m.transpose()para = np.dot(np.dot(np.linalg.inv(np.dot(mt, m)), mt), B)return para

##平面拟合
平面方程:
z=a0x+a1y+a2z=a_0x+a_1y+a_2z=a0​x+a1​y+a2​
误差函数:
F(a0,a1,a2)=a0x+a1y+a2−zF(a_0,a_1,a_2)=a_0x+a_1y+a_2-zF(a0​,a1​,a2​)=a0​x+a1​y+a2​−z

def planeerrors(para, points):"""平面误差"""a0, a1, a2 = parareturn a0 * points[:, 0] + a1 * points[:, 1] + a2 - points[:, 2]tparap = optimize.leastsq(planeerrors, [1, 1, 1], points)
para = tparap[0]

python中使用scipy.optimize.leastsq进行球面、圆柱面、平面拟合相关推荐

  1. python 中的 scipy.optimize 最优化功能的一些不足

    python 中的 scipy 也有最优化的功能,体现在里面的 optimize 中,自己简单使用了下,发现它具有以下缺点: 优化算法比较少,有信頼域.单纯形法.BFGS算法等,能够满足不少常规函数的 ...

  2. python中的scipy基础知识_python中SciPy是什么?

    python中Numpy常用于计算二维数组计算,而python的另一个库SciPy库与Numpy有着密切的关系,是需要通过Numpy为基础,同时也是通过Numpy数据来操控科学计算.常见的是插值运算. ...

  3. scipy中的scipy.optimize.curve_fit

    scipy中的scipy.optimize.curve_fit 这里写目录标题 scipy中的scipy.optimize.curve_fit 参数 Return scipy.optimize.``c ...

  4. python中使用scipy.integrate求积分、二重积分、三重积分

    python中使用scipy.integrate求积分.二重积分.三重积分 代码如下: import numpy as np from scipy.integrate import quad, tpl ...

  5. python模块:Scipy.optimize.linprog线性规划求解

    目录 一.模块介绍 二.模块源分析与参数解释 三.实例求解 四.参考 一.模块介绍 1.1模块功能 Scipy.optimize是Scipy中一个用于解决数学模型中优化类模型的子包,该子包中又包含了多 ...

  6. python科学计算——scipy.optimize

    查看全文 http://www.taodudu.cc/news/show-5979774.html 相关文章: python中scipy.optimize_浅谈SciPy中的optimize.mini ...

  7. python中curve fit_scipy.optimize.curve_fit函数用法解析

    在日常数据分析中,免不了要用到数据曲线拟合,而optimize.curve_fit()函数正好满足你的需求 scipy.optimize.curve_fit(f,xdata,ydata,p0=None ...

  8. python中的scipy基础知识_Python机器学习(五十二)SciPy 基础功能

    默认情况下,所有NumPy函数都可以在SciPy(命名空间)中使用.当导入SciPy时,不需要显式地导入NumPy函数.NumPy的主要对象是n次多维数组ndarray,SciPy构建在ndarray ...

  9. python中quad_python scipy integrate.quad用法及代码示例

    计算定积分. 使用Fortran库QUADPACK中的技术将func从a集成到b(可能是无限间隔). 参数: func:{function, scipy.LowLevelCallable}集成的Pyt ...

最新文章

  1. Spark LogisticRegression 逻辑回归之建模
  2. 学习IT技术你需要的是书?视频教程?还是老师?
  3. Android - Android Studio 解决访问被墙的问题
  4. 如何在进程间共享数据
  5. php限制下载文件格式,php下载文件 强制任意文件格式下载
  6. 从 ReactiveCocoa 中能学到什么?不用此库也能学以致用
  7. 【Flink】Flink 操作HDFS报错 hadoop is not in the classpath/dependencies
  8. abd shell关闭所有程序_带你进一步了解“终端”Shell
  9. VDownloader(网页视频下载软件)官方正式版V5.0.4113 | 油管视频下载神器 | 网页视频怎么下载到本地视频?
  10. 微软更新服务器ip地址,微软承认Windows 10更新导致路由等本地IP地址打不开
  11. Java之HTTP长连接
  12. C#编写一个控制台程序,输入一个日期,输出这一天是星期几。
  13. python快速幂算法解决大数取模
  14. DNS服务详解(解析+搭建)
  15. 【开发随机】JAVA+POI+自定义注解+反射构建自定义工具类实现快捷简便的Excel模板化导出(附demo代码)
  16. markdown(Latex)连乘符号
  17. VOIP信号传输过程
  18. 全球最顶级的管理模式全在这了
  19. 仙境传说 v1.0 绿色
  20. 中科院上海药物所等揭示AMPK促进DNA双链损伤修复的新机制

热门文章

  1. 庆祝兔子家的CSDN博客开通 :) 兔家的CAN总线世界
  2. 机器学习读书笔记(二)
  3. 免费使用IntelliJ_IDEA(限在校生)
  4. ubuntu虚拟机 立即使用客户机 灰色
  5. 新品BCM6755A1KFEBG/MT7921LE/MT7921AU WiFi芯片
  6. 彻底理解Python中浅拷贝和深拷贝的区别
  7. 问题1484:小鱼的刷剧时光
  8. OpenGL学习笔记24-Face culling
  9. electron 注册系统快捷键
  10. 预约Oracle OCP认证考试的保姆式流程