当前位置:   article > 正文

使用 OpenMVG+PMVS实现视觉三维重建

cmvs-pmvs

点击上方“3D视觉工坊”,选择“星标”

干货第一时间送达

一、什么是视觉三维重建?

我们知道,照相机的原理是将一个三维场景投影到二维平面。所谓视觉三维重建,顾名思义就是从已有的二维图像中复原原始三维场景。

三维重建的原理大致如下:

  • 首先,通过多角度拍摄或者从视频中提取得到一组图像序列,将这些图像序列作为三维重建系统的输入;

  • 然后分析多个视角的图像,根据纹理特征提取出稀疏特征点(稀疏点云),通过这些特征点估计相机位置和参数;

  • 在得到相机参数并完成特征点匹配后,就可以获得更稠密的点云(这些点可以附带颜色,从远处看就像还原了物体本身一样,但从近处能明显看出它们只是一些点);

  • 最后根据这些点重建物体表面,并进行纹理映射,就还原出三维场景和物体了。

基于图像的三维重建基本流程

多张图像的特征点匹配

多视图稠密重建(MVS)

目前,有不少开源的三维重建系统,本文简单介绍使用OpenMVG(有CUDA的可以用colmap)+PMVS(OpenMVS安装的坑比较多),实现三维场景的三维重建。

二、OpenMVG/PMVS概述

openMVG (Open Multiple View Geometry):开源多视角立体几何库,这是一个 cv 界处理多视角立体几何的著名开源库,信奉“简单,可维护”,提供了一套强大的接口,每个模块都被测试过,尽力提供一致可靠的体验。

openMVG 实现以下典型应用:

  • 解决多视角立体几何的精准匹配问题;

  • 提供一系列 SfM 需要用到的特征提取和匹配方法;

  • 完整的 SfM 工具链(校正,参估,重建,表面处理等);

  • openMVG 尽力提供可读性性强的代码,方便开发者二次开发,核心功能是尽量精简的,所以你可能需要其它库来完善你的系统。

CMVS-PMVS(a modified version):将运动结构(SfM)软件的输出作为输入,然后将输入图像分解成一组可管理大小的图像簇。MVS 软件可以用来独立和并行地处理每个簇,其中来自所有簇的重建不错过任何细节。

常见的多视图三维重建管线:重建稀疏点云-Structure from Motion(Sfm)→重建稠密点云-Multi-View Stereo(MSV)→重建表面-Surface Generation(SG)→纹理映射-Texture Mapping(TM)

在本文中,OpenMVG负责从原始图像到稀疏点云,PMVS负责重建稠密点云、重建表面和纹理映射。我这里还使用了Meshlab查看模型(点云)生成效果。

三、安装OpenMVG+PMVS(Ubuntu16)

OpenMVG安装过程:(参考:openMVG官方BUILD.md)

  1. # 安装依赖
  2. sudo apt-get install libpng-dev libjpeg-dev libtiff-dev libxxf86vm1 libxxf86vm-dev libxi-dev libxrandr-dev graphviz
  3. # 克隆代码
  4. git clone --recursive https://github.com/openMVG/openMVG.git
  5. # configure && build
  6. mkdir openMVG_Build && cd openMVG_Build
  7. cmake -DCMAKE_BUILD_TYPE=RELEASE ../openMVG/src/ -DOpenMVG_BUILD_TESTS=ON
  8. sudo cmake --build . --target install
  9. # test
  10. make test
  11. ctest --output-on-failure -j
  12. # .bashrc
  13. export PATH=$PATH:/home/work/tools/openMVG_Build/Linux-x86_64-RELEASE/

CMVS-PMVS安装过程:

  1. git clone https://github.com/pmoulon/CMVS-PMVS.git
  2. cd CMVS-PMVS
  3. mkdir build && cd build
  4. cmake ../program/
  5. make
  6. sudo cp main/pmvs2 main/genOption main/cmvs /usr/local/bin/

四、三维重建实例(城堡)

1. OpenMVG提取稀疏点云(参考:openMVG使用示例)

原始数据:11张从不同角度拍摄的城堡照片

openMVG提取稀疏点云过程:(参考openMVG_Build/software/SfM/tutorial_demo.py,测试图片和脚本:openmvg_test.tar)

  1. cd openMVG
  2. vim 3dr_test.py
  3. #!/usr/bin/python
  4. #! -*- encoding: utf-8 -*-
  5. # openmvg使用示例
  6. # usage : python tutorial_demo.py
  7. import os
  8. import subprocess
  9. import sys
  10. # openmvg编译bin目录(可cp -p到/usr/local/bin/)
  11. OPENMVG_SFM_BIN = "/home/work/tools/openMVG_Build/Linux-x86_64-RELEASE"
  12. # pmvs编译bin目录(可cp -p到/usr/local/bin/)
  13. PMVS_BIN = "/home/work/tools/CMVS-PMVS/build/main"
  14. # openmvg相机参数目录
  15. CAMERA_SENSOR_WIDTH_DIRECTORY = "/home/work/tools/openMVG/src/openMVG/exif/sensor_width_database"
  16. # 0. 下载测试照片
  17. os.chdir(os.path.dirname(os.path.abspath(__file__)))
  18. data_dir = os.path.abspath("./book")
  19. #data_dir = os.path.abspath("./ImageDataset_SceauxCastle")
  20. '''if not os.path.exists(data_dir):
  21. pImageDataCheckout = subprocess.Popen([ "git", "clone", "https://github.com/openMVG/ImageDataset_SceauxCastle.git" ])
  22. pImageDataCheckout.wait()'''
  23. input_dir = os.path.join(data_dir, "images")
  24. output_dir = data_dir
  25. print ("Using input dir : ", input_dir)
  26. print (" output_dir : ", output_dir)
  27. matches_dir = os.path.join(output_dir, "matches")
  28. camera_file_params = os.path.join(CAMERA_SENSOR_WIDTH_DIRECTORY, "sensor_width_camera_database.txt") #相机参数
  29. if not os.path.exists(matches_dir):
  30. os.mkdir(matches_dir)
  31. # 1. 从图片数据集中生成场景描述文件sfm_data.json
  32. print ("----------1. Intrinsics analysis----------")
  33. 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"] )
  34. #*注:如果产出的sfm_data.json里intrinsics内容为空,通常是在图片没有exif信息导致获取不到相机焦距、ccd尺寸等参数,用带exif的原图即可。
  35. pIntrisics.wait()
  36. # 2. 计算图像特征
  37. print ("----------2. Compute features----------")
  38. 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"] )
  39. pFeatures.wait()
  40. # 3. 计算几何匹配
  41. print ("----------3. Compute matches----------")
  42. 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"] )
  43. pMatches.wait()
  44. # 4. 执行增量三维重建
  45. reconstruction_dir = os.path.join(output_dir,"reconstruction_sequential")
  46. print ("----------4. Do Incremental/Sequential reconstruction----------") #set manually the initial pair to avoid the prompt question
  47. pRecons = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_IncrementalSfM"), "-i", matches_dir+"/sfm_data.json", "-m", matches_dir, "-o", reconstruction_dir] )
  48. pRecons.wait()
  49. # 5. 计算场景结构颜色
  50. print ("----------5. Colorize Structure----------")
  51. 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")] )
  52. pRecons.wait()
  53. # 6. 测量稳健三角
  54. print ("----------6. Structure from Known Poses (robust triangulation)----------")
  55. 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")] )
  56. pRecons.wait()
  57. '''
  58. # 使用全局SfM管道重建Reconstruction for the global SfM pipeline
  59. # 3.1 全局sfm管道几何匹配
  60. print ("----------3.1. Compute matches (for the global SfM Pipeline)----------")
  61. pMatches = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_ComputeMatches"), "-i", matches_dir+"/sfm_data.json", "-o", matches_dir, "-r", "0.8", "-g", "e"] )
  62. pMatches.wait()
  63. # 4.1 执行全局三维重建
  64. reconstruction_dir = os.path.join(output_dir,"reconstruction_global")
  65. print ("----------4.1. Do Global reconstruction----------")
  66. pRecons = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_GlobalSfM"), "-i", matches_dir+"/sfm_data.json", "-m", matches_dir, "-o", reconstruction_dir] )
  67. pRecons.wait()
  68. # 5.1 计算场景结构颜色
  69. print ("----------5.1. Colorize Structure----------")
  70. 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")] )
  71. pRecons.wait()
  72. # 6.1 测量稳健三角
  73. print ("----------6.1. Structure from Known Poses (robust triangulation)----------")
  74. 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")] )
  75. pRecons.wait()
  76. '''
  77. # 7. 把openMVG生成的SfM_Data转为适用于PMVS输入格式的文件
  78. print ("----------7. Export to PMVS/CMVS----------")
  79. pRecons = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_openMVG2PMVS"), "-i", reconstruction_dir+"/sfm_data.bin", "-o", reconstruction_dir] )
  80. pRecons.wait()
  81. #*注:执行后会在-o路径下生成一个PMVS目录,包含 models, txt, visualize 三个子目录:models为空;txt包含对应图像的txt文档,每个里面都是一个3x4的矩阵,大概是相机位姿;visualize包含11张图像,不确定是原图像还是校正过的图像
  82. # 8. 使用PMVS重建稠密点云、表面、纹理
  83. print ("----------8. pmvs2----------")
  84. pRecons = subprocess.Popen( [os.path.join(PMVS_BIN, "pmvs2"), reconstruction_dir+"/PMVS/", "pmvs_options.txt"] ) # 注:不要修改pmvs_options.txt文件名
  85. pRecons.wait()
  86. #*注:执行后会在./PMVS/models文件夹中生成一个pmvs_options.txt.ply点云文件,用meshlab打开即可看到重建出来的彩色稠密点云。
  87. #执行三维重建测试
  88. python 3dr_test.py

2.安装MeshLab,查看生成的稀疏点云文件:

下载安装:http://www.meshlab.net/#download

右上方俯视城堡稀疏点云 :(打开reconstruction_xxx下的colorized.ply或robust.ply)

3.PMVS重建稠密点云、重建表面和纹理映射过程:(测试生成的PMVS目录:pmvs_test.tar)

  1. # 1. 把openMVG生成的SfM_Data转为适用于PMVS输入格式的文件
  2. cd openMVG/ImageDataset_SceauxCastle/reconstruction_global/
  3. openMVG_main_openMVG2PMVS -i sfm_data.bin -o ./
  4. *注:执行后会在-o路径下生成一各PMVS目录,包含 models, txt, visualize 三个子目录:models为空;txt包含对应图像的txt文档,每个里面都是一个3x4的矩阵,大概是相机位姿;visualize包含11张图像,不确定是原图像还是校正过的图像
  5. # 2. 使用PMVS重建稠密点云、表面、纹理
  6. pmvs2 ./PMVS/ pmvs_options.txt # 注:不要修改pmvs_options.txt文件名
  7. *注:执行后会在./PMVS/models文件夹中生成一个pmvs_options.txt.ply点云文件,用meshlab打开即可看到重建出来的彩色稠密点云。

生成的三维稠密点云俯视角:

五、三维重建实例(书)

1.准备照片

注意事项:

  • 自己拍的照片必须确保照片里有exif信息!(光圈、焦距、品牌、ccd尺寸等),定位拍摄姿态和角度等用,没有会很麻烦;不要用微信/Hi等工具传,exif信息会丢失(选原图也会丢),亲测AirDrop(隔空投送)是不会丢的;

  • 照片最少准备3张以上,否则大概率重建失败;

拿手边的书随便拍了几张:book.zip

2.三维重建

python 3dr_test.py

六、常见问题

1.openMVG_main_IncrementalSfM: error while loading shared libraries: liblapack.so: cannot open shared object file: No such file or directory

解决方法:

  1. $ which openMVG_main_IncrementalSfM
  2. /usr/local/bin/openMVG_main_IncrementalSfM
  3. $ ll openMVG_Build/Linux-x86_64-RELEASE/openMVG_main_IncrementalSfM
  4. openMVG_Build/Linux-x86_64-RELEASE/openMVG_main_IncrementalSfM
  5. #经过对比测试发现/usr里确实是最新build的文件,但链接关系貌似有问题;直接使用openMVG_Build/Linux-x86_64-RELEASE/openMVG_main_IncrementalSfM就能正常
  6. $ sudo cp ../openMVG_Build/Linux-x86_64-RELEASE/* /usr/local/bin/ #整体cp覆盖后恢复正常

2.type INITIAL pair ids: X enter Y enter

  1. ----------------------------------------------------
  2. SequentialSfMReconstructionEngine::ChooseInitialPair
  3. ----------------------------------------------------
  4. Pairs that have valid intrinsic and high support of points are displayed:
  5. Choose one pair manually by typing the two integer indexes
  6. ----------------------------------------------------
  7. (1,5) 77 matches
  8. (2,4) 39 matches
  9. (0,2) 39 matches
  10. (3,7) 31 matches
  11. (2,5) 29 matches
  12. (2,3) 19 matches
  13. (0,1) 18 matches
  14. type INITIAL pair ids: X enter Y enter
  15. 2
  16. 4
  17. Putative starting pair is: (2,4)
  18. A-Contrario initial pair residual: 7.61613

SfM过程中遇到这个提示,可以按以上方式输入跳过,不过通常这时照片的质量堪忧,不要指望建出来预期的效果了,不如老老实实多重拍些,用视频切桢也行。

七、其他

生成的三维点云数据如果要用于自动驾驶避障,最好增加超声波、毫米波雷达,并把各传感器生成的点云与视觉重建点云进行融合。对融合后的点云数据进行噪点清理、三维目标检测,生成三维障碍物的类型/大小/位置信息,再根据三维空间的行进方向进行避障路径规划。

本文仅做学术分享,如有侵权,请联系删文。

下载1

在「3D视觉工坊」公众号后台回复:3D视觉即可下载 3D视觉相关资料干货,涉及相机标定、三维重建、立体视觉、SLAM、深度学习、点云后处理、多视图几何等方向。

下载2

在「3D视觉工坊」公众号后台回复:3D视觉github资源汇总即可下载包括结构光、标定源码、缺陷检测源码、深度估计与深度补全源码、点云处理相关源码、立体匹配源码、单目、双目3D检测、基于点云的3D检测、6D姿态估计源码汇总等。

下载3

在「3D视觉工坊」公众号后台回复:相机标定即可下载独家相机标定学习课件与视频网址;后台回复:立体匹配即可下载独家立体匹配学习课件与视频网址。

重磅!3DCVer-学术论文写作投稿 交流群已成立

扫码添加小助手微信,可申请加入3D视觉工坊-学术论文写作与投稿 微信交流群,旨在交流顶会、顶刊、SCI、EI等写作与投稿事宜。

同时也可申请加入我们的细分方向交流群,目前主要有3D视觉CV&深度学习SLAM三维重建点云后处理自动驾驶、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、学术交流、求职交流、ORB-SLAM系列源码交流、深度估计等微信群。

一定要备注:研究方向+学校/公司+昵称,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,可快速被通过且邀请进群。原创投稿也请联系。

▲长按加微信群或投稿

▲长按关注公众号

3D视觉从入门到精通知识星球:针对3D视觉领域的知识点汇总、入门进阶学习路线、最新paper分享、疑问解答四个方面进行深耕,更有各类大厂的算法工程人员进行技术指导。与此同时,星球将联合知名企业发布3D视觉相关算法开发岗位以及项目对接信息,打造成集技术与就业为一体的铁杆粉丝聚集区,近2000星球成员为创造更好的AI世界共同进步,知识星球入口:

学习3D视觉核心技术,扫描查看介绍,3天内无条件退款

 圈里有高质量教程资料、可答疑解惑、助你高效解决问题

觉得有用,麻烦给个赞和在看~  

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/238640
推荐阅读
相关标签
  

闽ICP备14008679号