最⼩⼆乘保⾓参数化(LeastSquareConformalMaps )
最⼩⼆乘保⾓参数化(Least Square Conformal Maps )
框架:
⽤的是中国科⼤傅孝明⽼师的框架:
概述
LSCM是指最⼩⼆乘保⾓映射,不需要固定边界来进⾏⽹格模型参数化。所采⽤的⽬标函数的最⼩化值可以使参数化后的⾓度变形最⼩,同时最⼩值唯⼀(即解线性⽅程)。
优缺点:
1. 减少了⾓度扭曲与不⼀致的缩放
2. 存在且具有唯⼀的最⼩值,避免局部最优解
3. 不需要确定边界的映射,因此可以作⽤于任意形状的边界
4. 会发⽣三⾓形的翻转与重叠
参数化最好的情况映射前后的每个三⾓形⾯积与⾓度不变,在u保持⾓度不变的情况下尽可能保持⾯积不变。
保⾓映射(Conformal Map)是⼀个数学概念,指的是两个曲⾯映射后和前每⼀个点上两个向量的夹⾓不变。例如下图,三维曲⾯上的顶点
,任意两个互相垂直的、位于此顶点的切平⾯向量,被映射到另⼀个平⾯,两个向量依旧垂直。
也就是说把平⾯域(u,v)映射到曲⾯也是保⾓的,那么通过的两个⽅向的切向正交,并且范式相等,也就是满⾜柯西-黎曼⽅程:
LSCM算法建⽴在柯西-黎曼⽅程的基础上。⾸先定义⼀个能量函数。在定义的保⾓能量函数是和每个三⾓形的⾯积成正⽐的。保⾓离散化
定义在光滑曲⾯上的能量函数需要进⾏离散化。通过离散化构建⼀个线性的系统,这个线性的系统的思路就是把u、v坐标表⽰为⼀个复数。离散步骤如下:
第⼀步:假设三维模型的每个三⾓形有⼀个局部正交坐标系,那么三⾓形的3个顶点的局部坐标为$ (x_1,y_1)、(x_2,y_2)、(x_3,y_3) $,法向都是Z轴⽅向。相邻两个三⾓形的⽅向⼀致
第⼆步:假设$ U:(x,y)\rightarrow(u,v)$是从三维空间到⼆维平⾯的映射,那么在局部坐标系中,柯西-黎曼⽅程离散化为:
第三步:上式X⽤复数表⽰为,让。那么根据反函数导数定理得出:
第四步:由于此公式⽆法被完全满⾜,因此可以⽤最⼩平⽅的形式满⾜。
(u ,v )X (u ,v )N (u ,v )×(u ,v )=∂u ∂X (u ,v )
∂v ∂X
−∂u ∂X i =∂v ∂X
X =x +iy U =u +iv +∂x ∂U
i =∂y ∂U 0
第五步:⽤来表⽰三⾓形的⾯积,从⽽对于每个三⾓形定义能量⽅程:
第六步:对于所有三⾓形来说,能量函数为所有单个三⾓形能量函数之和:
第七步:进⽽为每个顶点设置⼀个复数,从⽽使柯西-黎曼⽅程是最⼩平⽅。
第⼋步:假设在三⾓形内部是线性变化的,对于⼀个三⾓形来说,那么3个顶点上的值有如下关系:
即梯度公式,其中是三⾓形⾯积的两倍
A T C (T )=∣∫T +∂x ∂U i ∣∂y ∂U 2dA =∣+∂x ∂U
i ∣∂y ∂U 2A Tindex复数
C (T )=C (T )T ∈T ∑
U 3u (x ,x ),(x ,y ),(x ,y )122233u ,u ,u 123=[∂x ∂u ∂y ∂u ]d T 1[y −y y −y y −y 233112x −x x −x y −y 321321]⎣⎡u 1u 2u 3⎦
⎤d =T (x y −12y x )+12(x y −23y x )+23(x y −31y x )31
第九步:把上⾯的向量修改为复数形式:
其中:第⼗步:表⽰为复数,最终柯西-黎曼⽅程可以表⽰为:
第⼗⼀步:那么能量函数改变变量后变为:
第⼗⼆步:也就是每个三⾓形的能量函数为:
第⼗三步:能量⽅程是复数的⼆次形式,⽤矩阵形式表⽰为:
第⼗四步:其中是的Hermitia矩阵。表⽰的哈密尔顿共轭矩阵。是哈密尔顿Gram矩阵,可以写成:
第⼗五步:上述矩阵是⼤⼩为的矩阵,其中
第⼗六步:如果没有其他的额外约束条件,上述优化问题的解都是0。为了使优化问题避免简单的解,那么需要确定⼀些点的位置作为约束。
+∂x ∂U
i =∂y ∂U d T i [W W W 123][u u u 123]T
i ∗i =−1
⎩⎪⎨⎪⎧W =(x −x )+i (y −y )13232W =(x −x )+i (y −y )21313W =(x −x )+i (y −y )
32121U =j u +j iv j +∂x ∂U
i =∂y ∂U d T i [W W W 123][U U U 123]T
C (U =(U ,⋯,U ))=1n T C (T )T ∈T ∑
C (T )=∣d T 1
(W W W )(U U U )∣j 1,T j 2,T j 3,T j 1j 2j 3T 2
C (U )U ,⋯,U 1n C (U )=U CU
∗C n ×n U ∗U C C =M M
∗M =(m j )i F ×V m =i ,j {顶点j 属于三⾓形T
d Ti W j ,Ti
其他
第⼗七步:如果确定个点,那么
第⼗⼋步:也就是矩阵分为两部分其中,是⼤⼩为的矩阵,是的矩阵。
第⼗九步:由前⾯得:
第⼆⼗步:最终得到线性系统为:
其中
第⼆⼗⼀步:这个线性系统具有如下的特征:
1. A在约束点等于2的情况下是满秩的。
2. 如果约束点等于2,那么,假如曲⾯是可扩展⾯,那么映射是完全保⾓的,也就是⽬标函数的最⼩值是零。
3. 最⼩值是旋转不变的。
4. 最⼩值和模型的分辨率⽆关。
代码
P U =(U ,U )f T p T
T
M =(m )ij M =(M ,M )
f p M f F ×(V −P )M p F ×P C (U )=U M MU =∗∗∣∣MU ∣∣=2∣∣M U +f f M U ∣∣p p 2
C (x )=∣∣Ax −b ∣∣2
A =[M −M f 1f 2
M M f 2f 1]b =−[M −M p 1p 2M −M p 2p 1][U p 1
U p 2]x =(A A )A b T −1T
//Least Square Conformal Maps
int v_count, f_count, F_P, S_P;
vector<int> VertexMapping, antiVertexMapping;
Eigen::SparseMatrix<double> realMf,imageMf, realMp, imageMp, A2, BM, B_Sparse;
Eigen::MatrixXd NewP;
Eigen::Vector4d U;
vector< vector<Eigen::Vector2d>> edgeVectors;
vector<double> area, New_U, New_V;
//每个3D空间三⾓形对应的2D平⾯三⾓形的三条边,按⾯编号存储
void CalculateEdgeVectors();
//固定2个顶点
void FixTwoBoundryPoint();
//将顶点序号与坐标相对应
void MapBackUV();
//矩阵转化为稀疏矩阵
void buildSparseMatrix(Eigen::SparseMatrix<double>&A1_sparse, Eigen::MatrixXd A,int A_rows,int A_cols); //清理变量
void LSCM_End();
//构建A和BM矩阵
void build_A2_BM();
//构建新的mesh
void BuildMesh(Mesh &temp);
//LSCM参数化
Mesh Parameterize();
//Least Square Conformal Maps
//固定2个顶点
void MeshViewerWidget::FixTwoBoundryPoint(){
FindFirstBoundry();//到第⼀个边界点
FindAllBoundry();//到全部边界点
int len = boundry.size();
F_P =0;
S_P = len /2;//选取任意较远的两个点
}
//每个3D空间三⾓形对应的2D平⾯三⾓形的三条边,按⾯编号存储
void MeshViewerWidget::CalculateEdgeVectors(){
for(int k =0; k < f_count;++k){
edgeVectors[k].resize(3);//每⾏为3列
}
//遍历所有的⾯
for(auto f_it = mesh.faces_begin(); f_it != mesh.faces_end(); f_it++){
vector<int>v(3,0);
int i =0;
for(auto fv_it = mesh.fv_iter(*f_it); fv_it.is_valid();++fv_it){//遍历该⾯的所有点
v[i]=(*fv_it).idx();//保存该⾯顶点编号
i++;
}
//计算3条边的边长
double a, b, c;
a =(mesh.point((mesh.vertex_handle(v[0])))- mesh.point((mesh.vertex_handle(v[1])))).length();
b =(mesh.point((mesh.vertex_handle(v[1])))- mesh.point((mesh.vertex_handle(v[2])))).length();
c =(mesh.point((mesh.vertex_handle(v[2])))- mesh.point((mesh.vertex_handle(v[0])))).length();
double angle =acos((a*a + c * c - b * b)/(2* a*c));
double l =(a + b + c)/2.0;
area[(*f_it).idx()]=sqrt(l*(l - a)*(l - b)*(l - c));//三⾓形⾯积(海伦公式)
//以U1为原点,构建在2D平⾯的三⾓形坐标
Eigen::Vector2d U1, U2, U3;
U1 <<0,0;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论