由于ORB-SLAM2双目的稠密点云重建与RGBD的稠密重建大同小异,而且很多代码通用。所以建议朋友们可以先看一下我之前的ORB-SLAM2稠密点云重建:RGBD室内。
这里先提一下总体思路。由于利用RGBD的框架去做,所以对于双目来说,最主要的就是得到其视差图,然后利用双目的其中1张(你也可以试试用两张,我选择左图)作为rgb图,将视差图得出左图深度信息。这样就通用起来了。也许你会担心ORB-SLAM2输出的位姿是中心点的位姿而不是左图的位姿,这样会不会有什么问题。我的目前的观点是认为左中心和中心相对固定,而且误差在大尺度SLAM下显得微乎其微,所以并没有考虑这个问题,如有误也请读者指正。LIBELAS的视频(需要其网站上才会有视频)展示了其完整的双目重建,但我也没找到其源码(有找到的同学务必告诉我啊)。而且其视频效果我不知道是否有人工处理,或挑选了比较好看的部分。(哈哈,这么猜测有些小气,但也并非不合理。谁让他不开源呢?没有开源精神的世界就是这么讨人厌)。不过比较好的是,LIBELAS提供并开源了双目获得深度的工具elas,我们就利用它生成视差图,然后在代码中从视差图得出左图深度信息。
好了,废话就这么多,下面开始。
步骤0:准备工作之位姿文件
与ORB-SLAM2的git主页的双目例子一样,我选择KITTI的灰度图数据集中的00,运行ORB-SLAM2,会生成CameraTrajectory.txt。这是每帧的相机位姿。不知道为什么ORB-SLAM2没有写双目例子的关键帧输出文件。我目前也懒得管或写,就干脆直接用这个每帧文件。我复制数据集和每帧文件到Win下,D盘SLAM文件夹,然后重命名每帧文件为StereoTraj.txt。正常的话StereoTraj.txt应该有4541行。
步骤1:准备工作之为LIBELAS转化pgm
由于LIBELAS提供的工具elas只能处理pgm(我也懒得去改。。。),所以我先在Ubuntu下利用ImageMagick把数据集的png全转化为了pgm(实在找不到其他靠谱方法)。我在00文件夹下新建文件夹L,存放image_0中左图png转化出来的pgm;又新建了文件夹R,同理。
步骤2:改写,编译生成elas工具,使用elas生成视差图
首先下载elas(也就是页面下面的LIBELAS),然后使用CMake-gui工具生成了VS2017的项目。(怎么使用CMake可视化工具我就不赘述了,百度)。由于elas是命令台工具(就是你要进入cmd打命令和参数的),而且懒得写DOS脚本,干脆进入项目,添加一个参数,在第一个if后面:
else if (argc == 2 && !strcmp(argv[1], "xc0")) {
string mainPath = "D:\\SLAM\\data_odometry_gray\\dataset\\sequences\\00";
int n = 4541;
for (int i = 0; i < n; i++) {
char s[7];
sprintf(s, "%06d", i);
string tl = mainPath + "\\L\\" + s + "l.pgm", tr = mainPath + "\\R\\" + s + "r.pgm";
process(tl.c_str(), tr.c_str());
cout << "... done!" << endl;
}
}
然后编译生成elas.exe,cmd下直接elas xc0,就会在L,R文件夹下生成对应的视差图了。
步骤3:声明主函数JoinPCStereo,新建双目参数文件,添加双目参数类
与之前RGBD的JoinPC类似,不再赘述。使用:
JoinPCStereo("D:\\SLAM\\StereoTraj.txt", "D:\\SLAM\\data_odometry_gray\\dataset\\sequences\\00");
声明:
void JoinPCStereo(string camTransFile, string dataMainPath) {
ParameterReader pd("StereoParameters.txt");
// 相机内参
STEREO_CAMERA_PARAMETERS camera;
camera.fx = atof(pd.getData("camera.fx").c_str());
camera.fy = atof(pd.getData("camera.fy").c_str());
camera.cx = atof(pd.getData("camera.cx").c_str());
camera.cy = atof(pd.getData("camera.cy").c_str());
camera.baseline = atof(pd.getData("camera.baseline").c_str());
camera.inx = atof(pd.getData("camera.inx").c_str());
camera.iny = atof(pd.getData("camera.iny").c_str());
camera.outx = atof(pd.getData("camera.outx").c_str());
camera.outy = atof(pd.getData("camera.outy").c_str());
...
其中,StereoParameters.txt是00数据集相机的参数:
camera.fx=718.856;
camera.fy=718.856;
camera.cx=607.1928;
camera.cy=185.2157;
camera.baseline=0.3861448;
camera.inx=1241;
camera.iny=376;
camera.outx=640;
camera.outy=480;
STEREO_CAMERA_PARAMETERS类型用来保存双目的参数,在高博的slamBase.h中添加:
struct STEREO_CAMERA_PARAMETERS
{
double fx, fy, cx, cy, baseline, inx, iny, outx, outy;
};
好了,考虑到篇幅,先就到这里。