|||
三维曲面离散化为三维网格后,为了进行纹理贴图,有时还要展开到二维的uv坐标平面上。虽然大部分空间曲面都不是可展的,但是在曲面的局部区域观察是可以表示成f(u,v)的形式的,这个过程在数字图形处理中的术语叫参数化(Parameterization)。从三角网格的角度,每个三角形和它的uv平面上的对应都是仿射变换的关系,根据不同的应用,通常要给这种局部映射加约束,比如要求角度或者面积的变形最小等,在曲面不撕裂的情况下,这种假设只能近似满足。
常用的纹理映射方法是把和平面圆盘拓扑等价的曲面,映射到平面上。曲面的边界分别有固定边界和不固定边界两种。对于后者多数求解方法都是非线性的。而固定边界方法则用线性方程就能求解,即给定凸边界,不在边界上的点看成是边界点的某种线性加权(参见上一篇)。其中Tutte mapping堪称是最简单的uv映射方法,每个点是邻近点的重心位置。
下面针对Basel人脸模型做参数化。预先对于原网站上提供的10个模型作平均,得到一个平均模型,保存在Basel_color_meanface.mat中,三角形序号表示的‘面表’保存在face_tri.txt中。
clear all close all path = 'data\'; % load mesh data, Vertex, Color and Facets load([path,'Basel_color_meanface.mat']); facetri = 1 + load([path,'face_tri.txt']); % load IBUG 68 lmk for basel model idlmk = 1 + load([path,'lmk_id68_in53490.txt']); meanshape = meanface.shape; meantex = meanface.tex; numv = size(meanshape,1); % Calculate laplacian matrix L = cal_mesh_laplacian(double(meanshape),facetri,'conformal'); % Find contour: edges has only one half edge in edgelist [idcon,idseg] = find_mesh_contour( meanshape, facetri );
因为模型只有一条边界,idseg=1,即没有孔洞,拓扑结构和圆盘等价。68个蓝色点表示的是IBUG二维人脸特征点(ASM/AAM等face alignment方法常用的landmark配置)的对应位置:
把曲面x/z坐标归一化到一个半径r的圆柱面上(早年3DMM人脸模型经常做这样的操作):
sum2 = meanshape(:, 3).^2 + meanshape(:, 1).^2; sum2 = sqrt(sum2); r = mean(sum2); meanshape(:, 3) = r*meanshape(:, 3)./sum2; meanshape(:, 1) = r*meanshape(:, 1)./sum2; trimesh( facetri, meanshape(:, 1), meanshape(:, 2), meanshape(:, 3), ... 'EdgeColor', 'none', ... 'FaceVertexCData', meantex/255, 'FaceColor', 'interp', ... 'FaceLighting', 'phong' ); zlabel('Z');hold onview(-35,60); plot3( meanshape(idcon,1),meanshape(idcon,2),meanshape(idcon,3),'r.' ); axis equal
然后展开到Z=0平面上:
ang = atan2(meanshape(:, 1), meanshape(:, 3)); shx = ang*r; shy = meanshape(:, 2); shz = zeros(numv,1);
图中鼻孔和嘴部的瑕疵是鼻腔口腔内部三角网格映射形成的,也就是说网格点映射时产生了一对多的问题。这当然可以通过检查网格投影先后顺序来解决。但是参数化的要求是一对一的bijection,网格不能有折叠。
固定边界(红色的点)求内部点V的位置,保证每个三角网格的法线一致:都朝纸外。
%hard constaint idx = ones(numv,1); idx(idcon)=0; id_unkown = find(idx); % remove known vertex lines from L L(idcon,:)=[]; % move column of boundary vertex in LV=0 to right V = [shx,shy]; vh = sparse(double(V(idcon,:))); Rhs = -L(:,idcon) * (vh); % Unknow vertex on left Lhs = L(:,id_unkown); Vp = Lhs\Rhs; % copy back to vertex V(id_unkown,:) = full(Vp); figure trimesh( facetri, V(:,1), V(:,2), shz, 'EdgeColor', 'none', ... 'FaceVertexCData', meantex/255, 'FaceColor', 'interp', ... 'FaceLighting', 'phong' ); zlabel('Z');view(2);axis equal;hold on, shx = V(:,1); shy = V(:,2); plot3( shx(idcon),shy(idcon), zeros(length(idcon),1),'r.' ); plot3( shx(idlmk),shy(idlmk), zeros(length(idlmk),1),'b.' );
仍然用trimesh函数画出网格和颜色,以及边界和68个landmark的位置:
固定边界也可以按照edge的长度比例固定在圆形(长度按比例对应2PI角)或者正方形上,比如映射到正方形上是这样(“好吓人!”):
如果只固定少量边界点会怎样?比如只用8个点:
idcon = idcon(1:round(end/8):end);
如果在边界约束中加入部分face landmark会怎样?
idcon = [idcon;idlmk(9);idlmk(18:end-20)];
内部约束点会导致附近的三角形方向发生翻折,法线朝向纸内:
用 triplot()函数叠加网格,在下巴点处放大观察:
参考:
[1].计算稀疏矩阵L和W的函数cal_mesh_laplacian()参考自:
http://www.numerical-tours.com/matlab
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-11-22 18:39
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社