|||
通常Mesh文件(ply,off,obj等)用Vertice表保存V(x,y,z),Faces表保存三角形序号F(Vi,Vj,Vk),以及对应的纹理贴图的二维坐标Vt(u,v),常用的obj文件就是这样存储的。FaceGen的人脸模型就是用mesh加纹理图存储,但Basel人脸库不这样儿,它的Vertice的三维坐标和颜色是以(x,y,z,R,G,B)的形式存储的。
所以我们用上一篇介绍的Tutte/Floater参数化方法为Basel人脸模型生成一个纹理图,由于2D参数化坐标不在图像的整数grid上,这就需要做重采样:即每个图像点要到原图的三角形中进行三角形顶点颜色的线性插值(Barycentric Mapping)。麻烦.......
实际上可以把matlab中figure显示的mesh直接拷贝,保留中间两个方向投影积分不为0的部分:
% in R2014 fig = figure('Color','black','Position',[1 1 800 600]);%notice your system screen size trimesh( facetri, V(:,1), V(:,2), shz, 'EdgeColor', 'none', ... 'FaceVertexCData', meantex/255, 'FaceColor', 'interp', ... 'FaceLighting', 'phong' ); zlabel('Z');view(2);axis equal; xlim([min(V(:,1)) max(V(:,1))]); ylim([min(V(:,2)) max(V(:,2))]); axis off; grid off; %save figure as texture M=getframe(fig); M=M.cdata; ma = (M(:,:,1)>0); idrow = find(sum(ma,2)>0); idcol = find(sum(ma,1)>0); M = M(idrow(1):idrow(end),idcol(1):idcol(end),:); M = imresize(M,[512,512],'cubic');
再resize成正方形比如[512*512]的图像。下面是针对不同的weight计算方法得到的三个纹理图,分别对应
'combinatorial','distance', 'conformal’:
这时候53490个二维纹理参数化坐标V也可以在图像坐标系(图像尺寸512*512)中找到:
xm = minmax(V(:,1)'); ym = minmax(V(:,2)'); scale = 511.0/(xm(2)-xm(1)); V(:,1) = scale*(V(:,1)-xm(1))/511; V(:,2) = scale*(V(:,2)-ym(1))/511;
接下来可以在参数化坐标系下进行重采样,并生成新的三角网格(通常是点/网格更少,或者看起来网格更规则),这是通常称作Remesh的方法中的其中一种:在二维参数化空间进行。
这里的方法很随意。首先用meshgrid生成规则的新的采样点:
xm = minmax(V(:,1)'); ym = minmax(V(:,2)'); % interval xinc = xm(2)/50; [x,y] = meshgrid(0:xinc:xm(2),ym(1):xinc:ym(2)); x=x(:); y=y(:);
新的点x/y要在原始三角形中进行重采样,线性插值(Barycentric Mapping)。首先要找到每个x/y落在那个三角形内,太麻烦......
直接把x/y的位置落在最近的原始二维点上(随意就在这儿),把对应的原来mesh中的V的序号记下来。然后调用delaunay做三角化:
facetri_res = delaunay(double(Vt(:,1)),double(Vt(:,2)));
这样不光二维纹理坐标点有了,因为对应的三维点序号已知,三维点也有了。接下来写成obj文件。两个简化后的mesh的.obj文件可在Meshlab中打开显示。basel_texture.zip
下面两个mesh的Vertices/Faces 分别为:7831/15522和373/687。
以上的mesh简化的vertex是原始mesh的子集。更体面的方法是在参数化网格上生成更合理的网格点,这些点并不是原始mesh的子集,新的结点面临着重新投影back-prokection到原来三角形上进行采样的问题。这样的方法常见的如Centroidal Voronoi Tessellation。
这样的方法得到的mesh也并非没有可取之处,它可以看成原始mesh的一个子图sub-graph,或Embedded graph,它的每个结点都是原始mesh中的点,并且原始mesh的每个点都可以找到这个子图中的geodesic距离上的最近邻点。这在做mesh变形的时候非常有用,就像图像金字塔是光流等处理中的标配一样,先对sub-graph做变形处理,再把变形传播到高分辨率的原始结点上,可以加快计算速度。比如,对应5万节点的原始mesh的变形,可以依次在低分辨率的373和7831个结点的子图上进行处理,再最终传播到原始mesh上。
把上面的纹理图像用黑白格代替,在Meshlab中打开,效果如下。常看到相关的论文里这么干,为了显示和观察纹理的局部面积和角度的变形情况。
本篇知识点:
用getframe函数把figure保存成图像;
介绍一种野路子的Remesh方法。
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-11-22 19:42
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社