最近写了点SFM建图的代码,记录一些思路。
网上成熟的SFM软件很多,像openMVG,visualSFM等
建图流程:
- 提取所有图片的特征点及描述子,这里我用的是sift特征,鉴于openCV提取sift太慢了,所以用了siftGPU,关于这个高翔博士在博客中有详细介绍:http://www.cnblogs.com/gaoxiang12/p/5149067.html
按上述网址配置siftGPU,其中运行前需要运行 sudo ldconfig /usr/lib64/ 也可以export PATH=”$PATH:/usr/lib64/”
将提取到的数据存储下来 - 指定一组起始像对,或者随机挑选多组图片进行匹配,找到一组匹配最多的作为起始像对(此处还需改进)。根据初始像对的匹配点计算基本矩阵F,再计算本质矩阵E,分解本质矩阵得位姿RT,初始化坐标体系以及初始三维点云。(由于这里是不知道相机内参的,所以需要给个大致的初始值,这里用了cx=imagewidth/2,cy=imageheight/2,fx=fy=cx+cy;如果内参已知那自然最好,但考虑到大规模建图使用的像片来自很多相机,内参全已知不太可行,虽然我只用了一个序列)
- 后续图片的加入。每新加入一张图片,需要去与已有的图片比较找相似的,这个过程直接使用了简单粗暴的逐帧匹配(由于是一个序列,取了当前前5帧进行匹配),这样效率非常低下,后面考虑使用词袋模型。这里找到匹配点后,由于已知三维点和二维点了,使用solvePnPRansac计算位姿。
- BA,局部BA和整体BA。由于打算在加入BoW后再加入回环检测,只有局部BA的。BA所使用的库是ceres-solver http://www.ceres-solver.org/,用起来稍有点麻烦,不过很方便。
几个问题:
匹配点寻找策略:
sift匹配得到的特征点数目偏少,所以需要增加。
纯sift特征匹配(匹配阈值可适当加严)
另根据已有匹配点计算本质矩阵时
cv::Mat F = cv::findFundamentalMat(point1, point2, errorstate, cv::FM_RANSAC, 1, 0.99);
可通过errorstate来进一步筛选匹配点根据已有匹配计算出多个Homography矩阵,用H矩阵来增加新的匹配点。(关于H矩阵http://blog.youkuaiyun.com/heyijia0327/article/details/53782094说的很好)。这里涉及到怎么定义匹配代价,我考虑了最邻近+极线约束,但是极线约束写的有问题,导致匹配点并不准确。需要改进。
BoW(有待补充)
BA:
BA时要考虑多种情况,根据是否固定内参,畸变,投影矩阵构造不同的CostFunctor。