请选择 进入手机版 | 继续访问电脑版

点云技术相关产学研社区

 找回密码
 立即注册加入PCL中国点云技术相关产学研社区

扫一扫,访问微社区

查看: 25091|回复: 4

VisualSFM使用方法与心得

[复制链接]
发表于 2017-11-6 21:56:52 | 显示全部楼层 |阅读模式
VisualSFM是Changchang Wu编写的使用 Structure from Motion (SfM)进行3D重建的交互界面,具体内容详见http://ccwu.me/vsfm/使用方法参考官方文档http://ccwu.me/vsfm/doc.html

在这里说一些到目前为止的使用心得。

使用VisualSFM进行多图三维重建,第一步把多张图片加载进去,然后点击Match the Images,或者菜单中的“[size=14.6667px]SfM->Pairwise Matching->Compute Missing Match”,程序会自动计算图片中的sift点,并在图片路径目录下保存相应sift文件,然后默认执行全局匹配,并把匹配数据保存在图片路径下的.mat文件。

需要注意的是,执行全局匹配是指,所有图片都要和其他图片比一遍。因此时间复杂度是O(N^2)。并不是所有的图片数据都适合执行全局匹配。


该程序支持自定义匹配模式,只需要自己写一个.txt文件,类似这样:
a.jpg b.jpg
a.jpg c.jpg
b.jpg c.jpg
在把图像加载进来以后,选择菜单中的“SfM->Pairwise Matching -> Compute Specified Match”选项,载入刚才我们自定义的.txt文件,程序就会执行自定义匹配。

对于视频序列,可以使用菜单中的“SfM->Pairwise matching->Compute Sequence Match”选项,设置匹配临近范围。

使用这些选项可以有效提高计算速度和准确度。另外,勾选“SfM->More Fuctions->Use Shared Calibration”似乎也可以提高准确度。

然后执行稀疏重建和稠密重建。

在加载图片、计算sift特征点并匹配、稀疏重建和稠密重建4个步骤中,任意两个步骤之间都可以继续添加图片并重新执行,也可以存成nvm文件来保存工作空间。

nvm的格式如下:
NVM_V3 [optional calibration]                        # file version header
<Model1> <Model2> ...                                # multiple reconstructed models
<Empty Model containing the unregistered Images>     # number of camera > 0, but number of points = 0
<0>                                                  # 0 camera to indicate the end of model section
<Some comments describing the PLY section>
<Number of PLY files> <List of indices of models that have associated PLY>


The [optional calibration] exists only if you use "Set Fixed Calibration" Function
FixedK fx cx fy cy

Each reconstructed <model> contains the following
<Number of cameras>   <List of cameras>
<Number of 3D points> <List of points>

The cameras and 3D points are saved in the following format
<Camera> = <File name> <focal length> <quaternion WXYZ> <camera center> <radial distortion> 0
<Point>  = <XYZ> <RGB> <number of measurements> <List of Measurements>
<Measurement> = <Image index> <Feature Index> <xy>


想要知道具体怎么解析这个文件,可以查看Multicore bundle adjustment中的util.h来获得更多细节。

该软件还有很多技术细节,如相机内参和坐标系统,焦段初始化,sift导致的图片上下采样等,等我继续研究之后再更新。

作者说了VisualSFM是一款闭源软件,尽管如此,其中的SiftGPU (feature detection & matching) PBA (multicore bundle adjustment)部分是开源的。想用的话可以轻松使用并修改。
回复

使用道具 举报

发表于 2017-11-7 11:07:17 | 显示全部楼层
焦段初始化 是啥意思,是焦距吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-10 14:18:09 | 显示全部楼层
mypcl 发表于 2017-11-7 11:07
焦段初始化 是啥意思,是焦距吗?

是焦距,程序中相机内参是根据图像的exif信息自动计算的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-10 15:40:55 | 显示全部楼层
本帖最后由 v77pt 于 2017-11-10 15:46 编辑

VisualSfM使用注意事项:

输入数据(input):
VisualSfM只能以jpeg格式的照片作为输入,在读取jpeg文件时,VisualSfM会根据jpeg中的EXIF信息计算每一张照片的相机内参。


EXIF信息是相机在拍照的时候自动保存在照片中的,请确保输入的jpeg中包含正确的EXIF信息,否则图像匹配和重建的效果会非常差,具体改进方法参见下文。


焦距初始化(Focal length initialization):
VisualSfM中的焦距初始化是自动完成的。每一张照片的焦距是根据该照片内保存的EXIF信息(EXIF.Focallength and FocalplaneXRes/FocalplaneYRes)自动计算的,而不是根据CCD数据库计算的。所以需要注意:当你要resize照片时,确保照片中的EXIF信息没有丢失。
如果照片中不包含EXIF信息,焦距会被初始化为1.2 * max(width, height)。如果是这样,或是照片中的EXIF信息很差,重建效果一般都非常差,通过设置菜单中的“SfM -> More functions -> Set Fixed Calibration”来为所有照片设置相同且固定的相机内参[fx, cx, fy, cy]


拍摄照片注意事项:

手法:看过科研工作者们如何演示他们的SLAM/SfM系统,就会发现,他们都会小心翼翼的摆动手中的摄像头。这是因为,在摄像头的平移和旋转两种运动中,平移运动能够更有效的对特征点进行重建,因为远的特征点在图像坐标中移动慢,而近的移动快。所以在采集图像的过程中,尽可能从不同的位置对物体进行拍摄,同时在相邻照片中保留更多的相同景物。

农大东区体育馆示例:

尽量有序地采集照片,这样在使用VisualSfM进行match的时候,不用进行全局match,只需要使用“SfM->Pairwise matching->Compute Sequence Match”就可以了。使用这种匹配模式,需要设置一个参数n(我使用10,理论上更小的参数应该也可以),这样一来,照片只会和最近的n张照片进行匹配,可以节省很多时间。

农大东区体育馆重建效果:


可以看到重建效果还不错,相机位姿和我当时拍摄的路线几乎一样。



更多注意事项:
  • 如果是用手机拍摄的室外场景,在match之前勾选“SfM->More Fuctions->Use Shared Calibration”效果更好。因为在室外场景中,物体都比较远,相机内参变化不大。
  • 注意菜单右边的齿轮。Ctrl+鼠标左键点击,可以编辑一些程序参数。大部分参数已经被调整为最优的了。如果没有遇到问题几乎都不用管。
  • 我在拍摄过程中大概是1秒按一次快门,没有试过拍视频,然后在后期导出成序列图像,因为从视频中导出EXIF文件似乎很麻烦,就懒得试了。
  • 我用的电脑是笔记本,显卡是GTX970M,配置了CUDA和Cudnn,VisualSfM-gpu要用到CUDA库。另外显卡内存太小也可能会遇到问题。
  • 重建效果不好的话,会重建出来多个模型,一般有两个原因,一个是,各个模型之间没有共享足够多的图像特征,也就是说,在不同视点之间缺少特征匹配,解决方法是在这些视点中拍足够多的照片。另一个可能的原因是初始化问题,如果各个模型中有足够多的共享特征,可以试用“SfM->More Functions->Merge Sparse Models”看看能不能合并模型。



更多问题请查看官方文档Documentation
或联系我,如果有空的话我会回复:0magicwing0@163.com

回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-11-14 16:32:03 | 显示全部楼层
关于VisualSfM的更多内容


组合多个模型What if VisualSFM produces multiple models?

按照上述步骤进行稀疏重建后,理论上可以得到很好的模型。如果结果产生了多个模型,要想把多个模型合成成一个,点击菜单中的“SfM->More Functions->Merge Sparse Models”。log信息中会提示你各个模型中有多少共享的特征点,如果特征点数量小于程序默认的最小值,则不会进行模型融合。编辑VisualSfM路径下的nv.ini文件,可以修改程序要求的最小值“param_model_merge_min_matches ”(默认是100),把该参数改成小于模型间共享特征点数量的一个数(不宜小于10),再执行“SfM->More Functions->Merge Sparse Models”应该就可以融合有共享特征的模型了。如果模型之间一个共享特征都没有,那就只能从头来了。


稠密重建(Dense reconstruction):

在稀疏重建结束后,点击CMVS可以对模型进行稠密重建。CMVS会对样本进行聚类,再根据每一个聚类生成一个ply模型文件,生成时间较长,需要耐心等待。

中国农业大学东校区体育馆的稠密重建示例如下:

中国农业大学工学院的稠密重建示例如下:



输出格式The output format: N-View Match (NVM) & PLY):

NVM

理解NVM文件最简单的方法就是用TXT文本文件或Sublime Text打开,就可以直观的看到其组织方式。

NVM_V3

2
et007.jpg    660.197875977 0.998820995653 0.0275106001103 -0.0259087505623 0.0304716951484 0 0 0 0 0
et008.jpg    660.197875977 0.160476730087 -0.112869970691 -0.125560022607 -0.972492485698 -0.380315317109 -0.867596366593 0.320369513256 0 0

1111
-0.16864857602 0.290092727826 3.09711024403 231 201 214 2 0 0 -72.4277801514 22.055480957 1 3 158.19152832 -77.7308959961
…………

2代表2张照片,即下面2行,每一行是一个照片的参数。参数按空格分割依次是<File name> <focal length> <quaternion WXYZ> <camera center> <radial distortion> 0
然后1111代表有1111个点,每一行是一个点的信息,参数按空格分割依次是<XYZ> <RGB> <number of measurements> <List of Measurements>
一般我们只关心XYZ和RGB,取前6维数据即可。

Multicore bundle adjustment中的util.h文件提供了C++版本的nvm文件解析方法。我自己用python写了一个。其实就是按行解析,每一行以空格' '作为分隔符,就可以得到如下文件,因为pandas存储CSV是无序的,所以列没有按顺序保存。

其中dataframe是每一张照片对应的相机参数,坐标(XYZ)和四元数(WPQR)如下:


point_dataframe是点云文件,每一行对应一个点的颜色(RGB)和坐标(XYZ)如下:


PLY

PLY是一种电脑档案格式,全名为多边形档案(Polygon File Format)斯坦福三角形档案(Stanford Triangle Format)
稠密重建的结果会保存成PLY文件格式。它的具体格式如下:

ply
format ascii 1.0
element vertex 257684
property float x
property float y
property float z
property float nx
property float ny
property float nz
property uchar diffuse_red
property uchar diffuse_green
property uchar diffuse_blue
end_header
-0.721213 -2.01925 2.6344 0.130806 0.0792633 -0.988234 205 214 218
-0.991508 -1.99528 2.58972 0.163215 0.0746168 -0.983765 195 202 202
…………

前门是头文件,property描述了头文件之后的每一列的特征。也就是说,在end_header之后,按空格分隔,这9个数字依次代表点的坐标XYZ,法向量nx、ny、nz,和像素RGB。
这样只需要按类似方法解析就可以使用了。


坐标系统(coordinate system

Documentation原文说”As for the image coordinate system, X-axis points right, and Y-axis points downward, so Z-axis points forward.”
即X轴指右,Y轴指下,Z轴指前。这和openGL与Unity的坐标系统都不同,使用时注意坐标矫正。


用Unity游戏引擎进行可视化(Visualization with Unity):

Unity的Asset store上有很多点云库,我随便下载了一个。


把我们的点云数据转成了它要的off文件,就可以使用在unity里查看点云了。需要注意的是,要把读取坐标的代码修改一下,读取坐标y的时候要乘以-1,这样显示结果才是正确的。

off文件具体形式如下:

COFF
20733 0 0
0.253539073845 -0.100282664831 4.76099905695 20 24 12 255
1.53241726658 -2.33590458129 5.98022141801 62 58 52 255
…………

第二行表示点的数量
后面的参数按行分割就是每一个点,按空格分割是XYZ和RGB。


我们也可以对相机位姿进行可视化,可以看到可上图结果是差不多的。需要注意的是相机的y坐标和四元数Q也要乘以-1。


最后用unity自带相机对重建结果进行可视化验证。把相机坐标和角度赋值给unity相机以后,调整unity相机的Fov(field of view),我这里是50。然后以当前位姿拍摄的照片作为相机背景,即可得到如下效果。








回复 支持 反对

使用道具 举报

本版积分规则

QQ|小黑屋|点云技术相关产学研社区 ( 陕ICP备13001629号 )

GMT+8, 2024-3-29 06:42 , Processed in 2.498907 second(s), 16 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表