图形学有"建模"、"仿真"、"渲染"三大模块,各个模块之间又有很紧密的联系。
从这篇文章开始,整理几何建模与处理的基础知识,内容/代码主要参考中科大刘利刚老师的课程《games102-几何建模与处理基础》
数据拟合方法
根据Weierstrass逼近定理:
- 定理1:闭区间上的连续函数可用多项式级数一致逼近
- 定理2:闭区间上周期为2π的连续函数可用三角函数级数一致逼近
从多项式入手,讲4种代表性的拟合方法。先介绍原理,后提供代码及工程说明。
多项式插值(lagrange插值)
过两点确定一条直线 y = ax + b,解方程可以得到未知数 a、b的值。然后可以得到直线上其他点的坐标,这就是最简单的插值,此时多项式的次数为1。
如果多个点不在一条直线上呢?可以回忆下高数里的泰勒展开式,多项式可以逼近任意连续的曲线
泰勒展开式: 插值 ,其中
如果点比较多,则x项比较多,解方程不太容易。用lagrange插值法比较容易,理解也相对直观。
lagrange插值法:
限于篇幅,不做展开。lagrange插值法原理参考:
gauss插值
高斯插值本质上,就是在多项式插值的基础上,将基函数从多项式,改成高斯函数
使用 Gauss 基函数的线性组合 插值 ,其中
即对称轴在插值点上,,缺省设
不要被这个高斯基函数吓到了,代入已知的点,g(x)的值可以明确的计算出来,最后变成解多元方程,解出每一个的值
观察上图示例,高斯插值更侧重突出插入点,通过调值,可以很好的控制曲线变化的幅度。
注意: 实际上方程组还多了一个是未知的,有两种方法确定,
-
通过人为的增加一个点,比如取最后两个点的中间值
-
直接取所有插值点y坐标的平均值
下面计算gauss插值的代码中,我有点偷懒,直接去掉了项,有兴趣,你可以补上
高斯函数拟合可以参考: 拟合与高斯分布
无论多项式插值,还是高斯插值,都是选一组规律的函数来拟合插值的点,通过解方程,得到一个"漂亮"的拟合函数曲线,当然还有很多其他的插值基函数,不过原理都类似。
多项式拟合
如果多项式的次数太大,方程解起来很花时间,那怎么办呢?可以用低阶的多项式来近似拟合,不要求拟合出来的曲线能刚好穿过每一个点,只要路径近似就能满足要求。
具体怎么操作呢?比如有4个点,但我只想用基函数来拟合,4个点对应4个方程,但是只有三个未知数,就造成过拟合,方程是无解的。
使得当条件成立时,对应的值,
可以用最小二乘法来求一个近似的解,如果你还记得线性代数,或者学过机器学习,很好理解。
下面附一个讲的浅显易懂的文章,从偏导和几何的角度分别给出了解释: 最小二乘法
注意:如果多项式次数比较高,或者基函数选择的比较复杂,用最小二乘法可能无解,在机器学习领域,用梯度下降的方法来求解(模型训练)。
岭回归拟合
岭回归是概率统计的概念,在机器学习领域称为"正则化"。
在多项式拟合的基础上,增加了多项式的权重,这个解释起来有点繁琐,简言之,让曲线泛化的更好,我希望曲线不要太贴近插入的点,因为有可能某一个点是"噪点",把整个曲线带的很陡峭,增加"正则项",使得曲线拟合的更稳定。
工程介绍
代码基于'陈昱文-作业'修改完善,IDE使用CLion
工程目录:
- CPM.cmake cmake拓展,便于第三方库版本管理和集成
- glad GLFW 渲染接口层
- imgui 轻量的GUI框架,很方便的创建操作面板、按钮等交互空间
- eigen,线性代数计算库(和GLM类似,GLM主要和opengl配合使用,方便计算相机矩阵)
- MathUtil类,实现了上述几种拟合算法
- 主要调用逻辑在main.cpp中
简单的配置,就能实现一个轻便的交互界面,麻雀虽小五脏俱全。上面依赖的常用库真要深入进去吃透了,也非常强大。
读者朋友可以下载完整代码编译运行,参考原理介绍,梳理整个流程。