三维重建使用OpenMVG+OpenMVS做三维重建


这篇博客只是记录怎样使用OpenMVG和OpenMVS这两个开源工具完成一个三维重建的pipeline,不涉及开发。

为了简便,这里并没有用源码编译软件,而是直接下载的release版本。

OpenMVG是计算机视觉领域处理多视几何的开源库。

openMVG能够:

  1. 准确计算多视角立体几何模型;
  2. 提供SfM(Structure from Motion)重建需要的特征提取和匹配方法;
  3. 完整的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

可以看到重建的结果不是很完美,对图像的要求还是很高的。如果缺乏纹理,视角也不多变的话,大概率会重建失败。