3D人脸重构里的渲染质心(barycentric coordinates)坐标计算原理。

一、什么是质心坐标?

在几何结构中,质心坐标是指图形中的点相对各顶点的位置。

以图1的线段 AB 为例,点 P 位于线段 AB 之间,

  图1 线段AB和点P

 

此时计算点 P 的公式为 

 

同理,在三角形 ABC 中,三角形内点 P 的计算公式为:——公式一。

 公式一的最终表示形式为:

 

那么如何计算参数 m 和 n 呢?

下面给出推导过程:

根据公式一可得:

我们将  记作向量  ,将  记作向量  , 将  记作向量 ,则公式为:

然后分别乘以 v0  和 v1 得到如下两个公式:

  

继续化解方程式得:

 令:

继续化简方程式得:

根据莱布尼茨公式可得:

 

其中d = 

注意:到此整个系数的计算已经完成,质心的应用场景为:

  • 判断一个点是否在三角形内。即根据计算处理的系数是否可以到相等的x,y坐标。
  • 根据三角形的三个顶点得到三角形内任何一点P
  • 可以把系数当作权重,即三个点的任何属性,例如颜色、深度等信息,也可以使用这里的m、n、(1-m-n)得出对应的加权后的值。例如3D人脸的渲染跟深度计算就是根据这个原理得出的。

C++实现代码:

//vPos1, vPos2,vPos3 分别代表三角形的三个顶点
//vP代表三角形内的一个点、
//fI代表 vPos1的系数
//fJ代表 vPos2的系数
//fK 代表 vPos3的系数
bool GetBarycentricCoord(vec2 vPos1, vec2 vPos2, vec2 vPos3, vec2 vP, float& fI, float& fJ, float& fK)
{// Compute vectorsvec2 v0 = vPos2 - vPos1;vec2 v1 = vPos3 - vPos1;vec2 v2 = vP - vPos1;// Compute dot productsfloat fDot00 = Dot(v0, v0);float fDot01 = Dot(v0, v1);float fDot02 = Dot(v0, v2);float fDot11 = Dot(v1, v1);float fDot12 = Dot(v1, v2);// Compute barycentric coordinatesfloat fInvDenom = 1 / (fDot00 * fDot11 - fDot01 * fDot01);float fTempU = (fDot11 * fDot02 - fDot01 * fDot12) * fInvDenom;float fTempV = (fDot00 * fDot12 - fDot01 * fDot02) * fInvDenom;// Check if point is in triangle or edgebool bIsInTri = (fTempU >= 0) && (fTempV >= 0) && (fTempU + fTempV <= 1);if (bIsInTri){fJ = fTempU;fK = fTempV;fI = 1 - fJ - fK;}return bIsInTri;
}

python实现代码:

## 获得重心权重的函数
def get_point_weight(point, tri_points):''' Get the weights of the positionArgs:point: (2,). [u, v] or [x, y] tri_points: (3 vertices, 2 coords). three vertices(2d points) of a triangle. Returns:w0: weight of v0w1: weight of v1w2: weight of v3'''tp = np.array(tri_points)# vectorsv0 = tp[2,:] - tp[0,:]v1 = tp[1,:] - tp[0,:]v2 = np.array(point) - tp[0,:]# dot productsdot00 = np.dot(v0.T, v0) # distance of p2 and p0dot01 = np.dot(v0.T, v1) # dot02 = np.dot(v0.T, v2)dot11 = np.dot(v1.T, v1)dot12 = np.dot(v1.T, v2)# barycentric coordinatesif dot00*dot11 - dot01*dot01 == 0:inverDeno = 0else:inverDeno = 1/(dot00*dot11 - dot01*dot01)u = (dot11*dot02 - dot01*dot12)*inverDenov = (dot00*dot12 - dot01*dot02)*inverDenow0 = 1 - u - vw1 = vw2 = ureturn w0, w1, w2

 

使用到的人脸3d重构参考工程:

https://github.com/cleardusk/3DDFA

渲染工程:

https://github.com/cleardusk/SimRender/blob/master/lib/CMakeLists.txt

 

 

 

 

 

 

 

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部