径向基-薄板样条插值数学公式、原理,以及代码实现基本过程

径向基插值部分

有关径向基插值的基本概念参考:https://blog.csdn.net/qq_18343569/article/details/48227839?isappinstalled=0&from=groupmessage

径向基函数RBF (Radial Basis Function)有以下五种基函数

其中r代表代待求点X与已知点Xi之间的向量距离

上边的公式是适用于以上五种基函数的计算公式,其中X代表向量,不是一个数字

对于薄板样条插值,其公式(是经过上边的公式变形所得到的公式)为:

这个公式是用于二维的插值,对于三维的插值,应该加上+dz,以及等式:AjZj(对j=1到j=n取和)=0,之后分解该公式,构造出矩阵,对矩阵取逆;

对矩阵取逆,用该矩阵左乘value(或Z坐标值)构成的一个向量,得到一个向量,该向量代表了A1-An,以及a、b、c、d(A代表一个数字,不是矩阵),将A带入公式即可计算出待求点的属性值

具体插值公式参考:https://blog.csdn.net/qq_18343569/article/details/48227839?isappinstalled=0&from=groupmessage

薄板样条插值矩阵构建参考:https://blog.csdn.net/caoniyadeniniang/article/details/78107057?isappinstalled=0&from=singlemessage

矩阵操作

对于矩阵(非稀疏矩阵)操作部分,采用的库为Eigen数学库

头文件:#include <Eigen/Dense>

矩阵定义:

方法1:Eigen::Matrix<double, 5, 5, Eigen::RowMajor> matrix

方法2:

Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> matrix

matrix.resize(rowNum, colNum)   //分配内存、空间

矩阵赋值:

matrix(i, j) = 3.6

矩阵取逆:

matrix = matrix.inverse()

矩阵转置:

matrix = matrix.transpose()

对于矩阵间的运算,或者矩阵与向量间的运算直接用*即可

关于Eigen的细节部分可参考我自己总结的一篇博客:https://blog.csdn.net/qq_16334327/article/details/83577860

### 薄板样条插值用于点云数据 对于点云数据应用薄板样条插值,可以采用Fitzgerald Archibald的Matlab代码实现[^1]。该方法旨在通过给定的一组控制点及其对应的变形位置,在保持整体形状平滑的前提下计算新的坐标。 #### 使用Python实现薄板样条插值 下面是一个基于PyTorch框架下的Python版本实现: ```python import numpy as np import torch def compute_kernel_matrix(X, Y=None): """ 计算径向基核矩阵K(x,y)=||x-y||^2*log(||x-y||),其中X,Y表示输入特征点集合。 参数: X (Tensor): 输入源点集 [batch_size, num_points, dim] Y (Tensor): 可选的目标点集,默认为None即Y=X 返回: Tensor: 核矩阵 K [batch_size, num_points_X, num_points_Y] """ if Y is None: Y = X.clone() batch_size, n_x, d = X.shape _, n_y, _ = Y.shape # 扩展维度以便广播操作 XX = X.unsqueeze(2).expand(batch_size, n_x, n_y, d) YY = Y.unsqueeze(1).expand(batch_size, n_x, n_y, d) dist_sq = ((XX - YY)**2).sum(-1) # 平方欧氏距离 eps_mask = dist_sq != 0 # 防止log(0)错误发生 log_dist = torch.zeros_like(dist_sq) log_dist[eps_mask] = torch.log(dist_sq[eps_mask]) * dist_sq[eps_mask] return log_dist def thin_plate_spline(source, target): """ 应用薄板样条变换模型求解参数w和a. 参数: source (Tensor): 原始点的位置 [batch_size, num_points, dims] target (Tensor): 对应目标点的位置 [batch_size, num_points, dims] 返回: Tuple[Tensor,Tensor]: w系数与线性部分权重(a,bias) """ num_batch = source.size()[0] num_point = source.size()[1] ones = torch.ones(num_batch, num_point, 1).float().cuda() \ if torch.cuda.is_available() else torch.ones(num_batch, num_point, 1).float() p = torch.cat([ones, source], 2) # 形成增广矩阵 [bn, pn, 3][^2] L_top_left = compute_kernel_matrix(source) zeros = torch.zeros((num_batch, 3, 3)).to(p.device) bottom_right = torch.inverse(torch.bmm(p.transpose(1, 2), p)) top_right_and_bottom_left = torch.bmm(L_top_left, p) L = torch.cat([ torch.cat([L_top_left, top_right_and_bottom_left], dim=2), torch.cat([top_right_and_bottom_left.transpose(1, 2), bottom_right], dim=2) ], dim=1) v = torch.cat([target, torch.zeros((num_batch, 3, 2)).to(target.device)], dim=1) params = torch.solve(v.unsqueeze(-1), L)[0].squeeze(-1) w = params[:, :num_point, :] a = params[:, num_point:, :] return w, a def apply_tps_transform(w, a, points_to_warp): """ 将已学习到TPS参数应用于新点上执行转换. 参数: w (Tensor): 权重项 [batch_size, control_points, output_dims] a (Tensor): 线性组合系数 [batch_size, linear_terms, output_dims] points_to_warp (Tensor): 待变换的新点 [batch_size, query_points, input_dims] 返回: Tensor: 经过TPS变换后的点 [batch_size, query_points, output_dims] """ kernel_vals = compute_kernel_matrix(points_to_warp, source=w.new_zeros(*points_to_warp.shape[:-1], device=w.device)) warped_coords = torch.matmul(kernel_vals, w) + torch.matmul(points_to_warp, a[:, :-1, :]) + a[:, [-1], :] return warped_coords ``` 此段代码实现了完整的薄板样条插值过程,包括构建径向基函数核矩阵、解决最小二乘问题获得变换参数以及最终的应用这些参数完成实际的空间扭曲效果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值