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

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

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

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

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

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

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

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

多张图像的特征点匹配

多视图稠密重建(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)

# 安装依赖

sudo apt-get install libpng-dev libjpeg-dev libtiff-dev libxxf86vm1 libxxf86vm-dev libxi-dev libxrandr-dev graphviz

# 克隆代码

git clone --recursive https://github.com/openMVG/openMVG.git

# configure && build

mkdir openMVG_Build && cd openMVG_Build

cmake -DCMAKE_BUILD_TYPE=RELEASE ../openMVG/src/ -DOpenMVG_BUILD_TESTS=ON

sudo cmake --build . --target install

# test

make test

ctest --output-on-failure -j

# .bashrc

exportPATH=$PATH:/home/work/tools/openMVG_Build/Linux-x86_64-RELEASE/

CMVS-PMVS安装过程:

git clone https://github.com/pmoulon/CMVS-PMVS.git

cd CMVS-PMVS

mkdir build && cd build

cmake ../program/

make

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)

cd openMVG

vim 3dr_test.py

#!/usr/bin/python

#! -*- encoding: utf-8 -*-

# openmvg使用示例

# usage : python tutorial_demo.py

import os

import subprocess

import sys

# openmvg编译bin目录(可cp -p到/usr/local/bin/)

OPENMVG_SFM_BIN = "/home/work/tools/openMVG_Build/Linux-x86_64-RELEASE"

# pmvs编译bin目录(可cp -p到/usr/local/bin/)

PMVS_BIN = "/home/work/tools/CMVS-PMVS/build/main"

# openmvg相机参数目录

CAMERA_SENSOR_WIDTH_DIRECTORY = "/home/work/tools/openMVG/src/openMVG/exif/sensor_width_database"

# 0. 下载测试照片

os.chdir(os.path.dirname(os.path.abspath(__file__)))

data_dir = os.path.abspath("./book")

#data_dir = os.path.abspath("./ImageDataset_SceauxCastle")

'''if not os.path.exists(data_dir):

pImageDataCheckout = subprocess.Popen([ "git", "clone", "https://github.com/openMVG/ImageDataset_SceauxCastle.git" ])

pImageDataCheckout.wait()'''

input_dir = os.path.join(data_dir, "images")

output_dir = data_dir

print ("Using input dir : ", input_dir)

print (" output_dir : ", output_dir)

matches_dir = os.path.join(output_dir, "matches")

camera_file_params = os.path.join(CAMERA_SENSOR_WIDTH_DIRECTORY, "sensor_width_camera_database.txt") #相机参数

if not os.path.exists(matches_dir):

os.mkdir(matches_dir)

# 1. 从图片数据集中生成场景描述文件sfm_data.json

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"] )

#*注:如果产出的sfm_data.json里intrinsics内容为空,通常是在图片没有exif信息导致获取不到相机焦距、ccd尺寸等参数,用带exif的原图即可。

pIntrisics.wait()

# 2. 计算图像特征

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()

# 3. 计算几何匹配

print ("----------3. 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()

# 4. 执行增量三维重建

reconstruction_dir = os.path.join(output_dir,"reconstruction_sequential")

print ("----------4. 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()

# 5. 计算场景结构颜色

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()

# 6. 测量稳健三角

print ("----------6. 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()

'''

# 使用全局SfM管道重建Reconstruction for the global SfM pipeline

# 3.1 全局sfm管道几何匹配

print ("----------3.1. Compute matches (for the global SfM Pipeline)----------")

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"] )

pMatches.wait()

# 4.1 执行全局三维重建

reconstruction_dir = os.path.join(output_dir,"reconstruction_global")

print ("----------4.1. Do Global reconstruction----------")

pRecons = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_GlobalSfM"), "-i", matches_dir+"/sfm_data.json", "-m", matches_dir, "-o", reconstruction_dir] )

pRecons.wait()

# 5.1 计算场景结构颜色

print ("----------5.1. 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()

# 6.1 测量稳健三角

print ("----------6.1. 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()

'''

# 7. 把openMVG生成的SfM_Data转为适用于PMVS输入格式的文件

print ("----------7. Export to PMVS/CMVS----------")

pRecons = subprocess.Popen( [os.path.join(OPENMVG_SFM_BIN, "openMVG_main_openMVG2PMVS"), "-i", reconstruction_dir+"/sfm_data.bin", "-o", reconstruction_dir] )

pRecons.wait()

#*注:执行后会在-o路径下生成一个PMVS目录,包含 models, txt, visualize 三个子目录:models为空;txt包含对应图像的txt文档,每个里面都是一个3x4的矩阵,大概是相机位姿;visualize包含11张图像,不确定是原图像还是校正过的图像

# 8. 使用PMVS重建稠密点云、表面、纹理

print ("----------8. pmvs2----------")

pRecons = subprocess.Popen( [os.path.join(PMVS_BIN, "pmvs2"), reconstruction_dir+"/PMVS/", "pmvs_options.txt"] ) # 注:不要修改pmvs_options.txt文件名

pRecons.wait()

#*注:执行后会在./PMVS/models文件夹中生成一个pmvs_options.txt.ply点云文件,用meshlab打开即可看到重建出来的彩色稠密点云。

#执行三维重建测试

python 3dr_test.py

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

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

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

# 1. 把openMVG生成的SfM_Data转为适用于PMVS输入格式的文件

cd openMVG/ImageDataset_SceauxCastle/reconstruction_global/

openMVG_main_openMVG2PMVS -i sfm_data.bin -o ./

*注:执行后会在-o路径下生成一各PMVS目录,包含 models, txt, visualize 三个子目录:models为空;txt包含对应图像的txt文档,每个里面都是一个3x4的矩阵,大概是相机位姿;visualize包含11张图像,不确定是原图像还是校正过的图像

# 2. 使用PMVS重建稠密点云、表面、纹理

pmvs2 ./PMVS/ pmvs_options.txt # 注:不要修改pmvs_options.txt文件名

*注:执行后会在./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

解决方法:

$ which openMVG_main_IncrementalSfM

/usr/local/bin/openMVG_main_IncrementalSfM

$ ll openMVG_Build/Linux-x86_64-RELEASE/openMVG_main_IncrementalSfM

openMVG_Build/Linux-x86_64-RELEASE/openMVG_main_IncrementalSfM

#经过对比测试发现/usr里确实是最新build的文件,但链接关系貌似有问题;直接使用openMVG_Build/Linux-x86_64-RELEASE/openMVG_main_IncrementalSfM就能正常

$ sudo cp ../openMVG_Build/Linux-x86_64-RELEASE/* /usr/local/bin/ #整体cp覆盖后恢复正常

2.type INITIAL pair ids: X enter Y enter

----------------------------------------------------

SequentialSfMReconstructionEngine::ChooseInitialPair

----------------------------------------------------

Pairs that have valid intrinsic and high support of points are displayed:

Choose one pair manually by typing the two integer indexes

----------------------------------------------------

(1,5)77 matches

(2,4)39 matches

(0,2)39 matches

(3,7)31 matches

(2,5)29 matches

(2,3)19 matches

(0,1)18 matches

type INITIAL pair ids: X enter Y enter

2

4

Putative starting pair is: (2,4)

A-Contrario initial pair residual: 7.61613

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

七、其他

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

yan 20.1.20

参考:

python 稠密重建_使用openMVG+PMVS实现视觉三维重建相关推荐

  1. python 稠密重建_毕业设计记录的三维重建2:CMVs密集点云重建,之,2cmvs,稠密,实现...

    稠密重建部分直接在sfm的基础之上调用cmvs可执行程序,cmvs集成了稀疏点云聚类算法和基于面片的稠密重建算法pmvs,其中pmvs是目前效果最好的稠密重建算法. cmvs可执行程序在windows ...

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

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 一.什么是视觉三维重建? 我们知道,照相机的原理是将一个三维场景投影到二维平面.所谓视觉三维重建,顾名 ...

  3. 三维重建 几何方法 深度学习_基于深度学习的视觉三维重建研究总结

    三维重建意义 三维重建作为环境感知的关键技术之一,可用于自动驾驶.虚拟现实.运动目标监测.行为分析.安防监控和重点人群监护等.现在每个人都在研究识别,但识别只是计算机视觉的一部分.真正意义上的计算机视 ...

  4. 计算机视觉中的多视图几何_基于深度学习的视觉三维重建研究总结

    三维重建意义 三维重建作为环境感知的关键技术之一,可用于自动驾驶.虚拟现实.运动目标监测.行为分析.安防监控和重点人群监护等.现在每个人都在研究识别,但识别只是计算机视觉的一部分.真正意义上的计算机视 ...

  5. python 3d重建_三维人脸重建(一)——Python读取obj文件

    目录 一.obj格式模型介绍 文件说明很有必要,有助于数据提取时的理解.这一部分借鉴OBJ格式模型详细介绍 obj格式有4种数据,分别以一下字母开头: 1. v顶点 2. vt纹理坐标 3. vn顶点 ...

  6. 肺部ct重建_肺部CT血管分割及三维重建

    摘要: 现代社会人们的生活水平不断改善,由于膳食不合理以及锻炼的缺乏,我国血管类疾病发生率不断攀高,传统的逐张读片的诊断方式效率低下且依赖于医生个人的知识储备,本文以肺部CT序列为着重点,对其中的血管 ...

  7. 三维重建关键技术分享:特征检测+匹配+RT恢复+稠密重建方法

    视觉三维重建 = 定位定姿 + 稠密重建 + surface reconstruction +纹理贴图.三维重建技术是计算机视觉的重要技术之一,基于视觉的三维重建技术通过深度数据获取.预处理.点云配准 ...

  8. 【三维深度学习】Sparse Convolutional Network 基于稀疏采样不变性的深度稠密重建

    为了从稀疏的深度采样(Lidar)中重建出稠密的深度信息, 研究人员提出了一种高效的稀疏卷积层,用于在训练过程中精确定位数据缺失的位置,实现了具有稀疏不变性的特征抽取和重建手段.Sparsity In ...

  9. 计算机编程导论python程序设计答案-学堂在线_计算机科学与Python编程导论_作业课后答案...

    学堂在线_计算机科学与Python编程导论_作业课后答案 答案: 更多相关问题 近代中国完全沦为半殖民地半封建社会的标志是:A.<马关条约>B.<辛丑条约>C.<凡尔赛和 ...

  10. python 爬虫源代码-从零开始学Python网络爬虫_源代码.rar

    [实例简介] [实例截图] [核心代码] 从零开始学Python网络爬虫_源代码_1 ├── 58project │ ├── __pycache__ │ │ ├── channel_extract.c ...

最新文章

  1. LIS ZOJ - 4028
  2. 透视世界人工智能发展
  3. matlab练习程序(简单图像融合)
  4. Android UI开发第三十篇——使用Fragment构建灵活的桌面
  5. risc-v 操作系统教程
  6. PythonOpenCV - 随机生成图像 与 图像的转维(reshape)
  7. BZOJ4066: 简单题
  8. OpenGL 实例化 Instancing
  9. Idea 依赖冲突一分钟解决2种方案
  10. 运算符--位移运算符和一些其他运算符
  11. Doris之审计日志插件
  12. 算法入门—《啊哈算法》读书总结
  13. 软件实施工程师的经验之谈(适合新手,老鸟请指正)
  14. VS2013 IDE C#生成CodeMap
  15. GAMMA初学笔记二
  16. vue2的 watch的理解(7)
  17. MySQL 存储过程的写法
  18. java微信公众号服务器配置
  19. java窗体中添加图片_在java窗体程序中添加图片的方法
  20. PDF文件只能打印出第一页

热门文章

  1. 阿里P4 - P14技能要求及对应薪资曝光
  2. 用python来更改小伙伴的windows开机密码,不给10块不给开机
  3. 如何选择物联网服务商
  4. 不同网段共享文件服务器,不同网段ip 如何设置局域网共享?
  5. matlab中求积函数,高斯求积公式 matlab
  6. ps3自建服务器,PS3新手图文教程之网络设置
  7. 触发Full GC执行的情况
  8. 谷歌翻译SDK (Google Translate SDK)的使用
  9. 你应当知道的人工智能发展历史
  10. python网课一般多少钱-十大python零基础编程在线网课一对一费用多少钱