本文原载于我的主页:planckscale.info,转载于此。
版权声明:本文系PlanckScale工作室翻译整理,欢迎转载,但转载请以超链接形式注明文章来源(planckscale.info)、作者信息和本声明,否则将追究法律责任。
我们在实时三维重建方面的工作今年已经密集展开。或许不久后某一天,你会在本站看到带有SLAM(即时定位与地图构建)功能的四轴飞行器,或者让你在书桌上打一场现代战争的增强现实应用。在敲锣打鼓欢天喜地亮出我们自己的三维重建实现前,先拿别人的东西给大家打打牙祭。
中科大刘利刚教授的3D建模软件与处理软件简介介绍了N多实用的3D相关软件。而基于照片的快速建模软件并不多,之前玩过123D
Catch,很赞。围着你要建模的物体拍摄一圈,用123D Catch加载拍摄的图像,经过其强大的处理能力,生成具有纹理的3D模型。下图是我重建的我的蒙奇奇。你要做的只是拍照、上传、等待而已,相当简单。
但是123D Catch也存在一些局限,完全的黑盒子,对重建过程没有任何操控力。
要想了解从照片如何一步步重建出三维模型,并能操控某些过程,可用的免费开源软件也不少,较常用的是VisualSFM和Meshlab:
第一步:VisualSFM
VisualSFM软件允许我们上传一系列图像,它从这些图像中找到每一个图像的特定特征,利用这些特征信息重建出3D模型的稀疏点云,而后还可进行稠密点云重建。
输入:围着要重建对象拍摄的一系列照片;
输出:一个 .out文件,存储着每个相机的位置及重建出的稀疏点云;
一个.ply文件,存储着由稀疏点云重建出的稠密点云。
第二步:Meshlab
可用Meshlab对3D网格/点云做各种操作。输入VisualSFM的生成文件,Meshlab通过一系列操作可创建出包含纹理的、干净的、高分辨率的网格,并自动计算UV映射及创建纹理图像。
输入:VisualSFM的生成文件,.out文件和list.txt文件(存储照片序列); 以及.ply文件;
输出:一个.obj文件,3D模型的网格;
一个.png文件,任意大小的纹理图;
完整的流程见下图:
第一步:运行VisualSFM
1. 输入一系列图片
拍照注意事项:切忌不要站在原地,仅转动身体去拍:相机共中心能拼接全景,但是给不出三维重建的深度信息。要以待重建的对象为中心,围着它每转10-20度拍一张,这样转一圈,有不同高度信息更好。VisualSFM没有照片数量限制,照片越多,重建出的细节越丰富,但重建过程花费时间越长。
2. 特征检测及匹配
因照片可能存在旋转、缩放或亮度变化,此过程利用SIFT算法提取、描述特征,用 RANSAC算法过滤掉误匹配。此过程亦可利用GPU加速。工作状态实时显示在侧边的log窗口。
3. 利用SFM进行稀疏3D重建
利用 SFM 方法,通过迭代求解出相机参数和三维点坐标。即重建出3D模型的稀疏点云。若有“bad”相机(位置错误或朝向错误),结合工具栏上的“3+”按钮和手型按钮即可删除之,使结果更准确。
4. 利用 CMVS/PMVS 进行稠密3D重建
CMVS/PMVS需自己下载,编译,也可直接下载exe文件。而后把pmvs2.exe/cmvs.exe/genOption.exe文件放到VisualSFM.exe的同目录下。
通过 CMVS 对照片进行聚类,以减少稠密重建数据量,而后利用PMVS从3D模型的稀疏点云开始,在局部光度一致性和全局可见性约束下,经过匹配、扩散、过滤 生成带真实颜色的稠密点云。(下图为用Meshlab查看效果图)
至此,VisualSFM的工作告一段落,结果都已存盘。若因图片匹配失败或图片较少导致某区域重建失败或重建出的某区域细节不足,可以返回添加一些这个区域的照片,重新来过(本人较懒,未作补充,谅解)。但因特征检测和匹配的结果已存盘( 每张图像对应的.sift 和 .mat文件),所以已经匹配好的图像不必再次匹配,会更快完成。
第二步:运行Meshlab
1. 打开bundle.rd.out 文件
a. 按钮1,打开由 VisualSFM生成的存储在xx.nvm.cmvs文件夹下的 bundle.rd.out 文件。随后会询问是否选择照片列表文件,选择同文件夹下的 “list.txt”即可。这一步会把相机及对应的照片导入进来,对后续的纹理处理至关重要。
b. 按钮2,打开显示层目录,检测相机载入是否正确, Render –> Show Camera,因可视化相机的尺寸比网格尺寸大得多,所以需调整相机的缩放因子,scale factor可以从0.001开始调小,直到相机位置清晰可见。
2. 稠密点云代替稀疏点云
a. 按钮3,隐藏可视的稀疏点云;
b. File –> Import Mesh加载稠密点云(xx/00/models/option-0000.ply);VisualSFM生成多个.ply文件时,需合并成一个mesh。在载入的任何一个.ply上右键选“Flatter Visible Layers”。
3. 清除杂点
按钮4选中杂点区,按钮5删除之。大致清了桌前的一些杂点。
4. 网格化
Filter –> Point Set–> Surface Reconstruction: Poisson.
利用Poisson Surface Reconstruction算法由稠密点云生成多边形网格表面。
参数可调, Octree Depth:控制着网格的细节,此值越大细节越丰富但占内存越大运行起来慢,一般设10,可慢慢调大。
Poisson表面重建算法会生成一个“不漏水”气泡,把所有场景对象包裹在其中。即模型是封闭的。可以移除多余的面Filters –> Selection –> Select faces with edges longer than,而后删除。
保存(整个project和mesh)。
5. 修复流形边缘
后续的纹理处理要求网格化的模型必须是流形(MANIFOLD)的,因此需删除非流形边(简单讲就是任何由多面共享的边)。Filters –> Selection –> Select Non-Manifold edges,而后删除之。
6. 参数化(Parameterization)
Filter –> Texture –> Parameterization from registered rasters。
根据相机投影关系创建UV映射。
保存 (整个project和mesh)。
7. 投影纹理
Filter –> Texture –> Project active rasters color to current mesh, filling the texture。
可设置任意分辨率(512的2的二次方倍:512 / 1024 / 2048 / 4096 / 8192…)的纹理图。
6和7可以合为一步: Filter –> Texturing –> Parameterization + texturing from registered rasters.
8. 完成、导出
当你调整满意了之后,File –> Save mesh as… a .obj文件。即可便有了一个包含你选定分辨率纹理的obj文件。
收官啦。而后关乎应用,就是拼想象的时候了!
更多细节参见:We Did Stuff。