机器视觉 增强现实分享 http://blog.sciencenet.cn/u/wanglin193 把算法当成业余爱好......

博文

三维网格在参数化uv图上进行网格重采样做Remesh

已有 491 次阅读 2018-9-19 21:30 |个人分类:3D|系统分类:科研笔记| Remesh

通常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’:

dd.jpg

这时候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中打开,效果如下。常看到相关的论文里这么干,为了显示和观察纹理的局部面积和角度的变形情况。


本篇知识点:

  1. 用getframe函数把figure保存成图像;

  2. 介绍一种野路子的Remesh方法。



http://blog.sciencenet.cn/blog-465130-1135783.html

上一篇:固定边界的三维人脸网格参数化
下一篇:最小二乘网格( Least-squares Meshes) 选取结点组成子网格

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备14006957 )

GMT+8, 2018-10-18 06:27

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部