移动最小二乘法(Moving Least Squares, MLS)原理和c++实现


移动最小二乘法(Moving Least Squares, MLS)原理和c++实现

一、算法原理

移动最小二乘法(MLS) 是一种局部加权回归方法,通过对每个查询点邻域内的数据点进行加权最小二乘拟合,生成光滑的曲面或曲线。与传统最小二乘法不同,MLS的拟合函数随查询点位置动态变化,适用于非均匀采样数据与复杂几何建模。


二、数学推导
1. 基本模型

对于查询点 ( x ) ( x ) (x),在其邻域内找到最优拟合函数 ( f ( x ) ) ( f(x) ) (f(x)),最小化加权残差平方和:
min ⁡ f ∈ Π m ∑ i = 1 n w ( ∥ x − x i ∥ ) ( f ( x i ) − y i ) 2 \min_{f \in \Pi_m} \sum_{i=1}^n w(\|x - x_i\|) \left( f(x_i) - y_i \right)^2 fΠmmini=1nw(xxi)(f(xi)yi)2
其中:

  • ( Π m ) ( \Pi_m ) (Πm) ( m ) ( m ) (m) 次多项式空间(如线性、二次多项式)。
  • ( w ( d ) ) ( w(d) ) (w(d)) 为权重函数(如高斯核 ( w ( d ) = e − d 2 / h 2 ) ( w(d) = e^{-d^2/h^2} ) (w(d)=ed2/h2))。
2. 多项式展开

假设 ( f ( x ) = p ( x ) T a ) ( f(x) = \mathbf{p}(x)^T \mathbf{a} ) (f(x)=p(x)Ta),其中 ( p ( x ) ) ( \mathbf{p}(x) ) (p(x)) 为基函数向量,例如:

  • 线性基: ( p ( x ) = [ 1 , x , y ] T ) ( \mathbf{p}(x) = [1, x, y]^T ) (p(x)=[1,x,y]T)(2D)
  • 二次基: ( p ( x ) = [ 1 , x , y , x 2 , x y , y 2 ] T ) ( \mathbf{p}(x) = [1, x, y, x^2, xy, y^2]^T ) (p(x)=[1,x,y,x2,xy,y2]T)(2D)
3. 求解系数

构建加权设计矩阵 ( P ) ( \mathbf{P} ) (P) 和权重矩阵 ( W ) ( \mathbf{W} ) (W)
P = [ p ( x 1 ) T p ( x 2 ) T ⋮ p ( x n ) T ] , W = diag ( w ( ∥ x − x 1 ∥ ) , … , w ( ∥ x − x n ∥ ) ) \mathbf{P} = \begin{bmatrix} \mathbf{p}(x_1)^T \\ \mathbf{p}(x_2)^T \\ \vdots \\ \mathbf{p}(x_n)^T \end{bmatrix}, \quad \mathbf{W} = \text{diag}(w(\|x - x_1\|), \dots, w(\|x - x_n\|)) P= p(x1)Tp(x2)Tp(xn)T ,W=diag(w(xx1),,w(xxn))
目标函数转化为:
min ⁡ a ( y − P a ) T W ( y − P a ) \min_{\mathbf{a}} (\mathbf{y} - \mathbf{P}\mathbf{a})^T \mathbf{W} (\mathbf{y} - \mathbf{P}\mathbf{a}) amin(yPa)TW(yPa)
解得系数:
a = ( P T W P ) − 1 P T W y \mathbf{a} = (\mathbf{P}^T \mathbf{W} \mathbf{P})^{-1} \mathbf{P}^T \mathbf{W} \mathbf{y} a=(PTWP)1PTWy


三、应用场景
  1. 点云平滑与重建
    • 去除噪声,生成连续曲面(如3D扫描数据处理)。
  2. 图像变形与插值
    • 实现非刚性形变(如图像配准、医学图像处理)。
  3. 曲线/曲面拟合
    • 从离散数据点生成光滑曲线(如CAD建模)。

四、C++代码实现
1. 依赖库
  • Eigen:线性代数运算。
  • FLANN:快速邻域搜索(需安装 libflann-dev)。
#include <iostream>
#include <vector>
#include <Eigen/Dense>
#include <flann/flann.hpp>// 2D点结构体
struct Point2D {double x, y;Point2D(double x_, double y_) : x(x_), y(y_) {}
};// MLS拟合函数
double mlsFit(const std::vector<Point2D>& points, const Point2D& query, double radius, double h) {// 1. 邻域搜索flann::Matrix<double> dataset(new double[points.size()*2], points.size(), 2);for (size_t i = 0; i < points.size(); ++i) {dataset[i][0] = points[i].x;dataset[i][1] = points[i].y;}flann::Index<flann::L2<double>> index(dataset, flann::KDTreeIndexParams(4));index.buildIndex();// 查询邻域点double query_point[2] = {query.x, query.y};std::vector<int> indices;std::vector<double> dists;index.radiusSearch(flann::Matrix<double>(query_point, 1, 2), indices, dists, radius, flann::SearchParams(128));// 2. 构建矩阵P, W, yint m = 3; // 线性基: 1, x, yEigen::MatrixXd P(indices.size(), m);Eigen::VectorXd y(indices.size());Eigen::MatrixXd W = Eigen::MatrixXd::Zero(indices.size(), indices.size());for (size_t i = 0; i < indices.size(); ++i) {int idx = indices[i];double dx = query.x - points[idx].x;double dy = query.y - points[idx].y;double weight = exp(-(dx*dx + dy*dy)/(h*h));P(i, 0) = 1.0;P(i, 1) = points[idx].x;P(i, 2) = points[idx].y;y(i) = points[idx].y; // 假设拟合y值W(i, i) = weight;}// 3. 求解系数aEigen::MatrixXd PTW = P.transpose() * W;Eigen::MatrixXd PTWP = PTW * P;Eigen::VectorXd a = PTWP.inverse() * PTW * y;// 4. 预测query点的y值Eigen::VectorXd p_query(m);p_query << 1.0, query.x, query.y;return p_query.dot(a);
}int main() {// 生成带噪声的测试数据 (y = 2x + 1 + noise)std::vector<Point2D> points;for (int i = 0; i < 100; ++i) {double x = i * 0.1;double y = 2*x + 1 + 0.1 * ((double)rand()/RAND_MAX - 0.5);points.emplace_back(x, y);}// MLS参数double radius = 1.0; // 邻域半径double h = 0.5;      // 高斯核带宽// 在x=5.0处预测y值Point2D query(5.0, 0.0);double y_pred = mlsFit(points, query, radius, h);std::cout << "Predicted y at x=5.0: " << y_pred << std::endl;return 0;
}
2. 代码说明
  1. 邻域搜索:使用FLANN库快速查找查询点邻域内的数据点。
  2. 矩阵构建:构建设计矩阵 ( P ) ( \mathbf{P} ) (P)、权重矩阵 ( W ) ( \mathbf{W} ) (W) 和观测向量 ( y ) ( \mathbf{y} ) (y)
  3. 系数求解:通过加权最小二乘公式计算多项式系数 ( a ) ( \mathbf{a} ) (a)
  4. 预测值计算:利用拟合多项式预测查询点的函数值。

五、参数选择与优化
  • 邻域半径 ( r ) ( r ) (r):过小导致欠拟合,过大增加计算量。建议根据数据密度调整。
  • 带宽 ( h ) ( h ) (h):控制权重衰减速度,影响平滑程度。可通过交叉验证优化。
  • 多项式阶数:高阶多项式拟合能力强但易过拟合,通常选择线性或二次。

六、扩展应用示例

点云平滑2D点云:对每个点应用MLS,用邻域点的加权平均更新其位置。

void smoothPointCloud(std::vector<Point2D>& points, double radius, double h) {std::vector<Point2D> smoothed = points;for (auto& p : smoothed) {p.y = mlsFit(points, p, radius, h);}points = smoothed;
}

点云平滑3D点云

using namespace pcl;// 高斯权重函数
double gaussianWeight(double x, double y, double x0, double y0, double h) {return exp(-((x - x0) * (x - x0) + (y - y0) * (y - y0)) / (h * h));
}// 移动最小二乘计算
Eigen::VectorXd movingLeastSquares(const vector<PointXYZ>& points, const vector<double>& values, double x0, double y0, double h, int polyOrder = 2) {int N = points.size();int numCoeffs = (polyOrder + 1) * (polyOrder + 2) / 2; // 二维多项式项数Eigen::MatrixXd A = Eigen::MatrixXd::Zero(numCoeffs, numCoeffs);Eigen::VectorXd b = Eigen::VectorXd::Zero(numCoeffs);for (int i = 0; i < N; ++i) {double w = gaussianWeight(points[i].x, points[i].y, x0, y0, h);// 构建多项式基矩阵Eigen::VectorXd p(numCoeffs);p(0) = 1;if (polyOrder >= 1) {p(1) = points[i].x;p(2) = points[i].y;}if (polyOrder >= 2) {p(3) = points[i].x * points[i].x;p(4) = points[i].x * points[i].y;p(5) = points[i].y * points[i].y;}A += w * (p * p.transpose());b += w * (p * values[i]);}// 解线性方程 A * a = bEigen::VectorXd coeffs = A.ldlt().solve(b);return coeffs;
}void TestMLS3D()
{// 生成示例点云vector<PointXYZ> points = { {0, 0, 1}, {1, 0, 2}, {0, 1, 2}, {1, 1, 3}, {0.5, 0.5, 2.5} };vector<double> values = {1, 2, 2, 3, 2.5};double x0 = 0.5, y0 = 0.5, h = 1.0;Eigen::VectorXd coeffs = movingLeastSquares(points, values, x0, y0, h);// 计算平滑后点值double smoothedValue = coeffs(0) + coeffs(1) * x0 + coeffs(2) * y0 + coeffs(3) * x0 * x0 + coeffs(4) * x0 * y0 + coeffs(5) * y0 * y0;cout << "MLS 估计的值:" << smoothedValue << endl;
}

通过合理选择参数与高效实现,移动最小二乘法可广泛用于:

  • 点云平滑(如 PCL 中的 MLS 滤波器)
  • 曲面重建(如基于 MLS 的表面重建)
  • 数值计算(如无网格法中的插值)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/36425.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【PCB工艺】基础:电子元器件

电子原理图&#xff08;Schematic Diagram&#xff09;是电路设计的基础&#xff0c;理解电子元器件和集成电路&#xff08;IC&#xff09;的作用&#xff0c;是画好原理图的关键。 本专栏将系统讲解 电子元器件分类、常见 IC、电路设计技巧&#xff0c;帮助你快速掌握电子电路…

Html label标签中的for属性(关联表单控件:将标签与特定的表单元素(如输入框、复选框等)关联起来;提高可用性;无障碍性)

文章目录 示例代码for属性含义完整代码示例 示例代码 <div class"form-group"> <!-- 表单组&#xff0c;包含省份输入框和标签 --><label for"province">省份名称&#xff1a;</label> <!-- 省份输入框的标签 --><input…

S32K144外设实验(二):ADC单通道单次采样(软件触发)

文章目录 1. 概述1.1 理论回顾1.1.1 时钟系统1.1.2 采样通道1.2 实验目的2. 配置与代码编写1. 概述 1.1 理论回顾 S32K144的ADC应该说是特别灵活,笔者采用循序渐进的方式来学习使用这个很重要的外设。 在《入门笔记系列》专栏中对用户手册进行了翻译和解读,这里在回顾一下A…

进程控制~

一.进程控制 1.进程创建 我们可以通过./cmd来运行我们的程序&#xff0c;而我们运行的程序就是bash进程常见的子进程。当然我们也可以通过fork()系统调用来创建进程。 NAME fork - create a child process SYNOPSIS #include <unistd.h> pid_t fork(void…

经历过的IDEA+Maven+JDK一些困惑

注意事项&#xff1a;由于使用过程中是IDEA绑定好另外2个工具&#xff0c;所以报错统一都显示在控制台&#xff0c;但要思考和分辨到底是IDEA本身问题导致的报错&#xff0c;还是maven导致的 标准配置 maven Java Compiler Structure 编辑期 定义&#xff1a;指的是从open pr…

将bin文件烧录到STM32

将bin文件烧录到STM32 CoFlash下载生成hex文件hex2bin使用下载bin到单片机 CoFlash下载 选择需要安装的目录 在Config中可以选择目标芯片的类型 我演示的是 stm32f103c8t6 最小系统板 Adapter&#xff1a;烧录器类型 Max Clock&#xff1a;下载速度 Por&#xff1a;接口类型&am…

硬件基础(5):(2)二极管分类

文章目录 &#x1f4cc; 二极管的分类与详细介绍1. **整流二极管&#xff08;Rectifier Diode&#xff09;**特点&#xff1a;选型依据&#xff1a;补充说明&#xff1a; 2. **快恢复二极管&#xff08;Fast Recovery Diode&#xff09;**特点&#xff1a;选型依据&#xff1a;…

【MySQL】MySQL如何存储元数据?

目录 1.数据字典的作用 2. MySQL 8.0 之前的数据字典 3. MySQL 8.0 及之后的数据字典 4.MySQL 8 中的事务数据字典的特征 5.数据字典的序列化 6. .sdi文件的作用&#xff1a; 7..sdi的存储方式 在 MySQL 中&#xff0c;元数据&#xff08;Metadata&#xff09; 是描述数…

瑞萨RA系列使用JLink RTT Viewer输出调试信息

引言 还在用UART调试程序么?试试JLINK的RTT Viewer吧!不需占用UART端口、低资源暂用、实时性高延时微秒级,这么好的工具还有什么理由不用了! 目录 一、JLink RTT Viewer 简介 二、软件安装 三、工程应用 3.1 SEGGER_RTT驱动包 3.2 手搓宏定义APP_PRINT 3.3 使用APP_…

Ranger 鉴权

Apache Ranger 是一个用来在 Hadoop 平台上进行监控&#xff0c;启用服务&#xff0c;以及全方位数据安全访问管理的安全框架。 使用 ranger 后&#xff0c;会通过在 Ranger 侧配置权限代替在 Doris 中执行 Grant 语句授权。 Ranger 的安装和配置见下文&#xff1a;安装和配置 …

LabVIEW烟气速度场实时监测

本项目针对燃煤电站烟气流速实时监测需求&#xff0c;探讨了静电传感器结构与速度场超分辨率重建方法&#xff0c;结合LabVIEW多板卡同步采集与实时处理技术&#xff0c;开发出一个高效的烟气速度场实时监测系统。该系统能够在高温、高尘的复杂工况下稳定运行&#xff0c;提供高…

【系统架构设计师】操作系统 - 特殊操作系统 ③ ( 微内核操作系统 | 单体内核 操作系统 | 内核态 | 用户态 | 单体内核 与 微内核 对比 )

文章目录 一、微内核操作系统1、单体内核 操作系统2、微内核操作系统 引入3、微内核操作系统 概念4、微内核操作系统 案例 二、单体内核 与 微内核 对比1、功能对比2、单体内核 优缺点3、微内核 优缺点 一、微内核操作系统 1、单体内核 操作系统 单体内核 操作系统 工作状态 : …

人工智能之数学基础:线性方程组

本文重点 线性方程组是由两个或两个以上的线性方程组成的方程组,其中每个方程都是关于两个或两个以上未知数的线性方程。 记忆恢复 我们先从小学学习的线性方程组找到感觉 解答过程: 将第二个方程乘以2,得到: 2x−2y=2 将第一个方程减去新得到的方程,消去x: (2x+y)−…

​第十一届传感云和边缘计算系统国际会议

重要信息 时间地点&#xff1a;2025年4月18-20日 中国-珠海 会议官网&#xff1a;www.scecs.org 简介 第十一届传感云和边缘计算系统 (SCECS 2025&#xff09;将于2025年4月18-20日在中国珠海召开。将围绕“传感云”、“边缘计算系统”的最新研究领域&#xff0c;为来自国…

MDM设备管控,企业移动设备管理方案

目录&#xff1a; 目录 目录&#xff1a; 1. MDM&#xff1a;含义与定义 2. MDM如何工作&#xff1f; 3. BYOD与MDM&#xff1a;挑战与解决方案 4. 移动设备管理的主要优势 5. 移动设备管理的基本要素 6. 移动设备管理最佳实践 --地平线-- 移动设备管理 (MDM)历经多年…

S32k3XX MCU时钟配置

今天想从头开始配置S32K312中EB中的MCU模块&#xff0c;以下是我的配置思路与理解。 关键是研究明白&#xff0c;这些频率是如何通过一个总时钟&#xff0c;一步步分频得到的。 参考时钟&#xff0c;供外设模块使用&#xff0c;不同外设需要配置合理的参考时钟。 clock genera…

GitHub 超火的开源终端工具——Warp

Warp 作为近年来 GitHub 上备受瞩目的开源终端工具&#xff0c;以其智能化、高性能和协作能力重新定义了命令行操作体验。以下从多个维度深入解析其核心特性、技术架构、用户评价及生态影响力&#xff1a; 一、背景与核心团队 Warp 由前 GitHub CTO Jason Warner 和 Google 前…

SpringBoot 第二课(Ⅰ) 整合springmvc(详解)

目录 一、SpringBoot对静态资源的映射规则 1. WebJars 资源访问 2. 静态资源访问 3. 欢迎页配置 二、SpringBoot整合springmvc 概述 Spring MVC组件的自动配置 中央转发器&#xff08;DispatcherServlet&#xff09; 控制器&#xff08;Controller&#xff09; 视图解…

八股学习-JUC java并发编程

本文仅供个人学习使用&#xff0c;参考资料&#xff1a;JMM&#xff08;Java 内存模型&#xff09;详解 | JavaGuide 线程基础概念 用户线程&#xff1a;由用户空间程序管理和调度的线程&#xff0c;运行在用户空间。 内核线程&#xff1a;由操作系统内核管理和调度的线程&…

C++基础 [八] - list的使用与模拟实现

目录 list的介绍 List的迭代器失效问题 List中sort的效率测试 list 容器的模拟实现思想 模块分析 作用分析 list_node类设计 list 的迭代器类设计 迭代器类--存在的意义 迭代器类--模拟实现 模板参数 和 成员变量 构造函数 * 运算符的重载 运算符的重载 -- 运…