这篇博客只是记录怎样使用OpenMVG和OpenMVS这两个开源工具完成一个三维重建的pipeline,不涉及开发。
为了简便,这里并没有用源码编译软件,而是直接下载的release版本。
OpenMVG是计算机视觉领域处理多视几何的开源库。
openMVG能够:
- 准确计算多视角立体几何模型;
- 提供SfM(Structure from Motion)重建需要的特征提取和匹配方法;
- 完整的SfM工具链;
OpenMVG:https://github.com/openMVG/openMVG/releases。
我直接下载了最新版本,目前的V1.6。解压之后如图
文件夹下有众多的exe文件。
OpenMVS是计算机视觉领域另一个开源算法库,着重解决多视点立体重建,如稠密点云重建,表面重建,表面细化,纹理映射等。
OpenMVS:https://github.com/cdcseacave/openMVS/releases。
我下载的最新版是V1.1.1,解压之后如图
也有很多exe文件和动态库。
OpenMVG+OpenMVS恰好可以完成一个三维重建的pipeline。
一、OpenMVG
解压后的OpenMVG中有以下三个文件
SfM_GlobalPipeline.py是全局式SfM算法,SfM_SequentialPipeline.py是增量式SfM算法。简单一点就直接运行tutorial_demo.py脚本。默认使用的是ImageDataset_SceauxCastle里的图片,如果没有会自动从git上下载。
里面的图片是这样的
有一个K.txt文件是相机的内参,demo里并没有用到
Demo里用到是sensor_width_database下的sensor_width_camera_database.txt里面有大量厂商的相机内参数据。
如果照相机的型号不在这个列表里,(没看代码但猜测)应该是从图片的exif信息也可以推测出。但图片没有exif信息的话,就要自己提供这个K.txt文件了。
仿照demo里的文件组织,使用自己的图片进行三维重建,在同级目录下新建自己的文件夹milk,milk下新建images文件夹,把所有图片放到images文件夹下。
修改tutorial_demo.py 23行的ImageDataset_SceauxCastle为milk。
可以看一下tutorial_demo.py,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | print ("1. Intrinsics analysis") pIntrisics = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_SfMInit_ImageListing"), "-i", input_dir, "-o", matches_dir, "-d", camera_file_params, "-c", "3"] ) pIntrisics.wait() print ("2. Compute features") pFeatures = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_ComputeFeatures"), "-i", matches_dir+"/sfm_data.json", "-o", matches_dir, "-m", "SIFT", "-f" , "1"] ) pFeatures.wait() print ("2. Compute matches") pMatches = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_ComputeMatches"), "-i", matches_dir+"/sfm_data.json", "-o", matches_dir, "-f", "1", "-n", "ANNL2"] ) pMatches.wait() reconstruction_dir = os.path.join(output_dir,"reconstruction_sequential") print ("3. Do Incremental/Sequential reconstruction") #set manually the initial pair to avoid the prompt question pRecons = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_IncrementalSfM"), "-i", matches_dir+"/sfm_data.json", "-m", matches_dir, "-o", reconstruction_dir] ) pRecons.wait() print ("5. Colorize Structure") pRecons = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_ComputeSfM_DataColor"), "-i", reconstruction_dir+"/sfm_data.bin", "-o", os.path.join(reconstruction_dir,"colorized.ply")] ) pRecons.wait() print ("4. Structure from Known Poses (robust triangulation)") pRecons = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_ComputeStructureFromKnownPoses"), "-i", reconstruction_dir+"/sfm_data.bin", "-m", matches_dir, "-o", os.path.join(reconstruction_dir,"robust.ply")] ) pRecons.wait() |
其实就是调用了OpenMVG下的几个exe文件,完成重建的几个步骤。自己可以单独调用,一步步看中间结果,这里为了简便就直接运行脚本了。
执行脚本
1 | python tutorial_demo.py |
根据图片的大小和特征需等待数分钟。
完成。产生了一个tutorial_out文件夹,里面有三个子文件夹。
其中matches文件夹下是关于特征和匹配的一些文件,
而reconstruction_global和reconstruction_sequential是两种SfM方法产生的结果。
以reconstruction_global为例,
打开SfMReconstruction_Report.html,可以看到SfM重建的报告,
这里面还有一个最重要的文件sfm_data.bin,就是重建的数据。
在进行OpenMVS步骤之前还需要将上一步生成的sfm_data.bin转化成mvs格式。
OpenMVG下有一个可执行文件openMVG_main_openMVG2openMVS.exe可以完成这个功能。
1 | openMVG_main_openMVG2openMVS.exe -i tutorial_out\reconstruction_global\sfm_data.bin -o tutorial_out\reconstruction_global\scene.mvs |
这一步会产生两个输出,一个就是scene.mvs这个文件,另一个就是一个undistorted_images文件夹,里面是经过畸变校正的图像。
至此,OpenMVG的使命完成。
二、OpenMVS
将OpenMVG中生成的scene.mvs和undistorted_images文件夹拷贝到OpenMVS目录下。
先用Viewer查看一下稀疏点云,
1 | Viewer.exe scene.mvs |
生成稠密点云,
1 | DensifyPointCloud.exe scene.mvs |
这个过程比较耗时,我这十几张图片的场景会花费数分钟。
又生成了一系列文件。
查看稠密点云。
1 | Viewer.exe scene_dense.mvs |
建立粗网格,
1 | ReconstructMesh.exe scene_dense.mvs |
查看粗网格,
1 | Viewer.exe scene_dense_mesh.mvs |
生成精细网格(可选),相当耗时。
1 | RefineMesh.exe scene_dense_mesh.mvs |
查看结果,
1 | Viewer.exe scene_dense_mesh_refine.mvs |
建立混合网格,
1 | TextureMesh.exe scene_dense_mesh_refine.mvs |
查看最终结果,
1 | Viewer.exe scene_dense_mesh_refine_texture.mvs |
可以看到重建的结果不是很完美,对图像的要求还是很高的。如果缺乏纹理,视角也不多变的话,大概率会重建失败。