• 基于测地距离场的三维人脸参数化方法


    目录

    1. 前言

    2. 曲面参数化原理

    3. 人脸曲面参数化实现

    4. 实验结果

    Reference


    1. 前言

    三维人脸数据的识别与处理,一直是视觉与图形学领域的热点问题。相对于人脸图像来说,三维人脸数据拥有完整的几何信息,能够支持更加精确的人脸数据分析算法。在进行相关的计算之前,我们希望三维人脸能够有一个统一的表示形式,以准确的界定人脸的区域以及对应的位置,尽可能的消除姿态以及尺度不一致带来的影响。基于该目的,人脸参数化方法被提出。人脸参数化方法即建立三维人脸到二维参数域的映射,同时尽可能优化映射带来的形状畸变,即映射本身要接近保形的要求。在2002年,Desbrun [1] 提出一种内蕴参数化方法,通过优化余切权重,建立对保形能量的优化模型,进而实现映射。Lv [2] 基于该方法, 利用测地距离提取三维人脸的子曲面,并将曲面映射到参数域中,以建立三维人脸的非刚性对应关系,并降低表情影响。其他参数化方法包括Ricci Flow [3], 调和函数 [4],最优传输 [5] 等,均有不错的应用。本文基于 [1] [2] 两项工作,结合在github上的开源项目,来介绍该技术的具体实现。

    Project Link: Intrinisc Parameterization for 3D Facial Surface.


    2. 曲面参数化原理

    在工作 [1] 中,Desbrun解释了如何建立三维曲面到二维参数域的映射。首先,需要定义映射所产生的能量畸变,如下:

    下面考察映射后,点xi和xj位置变换到ui和uj所产生的畸变。一个理想的保形变换应保证所有的角度和面积保持不变。不过,现实中计算理论上的保形变换是比较难的,因为曲面的高斯曲率不是处处为0,自然将其映射到平面上,必然会产生畸变。在实践中,保形变换等价于获得最小化畸变的映射,即拟共形映射。这里,针对点xi和xj,建立他们的畸变能量表示:

    这两个能量一个对应角度的优化,一个对应距离的优化。角度优化能量即保形能量的量化表示形式,距离优化能量即保积能量的量化表示形式。对上述能量进行优化求解,即求极值:

    至此,我们得到了一个点和他周围点的能量极值计算方法。接下来,我们只需要对所有点计算全局最优解就可以了,基本可以转换为一个线性优化问题,公式如下:

    这是一个矩阵化后的能量极值计算表示。M存储的是基于拉普拉斯邻接关系的各个点的余切权重,包含角度优化能量和距离优化能量两项。C是边界条件,即我们希望三维曲面的边界是固定在二维参数域中的,以确定映射结果有明确的边界。最后对上述的线性系统求解,以获得二维坐标U,即曲面在参数域的二维坐标,结果如下:

    一个完美的等距映射,应该是实现对上述两个能量的全局优化,但是这比较难。在实践中,还是以优化保形能量为第一优先,以保证角度畸变最小,方便实现纹理映射等应用。另外,可能用户希望固定除了边界以外的一些特征点,如人脸的眼角,嘴角等,工作 [1] 中给了具体的实现,有兴趣的同学可以复现试试看。


    3. 人脸曲面参数化实现

    在工作 [2] 中,参数化方法被应用在三维人脸数据度量中。具体的做法是,基于鼻尖点,按照特定的测地距离,在人脸曲面上提取一个测地圆盘。该圆盘因为受到测地距离约束,使得能够更准确的界定需要度量的人脸区域,相当于一步face cropping, 如下图所示:

    代码实现有两个点需要注意,一个是测地距离计算,还有一个就是针对上述线性系统求解。这里,我列出针对提到两点的关键代码实现,提取自文章一开始介绍的Github项目:

    测地距离计算,基于VCG实现:

    1. void TriGeodesic_Mymesh_Geodesic(Point3f c) {
    2. //Point3f c = m.bbox.Center();
    3. MyVertex* closest = &*m.vert.begin();
    4. float minDist = Distance(closest->P(), c);
    5. for (MyMesh::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
    6. {
    7. if (Distance(vi->P(), c) < minDist)
    8. {
    9. minDist = Distance(vi->P(), c);
    10. closest = &*vi;
    11. }
    12. }
    13. vector seedVec;
    14. seedVec.push_back(closest);
    15. tri::EuclideanDistance ed;
    16. tri::Clean::RemoveUnreferencedVertex(m);
    17. tri::Allocator::CompactEveryVector(m);
    18. tri::UpdateTopology::VertexFace(m);
    19. tri::Geodesic::Compute(m, seedVec, ed);
    20. pair<float, float> minmax = tri::Stat::ComputePerVertexQualityMinMax(m);
    21. tri::UpdateColor::PerVertexQualityRamp(m);
    22. printf("min %f max %f\n", minmax.first, minmax.second);
    23. tri::io::ExporterPLY::Save(m, "Data/base.ply", tri::io::Mask::IOM_VERTCOLOR | tri::io::Mask::IOM_VERTQUALITY);
    24. vertexGeoDis.resize(m.vert.size(), 0);
    25. float minDis = 9999;
    26. float maxDis = -9999;
    27. for (size_t i = 0; i < m.vert.size(); ++i)
    28. {
    29. MyVertex* nextV = &*(m.vert.begin() + i);
    30. vertexGeoDis[i] = nextV->Q();
    31. if (vertexGeoDis[i] > maxDis) {
    32. maxDis = vertexGeoDis[i];
    33. }
    34. if (vertexGeoDis[i] < minDis) {
    35. minDis = vertexGeoDis[i];
    36. }
    37. }
    38. max_g = maxDis;
    39. min_g = minDis;
    40. cout << "geodesic computation finished" << endl;
    41. }

    线性系统求解,基于Eigen实现:

    1. //LaplaceNeighbor为网格的邻接矩阵,尺度等于网格顶点数
    2. Eigen::SparseMatrix<float> A1_sparse(LaplaceNeighbor.size(), LaplaceNeighbor.size());
    3. //网格邻接矩阵是一个稀疏矩阵,使用稀疏矩阵模型来进行数据存储于计算,效率较高
    4. Eigen::MatrixXf b1_sparse(LaplaceNeighbor.size(), 2);
    5. Eigen::MatrixXf x1_sparse;
    6. //使用三元素实现对稀疏矩阵的赋值
    7. std::vectorfloat>> tripletlist;
    8. //赋值tripletlist...
    9. //压缩稀疏矩阵
    10. A1_sparse.setFromTriplets(tripletlist.begin(), tripletlist.end());
    11. A1_sparse.makeCompressed();
    12. //使用BiCGSTAB解Ax=b
    13. Eigen::BiCGSTABfloat> > Solver_sparse;
    14. Solver_sparse.setTolerance(0.00001);
    15. Solver_sparse.compute(A1_sparse);
    16. x1_sparse = Solver_sparse.solve(b1_sparse);

    注:在Eigen里提供了很多方法解决Ax=b,参考图如下:

    稠密矩阵 

     稀疏矩阵

     

    可以根据需要求解的具体问题,选择合适的求解器。


    4. 实验结果

    1)基于测度距离的人脸子曲面提取:

    2)基于人脸子曲面的参数化:


    Reference

    [1] Desbrun M, Meyer M, Alliez P. Intrinsic parameterizations of surface meshes[C]. Computer graphics forum. Oxford, UK: Blackwell Publishing, Inc, 2002, 21(3): 209-218.

    [2] Lv C, Wu Z, Wang X, et al. Constructing 3D facial hierarchical structure based on surface measurements[J]. Multimedia Tools and Applications, 2019, 78(11): 14753-14776.

    [3] Zeng W, Samaras D, Gu D. Ricci flow for 3D shape analysis[J]. IEEE Transactions on Pattern Analysis and Machine Intelligence, 2010, 32(4): 662-677.

    [4] Hou J, Chau L P, Zhang M, et al. A highly efficient compression framework for time-varying 3-D facial expressions[J]. IEEE Transactions on Circuits and Systems for Video Technology, 2014, 24(9): 1541-1553.

    [5] Jin M, Wang Y, Yau S T, et al. Optimal global conformal surface parameterization[C]//IEEE Visualization 2004. IEEE, 2004: 267-274.

  • 相关阅读:
    《Beginning C++20 From Novice to Professional》第六章 Pointers and References
    MySQL性能优化的5个维度
    【毕业设计】基于java+swing的模拟写字板设计与实现(毕业论文+程序源码)——模拟写字板
    新消费降温,良品铺子还能走多远?
    17.Tensor Product Spaces
    APISpace 手机号码归属地API接口案例代码
    rocketMQ是如何利用MQFaultStrategy规避延迟故障的?
    想学设计模式、想搞架构设计,先学学 UML 系统建模吧
    59Redis高可用持久性
    stable diffusion本地部署教程
  • 原文地址:https://blog.csdn.net/aliexken/article/details/126663148