切比雪夫(最小区域法)球拟合算法

36 篇文章 0 订阅
21 篇文章 0 订阅

欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。

本期话题:切比雪夫(最小区域法)球拟合算法

相关背景和理论
点击前往
主要介绍了应用背景和如何转化成线性规划问题

在这里插入图片描述

球拟合输入和输出要求

输入

  1. 10到631个点,全部采样自球附近上。
  2. 每个点3个坐标,坐标精确到小数点后面20位。
  3. 坐标单位是mm, 范围[-500mm, 500mm]。

输出

  1. 1点X0表示 球心,用三个坐标表示。
  2. 球半径r。
  3. 球度F,所有点到球面距离最大的2倍。

精度要求

  1. C点到标准球心距离不能超过0.0001mm。
  2. r与标准半径的差不能超过0.0001mm。
  3. F与标准球度误差不能超过0.00001mm。

球优化标函数

根据论文,球拟合转化成数学表示如下:

球参数化表示

  1. 球心为1点X0 = (x0, y0, z0)。
  2. 半径r。

球方程 ( x − x 0 ) 2 + ( y − y 0 ) 2 + ( z − z 0 ) 2 = r 2 球方程 (x-x_0)^2+(y-y_0)^2+(z-z_0)^2=r^2 球方程(xx0)2+(yy0)2+(zz0)2=r2

点到球距离

第i个点 pi(xi, yi, zi)。

根据点乘得到距离

d i = ∥ ( p i − X 0 ) ∥ − r d_i =\left \| (p_i-X_0) \right \|-r di=(piX0)r

展开一下:

d i = r i − r d_i = r_i -r di=rir

r i = ( x i − x 0 ) 2 + ( y i − y 0 ) 2 + ( z i − z 0 ) 2 r_i = \sqrt{(x_i-x_0)^2 + (y_i-y_0)^2+(z_i-z_0)^2} ri=(xix0)2+(yiy0)2+(ziz0)2

优化能量方程

能量方程 H = f ( X 0 , r ) = max ⁡ 1 n ∣ d i ∣ H=f(X0, r)=\displaystyle \max_1^n {|d_i|} H=f(X0,r)=1maxndi

上式是一个4函数,X0, r是未知量,拟合球的过程也可以理解为优化X0, r使得方程H最小。

转化为线性规划

设 a = ( x 0 , y 0 , z 0 , r ) , d i = F ( x i ;   a ) , 引入 Γ = M A X i = 1 n    ∣ d i ∣ 设a=(x_0, y_0, z_0, r), d_i=F(x_i;\ a), 引入\Gamma=\overset n{\underset {i=1}{MAX}}\;|d_i| a=(x0,y0,z0,r),di=F(xi; a),引入Γi=1MAXndi

根据上述定义,可以将原来的最值问题转化为下述条件

对于所有点应该满足

F ( x i ;   a ) ≤ Γ , ( F ( x i ;   a ) > 0 ) F(x_i;\ a)\le \Gamma, (F(x_i;\ a)>0) F(xi; a)Γ,(F(xi; a)>0)

− F ( x i ;   a ) ≤ Γ , ( F ( x i ;   a ) < 0 ) -F(x_i;\ a)\le \Gamma, (F(x_i;\ a)<0) F(xi; a)Γ,(F(xi; a)<0)

我们可以通过小量迭代慢慢减小Γ

m a x      Δ Γ s . t .     F ( x i , a ) + J Δ a ≤ Γ − Δ Γ , ( i = 1 , 2... n )           − ( F ( x i , a ) + J Δ a ) ≤ Γ − Δ Γ , ( i = 1 , 2... n ) Δ Γ ≥ 0 \begin {array}{c}max \ \ \ \ \Delta {\Gamma}\\ s.t.\ \ \ F(x_i, a) + J\Delta a \le \Gamma -\Delta \Gamma, (i=1,2...n)\\ \ \ \ \ \ \ \ \ \ -(F(x_i, a) + J\Delta a) \le \Gamma -\Delta \Gamma, (i=1,2...n)\\ \Delta \Gamma \ge0\end{array} max    ΔΓs.t.   F(xi,a)+JΔaΓΔΓ,(i=1,2...n)         (F(xi,a)+JΔa)ΓΔΓ,(i=1,2...n)ΔΓ0

上述条件不需要管 F ( x i , a ) + J Δ a 正负情况,若 F ( x i , a ) + J Δ a 为正 − ( F ( x i , a ) + J Δ a ) ≤ Γ − Δ Γ 必成立,反之亦然。 上述条件不需要管F(x_i, a) + J\Delta a正负情况,若F(x_i, a) + J\Delta a为正-(F(x_i, a) + J\Delta a) \le \Gamma -\Delta \Gamma必成立,反之亦然。 上述条件不需要管F(xi,a)+JΔa正负情况,若F(xi,a)+JΔa为正(F(xi,a)+JΔa)ΓΔΓ必成立,反之亦然。
求解出以后更新a, Γ。

对线性规划模型标准化

需要对 Δ x 0 , Δ y 0 , Δ z 0 , Δ r 拆解,要求变量都要大于等于 0 需要对\Delta x_0, \Delta y_0, \Delta z_0, \Delta r 拆解,要求变量都要大于等于0 需要对Δx0,Δy0,Δz0,Δr拆解,要求变量都要大于等于0

m a x      Δ Γ s . t .     J i ⋅ [ Δ x 0 + - Δ x 0 - Δ y 0 + - Δ y 0 - Δ z 0 + - Δ z 0 - Δ r + − Δ r − ] + Δ Γ ≤ Γ - d i , ( i = 1 , 2... n )        − J i ⋅ [ Δ x 0 + - Δ x 0 - Δ y 0 + - Δ y 0 - Δ z 0 + - Δ z 0 - Δ r + − Δ r − ] + Δ Γ ≤ Γ + d i , ( i = 1 , 2... n ) Δ x 0 + , Δ x 0 − , Δ y 0 + , Δ y 0 − , Δ z 0 + , Δ z 0 - , Δ r , Δ Γ ≥ 0 ( 1 ) \begin {array}{c}max \ \ \ \ \Delta {\Gamma}\\ s.t.\ \ \ J_i \cdot \begin {bmatrix} \Delta x_0^+-\Delta x_0^-\\ \Delta y_0^+-\Delta y_0^-\\\Delta z_0^+-\Delta z_0^-\\ \Delta r^+- \Delta r^- \end{bmatrix} +\Delta \Gamma\le \Gamma-d_i, (i=1,2...n)\\\\ \ \ \ \ \ \ -J_i \cdot \begin {bmatrix} \Delta x_0^+-\Delta x_0^-\\ \Delta y_0^+-\Delta y_0^-\\\Delta z_0^+-\Delta z_0^-\\ \Delta r^+- \Delta r^- \end{bmatrix}+\Delta \Gamma\le \Gamma+d_i, (i=1,2...n)\\ \Delta x_0^+, \Delta x_0^-, \Delta y_0^+, \Delta y_0^-, \Delta z_0^+,\Delta z_0^-,\Delta r, \Delta \Gamma \ge0\end{array} (1) max    ΔΓs.t.   Ji Δx0+Δx0Δy0+Δy0Δz0+Δz0Δr+Δr +ΔΓΓdi,(i=1,2...n)      Ji Δx0+Δx0Δy0+Δy0Δz0+Δz0Δr+Δr +ΔΓΓ+di,(i=1,2...n)Δx0+,Δx0,Δy0+,Δy0,Δz0+,Δz0,Δr,ΔΓ0(1)

算法描述

Ji, di的计算。

对4个未知数求导结果如下:

∂ d i ∂ x 0 = 1 2 ( x i − x 0 ) 2 + ( y i − y 0 ) 2 + ( z i − z 0 ) 2 ⋅ ( x i − x 0 ) ⋅ − 1 = − ( x i − x 0 ) / r i \frac {\partial d_i} {\partial x_0}=\frac {1} {2 \sqrt{(x_i-x_0)^2 + (y_i-y_0)^2+(z_i-z_0)^2}}\cdot(x_i-x_0)\cdot -1 = -(x_i-x_0)/r_i x0di=2(xix0)2+(yiy0)2+(ziz0)2 1(xix0)1=(xix0)/ri

∂ d i ∂ y 0 = 1 2 ( x i − x 0 ) 2 + ( y i − y 0 ) 2 + ( z i − z 0 ) 2 ⋅ ( y i − y 0 ) ⋅ − 1 = − ( y i − y 0 ) / r i \frac {\partial d_i} {\partial y_0}=\frac {1} {2 \sqrt{(x_i-x_0)^2 + (y_i-y_0)^2+(z_i-z_0)^2}}\cdot(y_i-y_0)\cdot -1 = -(y_i-y_0)/r_i y0di=2(xix0)2+(yiy0)2+(ziz0)2 1(yiy0)1=(yiy0)/ri

∂ d i ∂ z 0 = 1 2 ( x i − x 0 ) 2 + ( y i − y 0 ) 2 + ( z i − z 0 ) 2 ⋅ ( z i − z 0 ) ⋅ − 1 = − ( z i − z 0 ) / r i \frac {\partial d_i} {\partial z_0}=\frac {1} {2 \sqrt{(x_i-x_0)^2 + (y_i-y_0)^2+(z_i-z_0)^2}}\cdot(z_i-z_0)\cdot -1 = -(z_i-z_0)/r_i z0di=2(xix0)2+(yiy0)2+(ziz0)2 1(ziz0)1=(ziz0)/ri

∂ d i ∂ r = − 1 \frac {\partial d_i} {\partial r}=-1 rdi=1

一次迭代过程

  1. 确定球初值,Γ,使用高斯拟合点击前往

  2. 根据上述公式(1)构建线性规划方程

  3. 求解 Δ p \Delta p Δp

  4. 更新解
    x 0 = x 0 + p x 0 y 0 = y 0 + p y 0 z 0 = z 0 + p z 0 r = r + p r Γ = Γ − Δ Γ \begin {array}{c} x_0 = x_0+p_{x_0} \\y_0 = y_0+p_{y_0} \\z_0 = z_0+p_{z_0} \\ r=r+p_r \\ \Gamma = \Gamma-\Delta \Gamma \end {array} x0=x0+px0y0=y0+py0z0=z0+pz0r=r+prΓ=ΓΔΓ

  5. 重复2直到收敛

最后,输出时F=2*Γ

代码实现

代码链接:https://gitcode.com/chenbb1989/3DAlgorithm/blob/master/CBB3DAlgorithm/Fitting/chebyshev/SphereFitter.cpp

拟合代码

#include "SphereFitter.h"
#include "../gauss/SphereFitter.h"
#include <algorithm>
#include <Eigen/Dense>


namespace Chebyshev {
	double SphereFitter::F(Fitting::Sphere sphere, const Point& p)
	{
		auto de = p - sphere.center;
		return de.norm() - sphere.r;
	}

	double SphereFitter::GetError(Fitting::Sphere sphere, const std::vector<Eigen::Vector3d>& points)
	{
		double err = 0;
		for (auto& p : points) {
			err = std::max(err, abs(F(sphere, p)));
		}

		return err;
	}

	Fitting::Matrix SphereFitter::Jacobi(const std::vector<Eigen::Vector3d>& points)
	{
		Fitting::Matrix J(points.size(), 4);
		for (int i = 0; i < points.size(); ++i) {
			auto  p =  points[i] - sphere.center;
			J(i, 0) = -p.x() / p.norm();
			J(i, 1) = -p.y() / p.norm();
			J(i, 2) = -p.z() / p.norm();
			J(i, 3) = -1;
		}
		return J;
	}

	void SphereFitter::beforHook(const std::vector<Eigen::Vector3d>& points)
	{}

	void SphereFitter::afterHook(const Eigen::VectorXd& xp)
	{
		sphere.center += Eigen::Vector3d(xp(0), xp(1), xp(2));
		sphere.r += xp(3);
		gamma -= xp(4);
	}
	Eigen::VectorXd SphereFitter::getDArray(const std::vector<Eigen::Vector3d>& points)
	{
		Eigen::VectorXd D(points.size());
		for (int i = 0; i < points.size(); ++i)D(i) = F(sphere, points[i]);
		return D;
	}
	bool SphereFitter::GetInitFit(const std::vector<Eigen::Vector3d>& points)
	{
		if (points.size() < 4)return false;
		Fitting::FittingBase* fb = new Gauss::SphereFitter();
		fb->Fitting(points, &sphere);
		delete fb;

		gamma = GetError(sphere, points);
		return true;
	}
	double SphereFitter::F(const Eigen::Vector3d& p)
	{
		return Chebyshev::SphereFitter::F(sphere, p);
	}
	double SphereFitter::GetError(const std::vector<Eigen::Vector3d>& points)
	{
		return Chebyshev::SphereFitter::GetError(sphere, points);
	}
	void SphereFitter::Copy(void* ele)
	{
		memcpy(ele, &sphere, sizeof(Fitting::Sphere));
	}
	SphereFitter::SphereFitter()
	{
		ft = Fitting::FittingType::CHEBYSHEV;
	}
}

测试结果

https://gitcode.com/chenbb1989/3DAlgorithm/blob/master/CBB3DAlgorithm/Fitting/chebyshev/chebyshev-testdata/officialtest/fitting_result/result.txt

C27 : SPHERE : pass
C28 : SPHERE : pass
C29 : SPHERE : pass
C30 : SPHERE : pass
C31 : SPHERE : pass
C32 : SPHERE : pass
C33 : SPHERE : pass
C34 : SPHERE : pass
C35 : SPHERE : pass
C36 : SPHERE : pass

本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。创作不易,帮忙点击公众号的链接。

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
50多种数学算法的源代码. 第1章线性代数方程组的解 1.全主元高斯约当消去 2.LU分解 3.追赶 4.五对角线性方程组解 5.线性方程组解的迭代改善 6.范德蒙方程组解 7.托伯利兹方程组解 8.奇异值分解 9.线性方程组的共轭梯度 10.对称方程组的乔列斯基分解 11.矩阵的QR分解 12.松弛迭代 第2章插值 1.拉格朗日插值 2.有理函数插值 3.三次样条插值 4.有序表的检索 5.插值多项式 6.二元拉格朗日插值 7.双三次样条插值 第3章数值积分 1.梯形求积 2.辛普森求积 3.龙贝格求积 4.反常积分 5.高斯求积 6.三重积分 第4章特殊函数 1.г函数、贝塔函数、阶乘及二项式系数 2.不完全г函数、误差函数 3.不完全贝塔函数 4.零阶、一阶和任意整数阶的第一、二类贝赛函数 5.零阶、一阶和任意整数阶的第一、二类变形贝赛函数 6.分数阶第一类贝赛尔函数和变形贝赛尔函数 7.指数积分和定指数积分 8.连带勒让德函数 第5章函数逼近 1.级数求和 2.多项式和有理函数 3.比雪夫逼近 4.积分和导数的比雪夫逼近 5.有比雪夫逼近函数的多项式逼近 第6章特征值问题 1.对称矩阵的雅可比变换 2.变实对称矩阵为三对角对称矩阵 3.三对角矩阵的特征值和特征向量 4.变一般矩阵为赫申伯格矩阵 5.实赫申伯格矩阵的QR算法 第7章数据拟合 1.直线拟合 2.线性最小二乘 3.非线性最小二乘 4.绝对值偏差最小的直线拟合 第8章方程求根和非线性方程组的解 1.图解 2.逐步扫描和二分 3.割线和试位 4.布伦特方 5.牛顿拉斐森 6.求复系数多项式根的拉盖尔方 7.求实系数多项式根的贝尔斯托方 8.非线性方程组的牛顿拉斐斯方 第9章函数的极值和最优化 1.黄金分割搜索 2.不用导数的布伦特 3.用导数的布伦特 4.多元函数的下山单纯形法 5.多元函数的包维尔 6.多元函数的共轭梯度 7.多元函数的变尺度 8.线性规划单纯形法 第10章傅里叶变换谱方 1.复数据快速傅里叶变换算法 2.实数据快速傅里叶变换算法一 3.实数据快速傅里叶变换算法二 4.快速正弦变换和余弦变换 5.卷积和逆卷积的快速算法 6.离散相关和自相关的快速算法 7.多维快速傅里叶变换算法 第11章数据的统计描述 1.分布的矩——均值、平均差、标准差、方差、斜差和峰态 2.中位数的搜索 3.均值与方差的显著性检验 4.分布拟合的X平方检验 5.分布拟合的K-S检验 第12章解常微分方程组 1.定步长四阶龙格库塔 2.自适应变步长的龙格库塔 3.改进的中点 4.外推 第13章偏微分方程的解 1.解边值问题的松驰 2.交替方向隐式方
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值